2015-01-23 8 views
11

Mi stavo chiedendo se qualcuno ha il karma grunt per eseguire solo una specifica che viene modificata di guardia. Questa è la mia configurazione qui sotto. Il problema è che la riga grunt.config ('karma.unit.options.files', filepath); non sembra che stia facendo nulla visto che tutte le specifiche continuano a funzionare, tuttavia foo ottiene l'output prima del karma: unit: run viene licenziato.Ottenere karma grunt per eseguire un test di unità

grunt.initConfig({ 
    karma: { 
     unit: { 
      configFile: 'karma.conf.js', 
      background: true, 
      singleRun: false, 
      options: { 
       files: allFilesArray 
      } 
     } 
    }, 
    watch: { 
     options: { 
      spawn: false, 
      livereload: true 
     }, 
     karma: { 
      files: ['js/spec/**/*.spec.js', 'js/src/**/*.js'], 
      tasks: ['karma:unit:run'] 
     } 
    } 
}) 

grunt.event.on('watch', function (action, filepath){ 
    console.log('foo'); 
    grunt.config('karma.unit.options.files', filepath); 
}); 

C'è qualcuno là fuori che ha raggiunto esecuzione uno spec nel terminale sul cambiamento di file? Abbiamo migliaia di test, quindi sta iniziando a rallentare.

Grazie, Alex

+0

problema Karma correlati: https://github.com/karma-runner/karma/issues/1507 # issuecomment-320383049 – Stefan

+0

Domanda correlata a una soluzione per Gulp: https://stackoverflow.com/questions/26552729/karma-run-single-test/45350941#45350941 – Stefan

risposta

7

Ho ottenuto questo per funzionare. Fondamentalmente, si usa watch con un gestore di eventi per modificare dinamicamente la configurazione karma ogni volta che un file cambia. Ecco il rundown:

La mia configurazione di Grunt ha due compiti karma: "tutti" e "uno". "all" li esegue tutti e "one" esegue solo un singolo file che non conosce in anticipo.

grunt.initConfig({ 
    // ... 
    karma: { 
    all: { 
     configFile: 'karma.conf.js', 
     browsers: ['PhantomJS'], 
     singleRun: true, 
     options: { 
     files: [ 
      'bower_components/jquery/dist/jquery.js', // dependencies 
      'src/js/**/*.js', // js source files 
      'src/js/**/*.spec.js' // unit test files 
     ] 
     } 
    }, 
    one: { 
     configFile: 'karma.conf.js', 
     browsers: ['PhantomJS'], 
     singleRun: true, 
     files: [ 
     {src: 'bower_components/jquery/dist/jquery.js'}, // dependencies 
     {src: ['src/js/**/*.js','!src/js/**/*.spec.js']} // source files 
     // (exclude the unit test files) 
     // watchEventListener will add the unit test file to run 
     ] 
    } 
    }, 
    // ... 
}); 

E poi nel mio gruntfile, aggiungo un listener per eventi di orologi. Questo ascoltatore aggiorna il karma: un compito e aggiunge il file di test unitario. Manteniamo una copia dell'array di file originale, altrimenti le nostre aggiunte continuerebbero ad accumularsi nel corso della durata dell'attività di controllo.

// when a unit test changes, execute only it 
var original_karmaOne_files = grunt.config.get('karma.one.files'); // keep the original files array 
grunt.event.on('watch', function watchEventListener(action, filepath, target){ 

    // this handler handles ALL watch changes. Try to filter out ones from other watch tasks 
    if (target == 'js_spec') handleJSHintSpec(); 

    // --------------------- 
    function handleJSHintSpec() { 
    if (action == 'deleted') return; // we don't need to run any tests when a file is deleted 
    // this will probably fail if a watch task is triggered with multiple files at once 
    // dynamically change the config 
    grunt.config.set('karma.one.files', [].concat(original_karmaOne_files, [{src: filepath}])); 
    } 
}); 

E qui è compito orologio di mio gruntfile:

watch: { 
    // ... 
    // when js spec files change, 
    // lint them 
    // run unit tests 
    js_spec: { 
    options: { 
     interrupt: true 
    }, 
    files: 'src/js/**/*.spec.js', 
    tasks: ['jshint:js_spec', 'karma:one'] 
    }, 
    // ... 
} 

Il mio file karma.conf.js è piuttosto di default, ma la sua vasta gamma di file è vuoto. In realtà, ho commentato, quindi la proprietà non è definita.

// list of files/patterns to load in the browser 
//files: [], // specified in the gruntfile 
+2

Inoltre, ho scoperto che l'array di file deve contiene oggetti con una proprietà 'src' - no t stringhe di filepath semplici, altrimenti non è riuscita. –

+0

Inoltre, ogni obiettivo di controllo deve avere l'opzione 'spawn' impostata su false, altrimenti' grunt.config.set() 'non avrà alcun effetto. –

+1

Grazie per il fantastico punto di partenza e i commenti. Tuttavia mi ci è voluto del tempo per farlo funzionare. Ho aggiunto il mio risultato Gruntfile.js come risposta sotto. – Stefan

