【问题标题】:How to run unit tests in mtime order with Grunt and Mocha如何使用 Grunt 和 Mocha 以 mtime 顺序运行单元测试
【发布时间】:2018-03-24 22:13:40
【问题描述】:

所以当您执行 TDD 时,您是否会等待它运行所有测试,直到您正在处理的测试?这需要太多时间。当我赶时间时,我将测试文件重命名为 aaaaaaaaaaaaaaa_testsomething.test.js 之类的文件,这样它会先运行,然后我会尽快看到错误。

我不喜欢这种方法,我确信有解决方案,但我找不到。那么使用 Mocha 以 mtime 顺序运行单元测试的最简单方法是什么?有 -sort 选项,但它仅按名称对文件进行排序。如何按修改时间对它们进行排序?

这是我的 Gruntfile.js:

module.exports = function(grunt) {

  grunt.initConfig({
    watch: {
      tests: {
        files: ['**/*.js', '!**/node_modules/**'],
        tasks: ['mochacli:local']
      }
    },
    mochacli: {
      options: {
        require: ['assert'],
        reporter: 'spec',
        bail: true,
        timeout: 6000,
        sort: true,
        files: ['tests/*.js']
      },
      local: {
        timeout: 25000
      }
    }
  });

  
  grunt.loadNpmTasks('grunt-mocha-cli');
  grunt.loadNpmTasks('grunt-contrib-watch');

  grunt.registerTask('test', ['mochacli:local']);
  grunt.registerTask('livetests', [ 'watch:tests']);

};

注意:它不是重复的。我不想每次保存源代码文件时都编辑我的测试或 Gruntfile.js。我在问如何修改 Grunt 任务,以便它首先从上次修改的 *.test.js 文件运行测试。如标题中所述,按 mtime 对单元测试进行排序。

简单场景:我在编辑器中打开 test1.test.js,更改它,按 Ctrl+B,它会从 test1.test.js 然后 test4.test.js 运行单元测试。我打开 test4.test.js,按 Ctrl+S、Ctrl+B 并从 test4.test.js 然后 test1.test.js 运行测试

我正在考虑一些 Grunt 插件来首先对文件进行排序,所以我可以将它的结果放在带有 grunt.config.set('mochacli.options.files', 'tests/recent.js,tests/older.js', ....); 的 'tests/*.js' 中,但我在那里找不到任何可以用作中间件的东西,不想发明自行车,因为我确信已经实现了一些东西。

【问题讨论】:

  • 您实际上并没有阅读其他问题的答案。例如,使用 Mocha 的 grep 选项不需要您编辑任何内容
  • 路易斯,我做到了。我不想进行一项测试。我想更改执行顺序。而且我不想每次运行测试时都修改 Gruntfile.js 本身。它在 Ctrl+B 上运行单元测试,从我提供的 Gruntfile.js 执行 grunt 测试文件。
  • 使用 grep 选项要求您至少编辑 grep 选项。它需要您切换到 CLI。记住测试名称以将其放入 grep。我希望它运行按 *.test.js 文件的 mtime 排序的测试。很简单。
  • 正如名称grep 所暗示的,它进行模式匹配。所以你可以用它运行多个测试。它不需要你像 Grunt 那样“切换到 CLI”。
  • 路易斯。你能再读一遍我的问题吗?我想运行所有测试。没有一个,没有被 grep 过滤。我想运行所有测试,但最近的一个 - 首先。

标签: javascript unit-testing gruntjs mocha.js grunt-contrib-watch


【解决方案1】:

不想发明自行车,因为我确信已经实现了一些东西。

...有时你必须骑自行车;)


解决方案

这可以通过在您的Gruntfile.js 中注册一个中间custom-task 来动态执行以下操作来实现:

  1. 使用 grunt.file.expand 和适当的 globbing 模式获取所有单元测试文件 (.js) 的文件路径。
  2. 按文件mtime/modified-date 对每个匹配的文件路径进行排序。
  3. 使用grunt.config 配置具有按时间顺序排列的文件路径的mochacli.options.file 数组
  4. 使用grunt.task.run运行mochacli任务中定义的localTarget

Gruntfile.js

如下配置您的Gruntfile.js

