【问题标题】:Getting grunt karma to run one unit test让 grunt karma 运行一个单元测试
【发布时间】:2015-01-23 11:04:06
【问题描述】:

我想知道是否有人得到了 grunt karma 来运行一个在手表上更改的规范。这是我下面的配置。问题是行 grunt.config('karma.unit.options.files', filepath);似乎没有做任何事情,因为所有规范仍在运行,但是 foo 在 karma:unit:run 被触发之前确实得到了输出。

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);
});

有没有人在文件更改时在终端中运行一个规范?我们有数千个测试,所以它开始变慢了。

谢谢, 亚历克斯

【问题讨论】:

标签: gruntjs karma-runner


【解决方案1】:

我得到了这个工作。基本上,只要文件更改,您就可以使用带有事件处理程序的 watch 来动态更改 karma 配置。这是纲要:

我的 Grunt 配置有两个 karma 任务:“all”和“one”。 “all”运行所有文件,“one”只运行一个事先不知道的文件。

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
      ]
    }
  },
  // ...
});

然后在我的 gruntfile 中,我添加了一个监听事件的监听器。此侦听器更新 karma:one 任务并添加单元测试文件。我们保留原始文件数组的副本,否则我们的添加将在监视任务的整个生命周期中持续存在并累积。

// 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}]));
  }
});

这是我的 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']
  },
  // ...
}

我的karma.conf.js 文件是默认的,但它的文件数组是空的。其实我注释掉了,所以属性是未定义的。

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

【讨论】:

  • 另外,我发现文件数组必须包含具有src 属性的对象——而不是简单的文件路径字符串,否则它会失败。
  • 另外,每个监视目标必须将spawn 选项设置为false,否则grunt.config.set() 将无效。
  • 感谢您的出色起点和 cmets。尽管如此,我还是花了一些时间让它工作。我在下面添加了生成的 Gruntfile.js 作为答案。
  • 当我的 karm.conf.js 有 files 数组并且我不允许更改它时,如何修改它以便它工作?
【解决方案2】:

TL; DR:到处使用 karma:unit 而不是 karma:unit:run 并使用 grunt.event.on('watch', function(){});编辑业力配置以仅包含您要运行的测试文件。

我有这个工作,但它可能不是你想要的。每次保存文件时,我都会重新启动服务器。进一步的解释如下。这是一些配置:

    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,
            ]
        }]);
    });

在我看来,karma 在启动服务器时会将所有应用程序文件和测试文件加载到浏览器中。在您的情况下,那将是您在命令行中输入“grunt karma:unit:start watch”。所以在这里,我使用了“grunt watch”,只是在流程中添加了一个“karma:unit”。然后我在启动服务器之前捕获了保存事件并更新了业力配置。

希望这会有所帮助。

【讨论】:

    【解决方案3】:

    结合使用 yargs 和一些运行时魔法,我这样做了:

    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();
        });
    });
    

    它将测试文件/路径模式作为 gulp 的参数并优先于 所有文件加载它。

    【讨论】:

      【解决方案4】:

      根据 Matthias 和 cmets 的回答,我的 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"
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多