2

TL; DR: Usa karma: unità ovunque anziché karma: unità: corri e usa grunt.event.on ('watch', function() {}); per modificare la configurazione karma per includere solo i file di test che si desidera eseguire.

Ho questo funzionamento, ma potrebbe non essere quello che vuoi. Sto riavviando il server ogni volta che salvi un file. Un'ulteriore spiegazione è qui sotto. Ecco alcuni dei config:

watch: { 
     tests: { 
      files: 'tests/**/*.js', 
      tasks: ['karma:unit'] 
     }, 
     tsChanged: { 
      files: config.tsFiles, 
      tasks: [ 
       'ts', 
       'karma:unit' 
      ] 
     } 
    } 

    grunt.event.on('watch', function(action, filepath){ 
     grunt.config(['karma', 'unit', 'files'], [{ 
      src: [ 
       path/to/your/source/files, 
       path/to/your/test/file, 
      ] 
     }]); 
    }); 

Mi sembra che il karma carica tutti i file app ei file di prova nel browser ogni volta che si avvia il server. Nel tuo caso, sarebbe quando inserisci "grunt karma: unit: start watch" nella riga di comando. Quindi, qui ho usato "grunt watch" e appena aggiunto un "karma: unit" al processo. Quindi ho catturato l'evento di salvataggio e aggiornato la configurazione karma prima di avviare il server.

Spero che questo aiuti.

1

Usando una combinazione di yargs e alcuni runtime-magia, faccio questo:

var argv = require('yargs') 
    .default('t', '*.js') 
    .alias('t', 'tests') 
    .describe('t', 'A file or file pattern of the test files to run, relative to the test/unit dir') 
    .help('?') 
    .alias('?', 'help') 
    .argv; 

var filesToLoad = ['src/**/*.js', 'test/unit/helpers/*.js']; 
filesToLoad.push(path.join('test/unit/**', argv.t)); 

gulp.task('tdd', function (done) { 
    karma.start({ 
     configFile: __dirname + '/../../karma.conf.js', 
     jspm: { 
      loadFiles: filesToLoad, 
     } 
    }, function(e) { 
     done(); 
    }); 
}); 

che prende un modello di file di test/path come argomento di inghiottire e di carichi che a preferenza di tutto i file.

0

Sulla base della risposta di Matthias e dei commenti il ​​mio Grundfile.js è:

module.exports = function (grunt) { 

    grunt.initConfig({ 
     pkg: grunt.file.readJSON('package.json'), 
     karma: { 
      all: { 
       configFile: 'karma.conf.js',    
       background: true, 
       files: [ 
        { src: './Leen.Managementsystem/bower_components/jquery/dist/jquery.js' }, 
        { src: './Leen.Managementsystem/bower_components/globalize/lib/globalize.js' }, 
        { src: './Leen.Managementsystem/bower_components/**/*.js', included: false }, 
        { src: './Leen.Managementsystem.Tests/App/test/mockFactory.js', included: false }, 
        { src: './Leen.Managementsystem/App/**/*.js', included: false }, 
        { src: './Leen.Managementsystem.Tests/App/test/*.js', included: false }, 
        { src: './Leen.Managementsystem.Tests/App/**/*.spec.js', included: false }, 
        { src: './Leen.Managementsystem.Tests/App/test-main.js' } 
       ] 
      }, 
      one: { 
       configFile: 'karma.conf.js',    
       files: [ 
        { src: './Leen.Managementsystem/bower_components/jquery/dist/jquery.js' }, 
        { src: './Leen.Managementsystem/bower_components/globalize/lib/globalize.js' }, 
        { src: './Leen.Managementsystem/bower_components/**/*.js', included: false }, 
        { src: './Leen.Managementsystem.Tests/App/test/mockFactory.js', included: false }, 
        { src: './Leen.Managementsystem/App/**/*.js', included: false }, 
        { src: './Leen.Managementsystem.Tests/App/test/*.js', included: false },   
        // (do not inlcude the *.spec.js files here! The watch event listener will add the single spec file to run) 
        { src: './Leen.Managementsystem.Tests/App/test-main.js' } 
       ] 
      } 
     }, 
     watch: {   
      spec_js: { 
       options: { 
        interrupt: true, 
        spawn: false 
       }, 
       files: 'Leen.Managementsystem.Tests/App/**/*.spec.js', 
       tasks: ['karma:one:start']    
      } 
     } 
    }); 

    var originalKarmaOneFiles = grunt.config.get('karma.one.files'); // keep the original files array 

    grunt.event.on('watch', function watchEventListener(action, filepath, target) { 

     if (target === 'spec_js') { 
      handleChangedSpecFile(); 
     } 

     function handleChangedSpecFile() { 
      if (action === 'deleted') { 
       return; 
      }   

      var testFilePath = "./" + filepath.replace(/\\/g, "/"); 

      grunt.log.writeln(['Running single karma test for: ' + testFilePath]); 
      var updatedFiles = originalKarmaOneFiles.concat([{ src: testFilePath, included: false }]); 

      grunt.config.set('karma.one.files', updatedFiles); 
     } 
    }); 


    grunt.loadNpmTasks('grunt-karma'); 
    grunt.loadNpmTasks('grunt-contrib-watch'); 

    grunt.registerTask('default', ['karma:all','watch']); 

}; 

