How to automatically run tests when there's any change in my project (Django)?

PythonDjangoUnit TestingTestingNose

Python Problem Overview


At the moment I am running python manage.py test every once in a while after I make significant changes in my django project. Is it possible to run those tests automatically whenever I change and save a file in my project? It'll be useful to detect bugs earlier (I know rails has something like this with rspec). I am using nose and django-nose. Thanks in advance.

Python Solutions


Solution 1 - Python

Use entr:

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

Or, for extra credit, combine it with ack:

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

If you want it to even find new files as you add them:

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

Solution 2 - Python

py.test answer (which also works for nose):

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

Since py.test understands nose, this works for nose too.

Solution 3 - Python

I'm a JavaScript developer so I used the tools JS developer have built with Node.js to achieve the same goal in my projects. It is very simple but you also need to install nodeJS to get it working.

I created a file called gruntfile.js in my project root directory:

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

What it's doing is basically watching any file in that directory that has a py extension and if they changed it execute a shell command which in this case is my python test (you might wanna change it, my test name was main_test.py). In order to run this grunt script you need to install Node.js and after that you will have npm in your global path. after that you need to insall a few node modules as well. All these modules except grunt-cli will be stored in your current folder so make sure you are at the root of your project or what ever folder you put that gruntfile.js in. then run the fallowing commands.

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

Don't worry about the size, these are very small modules. Now that you have every thing setup you can simply run grunt and it will start watching your py files and when you saved them it will run your tests. It may not be best way for running python tests but as I said I'm a JavaScript developer and I think Grunt has provided a very simple way of executing tests even for other languages so I use it.

Solution 4 - Python

I just tried nose-watch and it worked fantastic! install the plugin and run the test with the --with-watch option.

Update: :( it does not seem to work well when running tests from django-nose's manage.py helper.

Eventually I opted to use tdaemon, which supports django, although might require a bit of fiddling as well for full fledged projects.

For example here is how I ran it for my django project:

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

The --custom-args was to focus tests to specific app (same as you would do python manage.py test a_specific_app_to_test

The -d argument is to enable debug logging, which prints which file change triggered the run.

The --ignore-dirs was necessary because my tests wrote to the logs (which in itself is a problem!) and tdaemon went into an infinite loop.

Solution 5 - Python

Another Javascript dev here, I've found nodemon (https://github.com/remy/nodemon) to work pretty well. By default it watches *.js files but that's configurable with the --ext flag. To use it, do:

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

Now, whenever a *.py file changes, it'll re-run your command. It even finds new files.

Solution 6 - Python

I'm used watchr, something like Watchr

Solution 7 - Python

I did this using gulp. Install gulp-shell:

npm install gulp-shell --save-dev    

And in the 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']);

And it runs the tests anytime there are changes saved to any .py or .html files!

Solution 8 - Python

You can use Django Supervisor on top of Django. This will avoid the use of a CI tool (which may be useful in any case, this isn't invalidating the other response - maybe just complementary).

Solution 9 - Python

I would recommend setting up django-nose and sniffer. It's quite easy to setup and works great. Something along the lines of this scent.py was the only customization I needed. Then you can just run sniffer -x myapp.tests.

Nose comes with some other goodies that make tests a bit nicer to work with as well.

Solution 10 - Python

if you use git control code, another way to is use git hook pre-commit

maybe error like remote: fatal: Not a git repository: '.', check this post https://stackoverflow.com/a/4100577/7007942

Solution 11 - Python

I've found the easiest way is to use gulp as recommended by this post. Note that gulp-shell (recommended by other answers) is actually blacklisted by gulp, but thankfully you don't even need a plugin. Try this instead:

// 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)
}

In the past, I've tried many of the options suggested in other answers. This one was comparatively painless. It's helpful if you have some knowledge of JavaScript.

Solution 12 - Python

I wrote a Gulp task to automatically run ./manage.py test whenever any specified Python files are changed or removed. You'll need Node for this.

First, install Gulp:

yarn add -D gulp@next

Then use the following gulpfile.js and make any necessary adjustments:

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:`);
  });
});

Then simply run node node_modules/gulp/bin/gulp.js watch to run the task :)

Solution 13 - Python

https://pycrunch.com/

One of key features - run only impacted tests on file changes. Available as plugin for PyCharm

Solution 14 - Python

On ubuntu this script works, after installing inotifywait (sudo apt install inotify-tools):

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

Solution 15 - Python

You'll need a continuous integration server, something like Jenkins.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser1011444View Question on Stackoverflow
Solution 1 - PythonclackeView Answer on Stackoverflow
Solution 2 - PythonThe Unfun CatView Answer on Stackoverflow
Solution 3 - PythonIman MohamadiView Answer on Stackoverflow
Solution 4 - PythontutuDajujuView Answer on Stackoverflow
Solution 5 - PythonTom SaleebaView Answer on Stackoverflow
Solution 6 - PythonarmeoView Answer on Stackoverflow
Solution 7 - PythonlightsView Answer on Stackoverflow
Solution 8 - PythonUlflanderView Answer on Stackoverflow
Solution 9 - PythonCoryView Answer on Stackoverflow
Solution 10 - PythonKevin ChanView Answer on Stackoverflow
Solution 11 - PythonjordancoopermanView Answer on Stackoverflow
Solution 12 - PythondspacejsView Answer on Stackoverflow
Solution 13 - PythonGleb SevrukView Answer on Stackoverflow
Solution 14 - PythonErichBSchulzView Answer on Stackoverflow
Solution 15 - PythonDaniel RosemanView Answer on Stackoverflow