【问题标题】:How to automatically run tests when there's any change in my project (Django)?当我的项目(Django)发生任何变化时如何自动运行测试?
【发布时间】:2013-02-16 11:22:01
【问题描述】:

目前,在我对 django 项目进行重大更改后,我每隔一段时间就会运行python manage.py test。每当我在项目中更改和保存文件时,是否可以自动运行这些测试?更早地检测错误会很有用(我知道 rails 在 rspec 中有类似的东西)。我正在使用鼻子和 django-nose。提前致谢。

【问题讨论】:

标签: python django unit-testing testing nose


【解决方案1】:

使用entr:

  1. $brew install entr
  2. $find . -name '*.py' | entr python ./manage.py test

或者,为了额外的功劳,将它与ack结合起来:

$ ack --python | entr python ./manage.py test

如果您希望它在添加新文件时找到它们:

$ until ack -f --python | entr -d python ./manage.py test; do sleep 1; done

【讨论】:

  • 如果您使用的是银搜索器,请将“ack -f --python”更改为“ag -l --python”
  • 没听说过The Silver Searcher,谢谢提示!
  • 从未听说过entr。它比我想要的更有用。谢谢:)
  • @c17r 一年后,我几乎每个工作日都在使用ag(银牌搜索器)。
  • 还将ripgrep 视为ag/ack 的替代品。
【解决方案2】:

py.test 答案(也适用于鼻子):

pip install pytest-xdist
py.test -f # will watch all subfolders for changes, and rerun the tests

由于 py.test 理解鼻子,这也适用于鼻子。

【讨论】:

  • Nose 不再维护,而且 py.test 无论如何都要好得多,而且更 Pythonic。
【解决方案3】:

我是一名 JavaScript 开发人员,因此我使用 JS 开发人员使用 Node.js 构建的工具在我的项目中实现相同的目标。它非常简单,但您还需要安装 nodeJS 才能使其正常工作。

我在我的项目根目录中创建了一个名为 gruntfile.js 的文件:

//gruntfile.js
module.exports = function(grunt) {

  grunt.initConfig({
    watch: {
      files: ['*.py'],
      tasks: ['shell']
    },
    shell: {
      test: {
        command: 'python main_test.py'
      }
    }
  });

  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-shell');

  grunt.registerTask('default', ['watch']);
};

它所做的基本上是监视该目录中具有 py 扩展名的任何文件,如果他们更改了它,则执行一个 shell 命令,在这种情况下是我的 python 测试(你可能想要更改它,我的测试名称是 main_test.py )。为了运行这个 grunt 脚本,你需要安装 Node.js,然后你的全局路径中就会有 npm。之后,您还需要安装一些节点模块。除了 grunt-cli 之外的所有这些模块都将存储在您当前的文件夹中,因此请确保您位于项目的根目录或您将 gruntfile.js 放入的任何文件夹中。然后运行以下命令。

npm install grunt-cli -g
npm install grunt
npm install grunt-contrib-watch
npm install grunt-shell

不用担心大小,这些都是非常小的模块。现在你已经设置好了所有东西,你可以简单地运行grunt,它会开始观察你的 py 文件,当你保存它们时,它会运行你的测试。这可能不是运行 python 测试的最佳方式,但正如我所说,我是一名 JavaScript 开发人员,我认为 Grunt 提供了一种非常简单的方式来执行测试,即使是其他语言,所以我使用它。