karma.conf.js:

module.exports = function(config) { 
    config.set({ 

     // base path, that will be used to resolve files and exclude 
     basePath: '', //the solution root path, e.g. D:\Energienetzwerke\trunk 


     // frameworks to use 
     frameworks: ['jasmine', 'requirejs'], 

     // list of files/patterns to load in the browser 
     files: [ 
     './Leen.Managementsystem/bower_components/jquery/dist/jquery.js', 
     './Leen.Managementsystem/bower_components/globalize/lib/globalize.js', 
     { pattern: './Leen.Managementsystem/bower_components/**/*.js', included: false }, 
     { pattern: './Leen.Managementsystem.Tests/App/test/mockFactory.js', included: false }, 
     { pattern: './Leen.Managementsystem/App/**/*.js', included: false }, 
     { pattern: './Leen.Managementsystem.Tests/App/test/*.js', included: false}, 
     { pattern: './Leen.Managementsystem.Tests/App/**/*.spec.js', included: false}, 
     './Leen.Managementsystem.Tests/App/test-main.js' 
     ], 


     // list of files to exclude 
     exclude: [ 
     './Leen.Managementsystem/App/main.js' 
     ], 


     // test results reporter to use 
     // possible values: 'dots', 'progress', 'junit', 'growl', 'coverage' 
     reporters: ['progress', 'coverage', 'notify', 'htmlDetailed', 'xml'], 



     coverageReporter: { 
     dir: './Leen.Managementsystem.Tests/testCoverage', 
     reporters: [ 
      { type: 'html',subdir: 'html'}, 
      { type: 'cobertura',subdir: 'xml', file: 'coverage.xml' }, 
      { type: 'lcov', subdir: 'lcov' }, 
      { type: 'text-summary' } 
      ] 
     }, 


     notifyReporter: { 
     reportEachFailure: true, // Default: false, Will notify on every failed spec 
     reportSuccess: false // Default: true, Will notify when a suite was successful 
     }, 

     htmlDetailed: { 
     autoReload: true, 
     dir: './Leen.Managementsystem.Tests/testResults' 

     }, 
    preprocessors: { 
     // source files, that you wanna generate coverage for 
     // do not include tests or libraries 
     // (these files will be instrumented by Istanbul) 
     './Leen.Managementsystem/App/**/*.js': ['coverage'] 
    }, 


    // web server port 
    port: 9876, 


    // enable/disable colors in the output (reporters and logs) 
    colors: true, 


    // level of logging 
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG 
    logLevel: config.LOG_INFO, 


    // enable/disable watching file and executing tests whenever any file changes 
    autoWatch: false, //watching is done by Gruntfile.js to only execute changed tests 
    usePolling: true, 

    // Start these browsers, currently available: 
    // - Chrome 
    // - ChromeCanary 
    // - Firefox 
    // - Opera 
    // - Safari (only Mac) 
    // - PhantomJS 
    // - IE (only Windows) 
    browsers: ['Chrome_With_Saved_DevTools_Settings'], 

    customLaunchers: { 
     Chrome_With_Saved_DevTools_Settings: { 
      base: 'Chrome', 
      chromeDataDir: './.chrome'    
     } 
    }, 


    // If browser does not capture in given timeout [ms], kill it 
    captureTimeout: 60000, 


    // Continuous Integration mode 
    // if true, it capture browsers, run tests and exit 
    singleRun: true 
    }); 
}; 

package.json:

{ 
    "name": "solution", 
    "version": "1.0.0", 
    "description": "contains packages that are needed for running karma", 
    "main": "./Leen.Managementsystem.Tests/App/test-main.js", 
    "dependencies": { 
    "grunt": "1.0.1", 
    "grunt-cli": "1.2.0", 
    "grunt-contrib-watch": "1.0.0", 
    "grunt-karma": "2.0.0", 
    "jasmine-core": "2.6.4", 
    "karma": "1.7.0", 
    "karma-chrome-launcher": "2.2.0", 
    "karma-cli": "1.0.1", 
    "karma-coverage": "1.1.1", 
    "karma-firefox-launcher": "1.0.1", 
    "karma-html-detailed-reporter": "1.1.20", 
    "karma-ie-launcher": "1.0.0", 
    "karma-jasmine": "1.1.0", 
    "karma-notify-reporter": "1.0.1", 
    "karma-phantomjs-launcher": "1.0.4", 
    "karma-requirejs": "1.1.0", 
    "karma-xml-reporter": "0.1.4", 
    "requirejs": "2.3.4" 
    }, 
    "devDependencies": {}, 
    "scripts": { 
    "test": "karma run" 
    }, 
    "author": "LEEN", 
    "license": "private" 
}