如何在更新时自动 运行 单个 phpunit 测试?
How to automatically run a single phpunit test when it is updated?
我正在使用 Laravel 5.3,不幸的是,当您 运行 gulp tdd
时,对 1 个文件的更改 运行 整个测试套件现在需要将近 2 分钟。参考,我开始使用G运行t到运行特定文件更改时的特定测试。下面的示例 G运行t 文件:
Gruntfile.js:
var phpunit = 'vendor/bin/phpunit ';
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
watch: {
HomeSrc: {
files: [
'app/Http/**/HomeController.php',
'resources/views/home/**/*.php'
],
tasks: ['HomeTests']
},
shell: {
HomeTests: { command: phpunit + 'tests/Home' },
}
});
但是,现在我的 G运行t 文件变得很长,我想 运行 更改后的特定测试文件。
问题
- 有没有更有效的方法来做到这一点? (更好地组织 G运行 文件或改用 Gulp)
- 我如何运行 更改文件后进行特定测试?
示例:
当tests/Home/IndexTest.php
改变时,自动运行vendor/bin/phpunit tests/Home/IndexTest.php
使用命令行
转到您的项目文件夹,然后在合适的命令下运行
运行 所有测试 class 个文件
phpunit
运行具体测试class文件
phpunit ./tests/ExampleTest.php
或
运行 来自 class 文件 运行 命令下的特定测试用例
phpunit --filter testBasicExample ./tests/ExampleTest.php
好的,要处理这个问题,您需要捕获匹配的文件名并动态设置一个变量以用作单元测试文件。这应该涵盖所有基本映射,其中测试 class 名称与其所在的文件名完全相同,并且支持名称空间,因此并非所有具有相同 class 名称的测试文件都会被选择过滤器。
示例:
grunt.initConfig({
// .. snipped ..
unitTestFile: 'to_be_replaced',
watch: {
php: {
files: ["tests/**/*.php"],
tasks: ["shell:unitTest"],
options: {
spawn: false
}
}
},
shell: {
unitTest: {
command: "phpunit --filter <%= unitTestFile %>"
}
}
grunt.loadNpmTasks('grunt-shell');
grunt.event.on('watch', function (action, filepath) {
if (grunt.file.isMatch(grunt.config('watch.php.files'), filepath)) {
var testFile = filepath.replace(/\/g, '\\');
grunt.config('unitTestFile', testFile.replace(/.php/, ''));
}
});
};
因此,如果更改了名为 tests\unit\ApplicationTest.php
且位于 tests\unit
命名空间内的文件,现在将 运行 作为测试。结果命令为:
phpunit --filter tests\unit\ApplicationTest // only runs in this namespace
您可以考虑以下解决方案:
- 利用外部
.json
,其中包含您打算观看的 files/paths 数组,最终 运行 作为单元测试。
- 为
watch
和 shell
任务动态生成 Targets。
(以上两点肯定有助于减少代码行数。)
下面的要点证明了这一点:
JSON
假设我们有一个名为 test-mappings.json
的文件,每个文件路径 (根据第 1 点) 指定如下,并与 [= 一起保存在项目根目录中17=]
[{
"file": "tests/testA.php"
},{
"file": "tests/testB.php"
},{
"file": "tests/testC.php"
},{
"file": "tests/testD.php"
}]
Gruntfile.js
使用一个Gruntfile.js
配置如下:
module.exports = function(grunt) {
'use strict';
var mapping = grunt.file.readJSON('test-mappings.json'),
watch = {},
shell = {};
// Dynamically create the targets for 'watch' and 'shell' tasks.
mapping.forEach(function(config, index) {
watch[index] = {
files: [config.file],
tasks: [index]
};
shell[index] = {
command: 'vendor/bin/phpunit ' + config.file
};
// Register the shell target
grunt.registerTask(index, ['shell:' + index ]);
});
grunt.initConfig({
watch: watch,
shell: shell
});
// Handy for dev - logs generated targets
//grunt.log.writeln(JSON.stringify(grunt.config(), null, 2));
require('load-grunt-tasks')(grunt);
grunt.registerTask('default', [
'watch'
]);
};
请注意,watch
和 shell
任务的每个目标都是根据 test-mappings.json
中指定的文件列表动态生成和配置的。
要查看自动生成目标的配置,您只需在 运行ning $ grunt
之前取消注释 grunt.log.writeln...
行,它将打印到控制台。
运行任务
- 通过 CLI 输入
$ grunt
。
- 对
test-mappings.json
中列出的文件之一进行编辑并保存。
watch
任务将 运行 相应的 shell
命令。
补充说明
目前,文件列在外部 .json
中,但它们可以驻留在 Gruntfile.js
中,如果愿意,可以分配给变量。
或者,可以使用适当的 globbing pattern(s) and modifying the gist above as necessary. In which case iterating over grunt.file.expand 获取文件,而不是当前的 mapping
数组。
以下 g运行t 插件用于上述要点:
更新:
下面的Gruntfile.js
是针对第1点前面提到的方法。 附加说明 节下的两个(即 Globbing 而不是外部 JSON 文件路径配置)。
module.exports = function(grunt) {
'use strict';
var tests = 'tests/**/*.php',
watch = {},
shell = {};
grunt.file.expand(tests).forEach(function(filepath, index) {
watch[index] = {
files: [filepath],
tasks: [index]
};
shell[index] = {
command: 'vendor/bin/phpunit ' + filepath
};
grunt.registerTask(index, ['shell:' + index]);
});
grunt.initConfig({
watch: watch,
shell: shell
});
require('load-grunt-tasks')(grunt);
grunt.registerTask('default', [
'watch'
]);
};
我正在使用 Laravel 5.3,不幸的是,当您 运行 gulp tdd
时,对 1 个文件的更改 运行 整个测试套件现在需要将近 2 分钟。参考
Gruntfile.js:
var phpunit = 'vendor/bin/phpunit ';
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
watch: {
HomeSrc: {
files: [
'app/Http/**/HomeController.php',
'resources/views/home/**/*.php'
],
tasks: ['HomeTests']
},
shell: {
HomeTests: { command: phpunit + 'tests/Home' },
}
});
但是,现在我的 G运行t 文件变得很长,我想 运行 更改后的特定测试文件。
问题
- 有没有更有效的方法来做到这一点? (更好地组织 G运行 文件或改用 Gulp)
- 我如何运行 更改文件后进行特定测试?
示例:
当tests/Home/IndexTest.php
改变时,自动运行vendor/bin/phpunit tests/Home/IndexTest.php
使用命令行
转到您的项目文件夹,然后在合适的命令下运行
运行 所有测试 class 个文件
phpunit
运行具体测试class文件
phpunit ./tests/ExampleTest.php
或
运行 来自 class 文件 运行 命令下的特定测试用例
phpunit --filter testBasicExample ./tests/ExampleTest.php
好的,要处理这个问题,您需要捕获匹配的文件名并动态设置一个变量以用作单元测试文件。这应该涵盖所有基本映射,其中测试 class 名称与其所在的文件名完全相同,并且支持名称空间,因此并非所有具有相同 class 名称的测试文件都会被选择过滤器。
示例:
grunt.initConfig({
// .. snipped ..
unitTestFile: 'to_be_replaced',
watch: {
php: {
files: ["tests/**/*.php"],
tasks: ["shell:unitTest"],
options: {
spawn: false
}
}
},
shell: {
unitTest: {
command: "phpunit --filter <%= unitTestFile %>"
}
}
grunt.loadNpmTasks('grunt-shell');
grunt.event.on('watch', function (action, filepath) {
if (grunt.file.isMatch(grunt.config('watch.php.files'), filepath)) {
var testFile = filepath.replace(/\/g, '\\');
grunt.config('unitTestFile', testFile.replace(/.php/, ''));
}
});
};
因此,如果更改了名为 tests\unit\ApplicationTest.php
且位于 tests\unit
命名空间内的文件,现在将 运行 作为测试。结果命令为:
phpunit --filter tests\unit\ApplicationTest // only runs in this namespace
您可以考虑以下解决方案:
- 利用外部
.json
,其中包含您打算观看的 files/paths 数组,最终 运行 作为单元测试。 - 为
watch
和shell
任务动态生成 Targets。
(以上两点肯定有助于减少代码行数。)
下面的要点证明了这一点:
JSON
假设我们有一个名为 test-mappings.json
的文件,每个文件路径 (根据第 1 点) 指定如下,并与 [= 一起保存在项目根目录中17=]
[{
"file": "tests/testA.php"
},{
"file": "tests/testB.php"
},{
"file": "tests/testC.php"
},{
"file": "tests/testD.php"
}]
Gruntfile.js
使用一个Gruntfile.js
配置如下:
module.exports = function(grunt) {
'use strict';
var mapping = grunt.file.readJSON('test-mappings.json'),
watch = {},
shell = {};
// Dynamically create the targets for 'watch' and 'shell' tasks.
mapping.forEach(function(config, index) {
watch[index] = {
files: [config.file],
tasks: [index]
};
shell[index] = {
command: 'vendor/bin/phpunit ' + config.file
};
// Register the shell target
grunt.registerTask(index, ['shell:' + index ]);
});
grunt.initConfig({
watch: watch,
shell: shell
});
// Handy for dev - logs generated targets
//grunt.log.writeln(JSON.stringify(grunt.config(), null, 2));
require('load-grunt-tasks')(grunt);
grunt.registerTask('default', [
'watch'
]);
};
请注意,watch
和 shell
任务的每个目标都是根据 test-mappings.json
中指定的文件列表动态生成和配置的。
要查看自动生成目标的配置,您只需在 运行ning $ grunt
之前取消注释 grunt.log.writeln...
行,它将打印到控制台。
运行任务
- 通过 CLI 输入
$ grunt
。 - 对
test-mappings.json
中列出的文件之一进行编辑并保存。 watch
任务将 运行 相应的shell
命令。
补充说明
目前,文件列在外部
.json
中,但它们可以驻留在Gruntfile.js
中,如果愿意,可以分配给变量。或者,可以使用适当的 globbing pattern(s) and modifying the gist above as necessary. In which case iterating over grunt.file.expand 获取文件,而不是当前的
mapping
数组。以下 g运行t 插件用于上述要点:
更新:
下面的Gruntfile.js
是针对第1点前面提到的方法。 附加说明 节下的两个(即 Globbing 而不是外部 JSON 文件路径配置)。
module.exports = function(grunt) {
'use strict';
var tests = 'tests/**/*.php',
watch = {},
shell = {};
grunt.file.expand(tests).forEach(function(filepath, index) {
watch[index] = {
files: [filepath],
tasks: [index]
};
shell[index] = {
command: 'vendor/bin/phpunit ' + filepath
};
grunt.registerTask(index, ['shell:' + index]);
});
grunt.initConfig({
watch: watch,
shell: shell
});
require('load-grunt-tasks')(grunt);
grunt.registerTask('default', [
'watch'
]);
};