douxin1956
2017-01-18 21:52
浏览 79
已采纳

如何在更新时自动运行单个phpunit测试?

I am using Laravel 5.3 and unfortunately when you run gulp tdd, a change to 1 file runs the entire test suite which now takes nearly 2 minutes. With reference to this post, I started using Grunt to run specific tests when specific files are changed. Sample Gruntfile below:

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

However, now my Gruntfile is getting pretty long and I would like to run specific test files when they are changed.

Questions

  1. Is there a more efficient way to do this? (better organization of the Grunfile or using Gulp instead)
  2. How can I run a specific test when its file is changed?

Example: When tests/Home/IndexTest.php is changed, automatically run vendor/bin/phpunit tests/Home/IndexTest.php

图片转代码服务由CSDN问答提供 功能建议

我正在使用Laravel 5.3,不幸的是,当您运行 gulp tdd 时,更改为1 file运行整个测试套件,现在需要将近2分钟。 参考这篇文章,我开始使用 Grunt < / em>在更改特定文件时运行特定测试。 下面的示例Gruntfile:

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'
],
任务:['HomeTests'] 
},
 shell:{
 HomeTests:{command:phpunit  +'tests / Home'},
} 
}); 
   
 
 

但是,现在我的Gruntfile已经很长了,我想运行特定的测试 文件更改时。

问题

  1. 是否有更有效的方法来执行此操作 ? (更好地组织Grunfile或使用Gulp)
  2. 如何在文件更改时运行特定测试?

    示例: 当 tests / Home / IndexTest.php 发生更改时,自动运行 vendor / bin / phpunit tests / Home / IndexTest.php

  • 写回答
  • 好问题 提建议
  • 关注问题
  • 收藏
  • 邀请回答

3条回答 默认 最新

  • dongyi5425 2017-01-19 17:01
    已采纳

    OK, to handle this you will need to catch the matched file name and dynamically set a variable to use as the unit test file. This should cover all basic mappings where the test class name is exactly the same name as the file name it is within, and supports namespaces so not all test files with the same class name will be picked up by the filter.

    Example:

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

    So, a file named tests\unit\ApplicationTest.php and within a namespace of tests\unit if changed will now run that as a test. The resulting command being:

    phpunit --filter tests\\unit\\ApplicationTest // only runs in this namespace
    
    已采纳该答案
    评论
    解决 无用
    打赏 举报
  • dsogx84602 2017-01-19 05:07

    Using command line

    go to your project folder then run below suitable command

    Run all test class files

    phpunit

    Run specific test class file

    phpunit ./tests/ExampleTest.php

    or

    Run specific test case from class file run below command

    phpunit --filter testBasicExample ./tests/ExampleTest.php

    评论
    解决 无用
    打赏 举报
  • douti8321 2017-01-19 17:57

    You could consider the following solution:

    1. Utilize an external .json which includes an array of files/paths you intend to watch and ultimately run as a unit test.
    2. Dynamically generate the Targets for both the watch and shell Tasks.

    (Both points above will certainly help to reduce the lines of code.)

    The following gist demonstrates this:


    JSON

    Lets assume we have a file named test-mappings.json with each file path (as per point 1) specified as followed and saved in the projects root directory alongside Gruntfile.js

    [{
        "file": "tests/testA.php"
    },{
        "file": "tests/testB.php"
    },{
        "file": "tests/testC.php"
    },{
        "file": "tests/testD.php"
    }]
    

    Gruntfile.js

    Use a Gruntfile.js configured as follows:

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

    Notice each Target for both the watch and shell Tasks are dynamically generated, and configured, according to the file list specified in test-mappings.json.

    To see the configuration of the auto generated targets you can simply uncomment the line reading grunt.log.writeln..., before running $ grunt, and it will be printed to the console.


    Running the task

    1. Type $ grunt via the CLI.
    2. Make an edit to one of the files listed in test-mappings.json and save it.
    3. The watch task will then run the corresponding shell command.

    Additional notes

    1. Currently the files are listed in an external .json, however they could reside in the Gruntfile.js and be assigned to a variable if preferred.

    2. Or, the files could be obtained using the appropriate globbing pattern(s) and modifying the gist above as necessary. In which case iterating over grunt.file.expand will be handy for that, instead of the current mapping array.

    3. The following grunt plugins were used for the above gist:


    Update:

    The following Gruntfile.js is for the approach previously mentioned in point no. two under the Additional notes secton (i.e. Globbing instead of an external JSON filepath config).

    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'
        ]);
    
    };
    
    评论
    解决 无用
    打赏 举报

相关推荐 更多相似问题