module.exports = function(grunt) {

  // Additional built-in node module.
  var statSync = require('fs').statSync;

  grunt.initConfig({
    watch: {
      tests: {
        files: ['**/*.js', '!**/node_modules/**', '!Gruntfile.js'],
        tasks: ['runMochaTests']
      }
    },
    mochacli: {
      options: {
        require: ['assert'],
        reporter: 'spec',
        bail: true,
        timeout: 6000,
        files: [] // <-- Intentionally empty, to be generated dynamically.
      },
      local: {
        timeout: 25000
      }
    }
  });

  grunt.loadNpmTasks('grunt-mocha-cli');
  grunt.loadNpmTasks('grunt-contrib-watch');

  /**
   * Custom task to dynamically configure the `mochacli.options.files` Array.
   * All filepaths that match the given globbing pattern(s), which is specified
   # via the `grunt.file.expand` method, will be sorted chronologically via each
   * file(s) latest modified date (i.e. mtime).
   */
  grunt.registerTask('runMochaTests', function configMochaTask() {
    var sortedPaths = grunt.file.expand({ filter: 'isFile' }, 'tests/**/*.js')
      .map(function(filePath) {
        return {
          fpath: filePath,
          modtime: statSync(filePath).mtime.getTime()
        }
      })
      .sort(function (a, b) {
        return a.modtime - b.modtime;
      })
      .map(function (info) {
        return info.fpath;
      })
      .reverse();

    grunt.config('mochacli.options.files', sortedPaths);
    grunt.task.run(['mochacli:local']);
  });

  grunt.registerTask('test', ['runMochaTests']);
  grunt.registerTask('livetests', [ 'watch:tests']);

};

附加说明

使用上面的配置。通过 CLI 运行 $ grunt livetests,然后保存修改后的测试文件将导致 Mocha 根据文件上次修改日期按时间顺序运行每个测试文件(即最近修改的文件将首先运行并且最后修改的文件将最后运行)。同样的逻辑也适用于运行$ grunt test

但是,如果您希望 Mocha 首先运行最近修改的文件,然后按正常顺序(即按名称)运行其他文件,然后在 @987654338 中自定义 runMochaTests 任务上面的@应该替换为以下逻辑:

/**
 * Custom task to dynamically configure the `mochacli.options.files` Array.
 * The filepaths that match the given globbing pattern(s), which is specified
 # via the `grunt.file.expand` method, will be in normal sort order (by name).
 * However, the most recently modified file will be repositioned as the first
 * item in the `filePaths` Array (0-index position).
 */
grunt.registerTask('runMochaTests', function configMochaTask() {
  var filePaths = grunt.file.expand({ filter: 'isFile' }, 'tests/**/*.js')
    .map(function(filePath) {
      return filePath
    });

  var latestModifiedFilePath = filePaths.map(function(filePath) {
      return {
        fpath: filePath,
        modtime: statSync(filePath).mtime.getTime()
      }
    })
    .sort(function (a, b) {
      return a.modtime - b.modtime;
    })
    .map(function (info) {
      return info.fpath;
    })
    .reverse()[0];

  filePaths.splice(filePaths.indexOf(latestModifiedFilePath), 1);
  filePaths.unshift(latestModifiedFilePath);

  grunt.config('mochacli.options.files', filePaths);
  grunt.task.run(['mochacli:local']);
});

【讨论】:

  • 我确信我为此感谢了你,但在这里看不到 cmets。多次检查你的答案,非常感谢,@RobC 你太棒了!
  • 不客气@EvgeniyKiselyov - 很高兴它有帮助:) 你之前可能确实感谢过我,但是 cmets 经常被删除。
【解决方案2】:

如果您使用的是 mocha,您可以在您感兴趣的测试上设置 .only:

describe(function () {
  // these tests will be skipped
});
describe.only(function () {
  // these tests will run
})

【讨论】:

  • 我不想对测试进行重大更改。我希望 mocha 首先运行最近编辑的 *.test.js 文件。只需按 mtime 对 .test.js 文件进行排序,而不是按名称。
  • 另外,我不希望它只运行单个文件。我只想更改顺序并运行所有测试,但最近的测试 - 首先。
  • 我不确定我是否理解以这种方式控制测试执行顺序的动机。我最初认为您对在开发功能时监控特定测试或一组测试感兴趣。不是这样吗?
  • 是的。但它是开发的初始阶段,几乎每个测试都与许多事情有关。我想尽快看到我目前正在研究的单位的结果。但我也希望它继续在后台检查所有内容。如果其他测试有错误 - 我想快速切换到它们,比如在那里按 Ctrl+S,向其中添加一些控制代码。
  • 据我所知,没有内置的方法可以按照您正在寻找的顺序运行测试。通常我在初始开发期间我关心的测试上设置 .only 。一旦我让他们通过,我删除 .only 并再次运行所有测试。
猜你喜欢
  • 2016-07-17
  • 2023-03-30
  • 2015-11-24
  • 2012-05-19
  • 1970-01-01
  • 2012-06-05
  • 1970-01-01
  • 2016-03-09
  • 1970-01-01
相关资源
最近更新 更多