【讨论】:

    【解决方案4】:

    我刚刚尝试了nose-watch,效果非常好!安装插件并使用--with-watch 选项运行测试。

    更新: :(从 django-nose 的 manage.py 帮助程序运行测试时,它似乎无法正常工作。

    最终我选择使用支持 django 的 tdaemon,尽管对于成熟的项目可能还需要一些小技巧。

    例如,这是我为我的 django 项目运行它的方式:

    tdaemon -t django --custom-args=a_specific_app_to_test -d --ignore-dirs logs
    

    --custom-args 用于将测试集中在特定应用上(与 python manage.py test a_specific_app_to_test 一样)

    -d 参数是启用调试日志记录,它会打印触发运行的文件更改。

    --ignore-dirs 是必要的,因为我的测试写入了日志(这本身就是一个问题!)并且tdaemon 进入了无限循环。

    【讨论】:

      【解决方案5】:

      这里是另一个 Javascript 开发人员,我发现 nodemon (https://github.com/remy/nodemon) 工作得很好。默认情况下,它监视*.js 文件,但可以使用--ext 标志进行配置。要使用它,请执行以下操作:

      npm install -g nodemon
      cd /your/project/dir/
      nodemon --ext py --exec "python manage.py test"
      

      现在,每当*.py 文件更改时,它都会重新运行您的命令。它甚至可以找到新文件。

      【讨论】:

      • 我喜欢这个。很干净。
      • 我也一直在这样做,但我发现当测试完成时它会注册为“崩溃”,有时拆解似乎没有运行。还没有完全弄清楚,但想知道您是否会遇到类似的问题?
      • @dcsan 我没有,但我也很长时间没有接触过我正在使用它的项目。抱歉,我帮不上忙。
      【解决方案6】:

      我用过 watchr,比如Watchr

      【讨论】:

        【解决方案7】:

        我是用 gulp 做的。安装 gulp-shell:

        npm install gulp-shell --save-dev    
        

        在 gulpfile.js 中:

        var shell = require('gulp-shell')
        
        gulp.task('run-tests', shell.task([
           'python3 manage.py test']))
        
        gulp.task('watch', function(){
           gulp.watch(['./your-project-name/**/*.html', './your-project-name/**/*.py'], ['run-tests']);
        });
        
        gulp.task('default',['run-tests','watch']);
        

        它会在任何保存到任何 .py 或 .html 文件的更改时运行测试!

        【讨论】:

          【解决方案8】:

          您可以在 Django 之上使用Django Supervisor。这将避免使用 CI 工具(这在任何情况下都可能有用,这不会使其他响应无效 - 可能只是补充)。

          【讨论】:

            【解决方案9】:

            我建议设置django-nosesniffer。它很容易设置并且效果很好。类似于this scent.py 的东西是我唯一需要的定制。然后你可以运行sniffer -x myapp.tests

            Nose 还附带了一些其他好东西,它们也使测试更易于使用。

            【讨论】:

              【解决方案10】:

              如果你使用 git 控制代码,另一种方法是使用 git hook pre-commit

              可能是remote: fatal: Not a git repository: '.'之类的错误,请查看此帖子https://stackoverflow.com/a/4100577/7007942

              【讨论】:

                【解决方案11】:

                我发现最简单的方法是按照this post 的建议使用 gulp。请注意gulp-shell(由其他答案推荐)实际上是blacklisted by gulp,但幸运的是您甚至不需要插件。试试这个:

                // gulpfile.js
                
                const { watch } = require('gulp')
                var exec = require('child_process').exec
                
                function test (cb) {
                  exec('python manage.py test', function (err, stdout, stderr) {
                    console.log(stdout)
                    console.log(stderr)
                    cb(err)
                  })
                }
                
                exports.default = function () {
                  watch('./**/*.py', test)
                }
                

                过去,我尝试过其他答案中建议的许多选项。这个比较无痛。如果您对 JavaScript 有所了解,这将很有帮助。

                【讨论】:

                  【解决方案12】:

                  我编写了一个 Gulp 任务来在任何指定的 Python 文件被更改或删除时自动运行./manage.py test。为此,您需要 Node。

                  首先,安装 Gulp:

                  yarn add -D gulp@next
                  

                  然后使用以下gulpfile.js 并进行必要的调整:

                  const { exec } = require('child_process');
                  const gulp = require('gulp');
                  
                  const runDjangoTests = (done) => {
                    const task = exec('./manage.py test --keepdb', {
                      shell: '/bin/bash', // Accept SIGTERM signal. Doesn't work with /bin/sh
                    });
                  
                    task.stdout.pipe(process.stdout);
                    task.stderr.pipe(process.stderr);
                  
                    task.on('exit', () => {
                      done();
                    });
                  
                    return task;
                  };
                  
                  gulp.task('test', runDjangoTests);
                  
                  gulp.task('watch', (done) => {
                    let activeTask;
                    const watcher = gulp.watch('**/*.py', {
                      // Ignore whatever directories you need to
                      ignored: ['.venv/*', 'node_modules'],
                    });
                  
                    const runTask = (message) => {
                      if (activeTask) {
                        activeTask.kill();
                        console.log('\n');
                      }
                  
                      console.log(message);
                      activeTask = runDjangoTests(done);
                    };
                  
                    watcher.on('change', (path) => {
                      runTask(`File ${path} was changed. Running tests:`);
                    });
                  
                    watcher.on('unlink', (path) => {
                      runTask(`File ${path} was removed. Running tests:`);
                    });
                  });
                  

                  然后只需运行node node_modules/gulp/bin/gulp.js watch 即可运行任务:)

                  【讨论】:

                    【解决方案13】:

                    https://pycrunch.com/

                    其中一项关键功能 - 仅对文件更改运行受影响的测试。可作为 PyCharm 的插件使用

                    【讨论】:

                      【解决方案14】:

                      在 ubuntu 上,安装 inotifywait (sudo apt install inotify-tools) 后,此脚本有效:

                      inotifywait -qrm -e close_write * |
                      while read -r filename event; do
                        python manage.py test accord
                      done
                      

                      【讨论】:

                        【解决方案15】:

                        您需要一个持续集成服务器,例如 Jenkins

                        【讨论】:

                        • 感谢您的回答。当我使用 Selenium 时,我肯定会检查这一点。目前,我只是使用 Django 附带的“假”服务器进行基本测试。
                        • Jenkins 与 Selenium 无关。您可以轻松地将它与正常的单元测试一起使用。
                        • 这里值得一提的是django-jenkins项目。
                        • 我认为这对于文件保存来说有点夸张。有没有类似rails guard gem 的东西?但是对于python?
                        • 这个答案对于 TDD 来说太重了。 OP 询问如何编写作为 Jenkins 运行的心跳的快速简单测试。您的建议需要很长的周转时间,并且可能需要签到
                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2020-11-25
                        • 2021-11-12
                        • 1970-01-01
                        • 2014-10-07
                        • 1970-01-01
                        相关资源
                        最近更新 更多