如何使用 G运行t 和 Mocha 按 mtime 顺序 运行 进行单元测试
How to run unit tests in mtime order with Grunt and Mocha
因此,当您进行 TDD 时,是否会等 运行 所有测试直到您正在处理的测试?这需要太多时间。当我匆忙时,我将测试文件重命名为 aaaaaaaaaaaaaaaa_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。我在询问如何修改 G运行t 任务,以便它首先从上次修改的 *.test.js 文件进行 运行s 测试。按时间排序单元测试,如标题所述。
简单场景:我在编辑器中打开 test1.test.js,更改它,按 Ctrl+B,它从 test1.运行s 单元测试。test.js 然后是 test4.test.js。我打开 test4.test.js,按 Ctrl+S、Ctrl+B,它从 test4.test.js 然后是 test1.test.js
运行s 测试
我正在考虑一些 G运行t 插件来首先对文件进行排序,这样我就可以把它的结果放在那里而不是 'tests/*.js' 和 grunt.config.set('mochacli.options.files', 'tests/recent.js,tests/older.js', ....);
但我找不到我可以在那里用作中间件的任何东西,不想发明 bycicle,因为我确定已经实现了一些东西。
如果您使用的是 mocha,您可以在您感兴趣的测试中设置 .only:
describe(function () {
// these tests will be skipped
});
describe.only(function () {
// these tests will run
})
don't want to invent bicycle as I'm sure there's something for this implemented already.
...有时你必须骑自行车;)
解决方案
这可以通过在您的 Gruntfile.js
中注册中间体 custom-task 来动态执行以下操作来实现:
- 使用 grunt.file.expand with the appropriate globbing 模式获取所有单元测试文件 (
.js
) 的文件路径。
- 按文件 mtime/修改日期对每个匹配的文件路径进行排序。
- 使用 grunt.config
使用按时间顺序排序的文件路径配置 mochacli.options.file
数组
- 运行
local
Target defined in the mochacli
Task using grunt.task.run
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']);
};
补充说明
使用上面的配置。 运行ning $ grunt livetests
通过您的 CLI,然后随后保存修改后的测试文件将导致 Mocha 到 运行 每个测试文件按时间顺序排列文件上次修改日期(即最近修改的文件将 运行 放在最前面,最后修改的文件将 运行 最后)。同样的逻辑也适用于运行宁$ grunt test
。
但是,如果您希望 Mocha 先 运行 最近修改的文件,然后 运行 其他文件按正常顺序排列(即按名称), 那么上面 Gruntfile.js
中的自定义 runMochaTests
Task 应该替换成下面的逻辑:
/**
* 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']);
});
因此,当您进行 TDD 时,是否会等 运行 所有测试直到您正在处理的测试?这需要太多时间。当我匆忙时,我将测试文件重命名为 aaaaaaaaaaaaaaaa_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。我在询问如何修改 G运行t 任务,以便它首先从上次修改的 *.test.js 文件进行 运行s 测试。按时间排序单元测试,如标题所述。
简单场景:我在编辑器中打开 test1.test.js,更改它,按 Ctrl+B,它从 test1.运行s 单元测试。test.js 然后是 test4.test.js。我打开 test4.test.js,按 Ctrl+S、Ctrl+B,它从 test4.test.js 然后是 test1.test.js
运行s 测试我正在考虑一些 G运行t 插件来首先对文件进行排序,这样我就可以把它的结果放在那里而不是 'tests/*.js' 和 grunt.config.set('mochacli.options.files', 'tests/recent.js,tests/older.js', ....);
但我找不到我可以在那里用作中间件的任何东西,不想发明 bycicle,因为我确定已经实现了一些东西。
如果您使用的是 mocha,您可以在您感兴趣的测试中设置 .only:
describe(function () {
// these tests will be skipped
});
describe.only(function () {
// these tests will run
})
don't want to invent bicycle as I'm sure there's something for this implemented already.
...有时你必须骑自行车;)
解决方案
这可以通过在您的 Gruntfile.js
中注册中间体 custom-task 来动态执行以下操作来实现:
- 使用 grunt.file.expand with the appropriate globbing 模式获取所有单元测试文件 (
.js
) 的文件路径。 - 按文件 mtime/修改日期对每个匹配的文件路径进行排序。
- 使用 grunt.config 使用按时间顺序排序的文件路径配置
- 运行
local
Target defined in themochacli
Task using grunt.task.run
mochacli.options.file
数组
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']);
};
补充说明
使用上面的配置。 运行ning $ grunt livetests
通过您的 CLI,然后随后保存修改后的测试文件将导致 Mocha 到 运行 每个测试文件按时间顺序排列文件上次修改日期(即最近修改的文件将 运行 放在最前面,最后修改的文件将 运行 最后)。同样的逻辑也适用于运行宁$ grunt test
。
但是,如果您希望 Mocha 先 运行 最近修改的文件,然后 运行 其他文件按正常顺序排列(即按名称), 那么上面 Gruntfile.js
中的自定义 runMochaTests
Task 应该替换成下面的逻辑:
/**
* 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']);
});