Purpose: speeding up development with nose tests
Jump to section: nose step-by-step tutorial
Why not just use Django’s test runner?
Recently, I worked on a heavily tested Django project. Running all tests in the project took several minutes, and the dependencies that were marked external in our Subversion project repository ran all of their tests too–each time project tests were run! I work on a team where testing frequently and committing often are tantamount to productivity. Nose tests can improve both testing speed, and subsequently accelerate development. As we walk through this tutorial you’ll begin to see how nose and its plugins (nose-exclude, django-nose) improve the productivity on any size Django project.
What nose and its plugins buy you?
- Exclude dependencies, directories, externals, or files you don’t need to test in your application.
- Run all tests that failed in the previous run.
- Identify slow-running tests.
- Get detailed information about tests that fail or error.
- Faster test runs.
- And so much more. Once you’ve completed this tutorial, open a terminal and type: nosetests –help.
What you’ll need to set up nose for Django
Although information in this tutorial can be used in almost any development environment, the walk-through for setting up nose and the related plug-ins was created and tested (of course) using the following:
- Ubuntu 9.10 (Karmic Koala)
- Python 2.64
- Django 1.1.1
- pip for installing nose, nose-exclude, and django-nose.
Nose gotchas, tips, and other “fun”
- It seems that Synaptic Package Manager installs the older package pip-0.3.1. Don’t use it. Remove it. Do this first: Go to: System > Administration > Synaptic Package Manager > search for pip > right-click on python-pip > Mark for removal > click Apply button etc.
- Don’t use TransactionTestCase; nose wraps every test in a transaction (batteries included)
Don’t use the word “test”, or any variation thereof, in any method or class name; however, you can “exclude” certain non-tests from nose in the setup.cfg file discussed later in this tutorial.
Thanks to Jon Sackett for his comment on using the decorator @nottest on methods that have “test” in the name.
- Open a terminal, and pip uninstall or remove any previous versions of django-nose, nose, nose-exclude.
Note: This step may require finding and deleting older versions of pip installed on Ubuntu; ie. pip-0.3.1 (type pip –version to see which you have)
Next, install pip-0.6.3 if you haven’t already. Download the source tarball (pip-0.6.3.tar.gz), extract it, and cd into the extraction directory.
- In the terminal type: sudo python setup.py install
- type: pip –version (if you don’t see 0.6.3, make sure you’ve removed all pip eggs and directories system-wide, and try again.)
- terminal: pip install nose –upgrade
- terminal: pip install django-nose –upgrade
- IMPORTANT: cd out of the current project you’re working in (some projects will have ‘nose-exclude’ as part of the build directory); I cd into my home directory, and then type: pip install nose-exclude.
- Now go back to your project directory, and create a new file named nose_exclude.txt. See Using File-Based Exclusion List for what should go in this file. My recommendation is to create a file named nose_exclude.txt.tmpl with some common settings to keep track of the application dependencies or directories that you don’t want or need to test.
- Likewise, create a new file in you project’s root directory named setup.cfg. This file contains the options or flags that you want to pass to “python manage.py test” every time you run tests. Optionally create one or more template files with predefined settings much like the nose_exclude.txt.tmpl file recommended above. This will help with different testing scenarios. For example, you probably don’t want to run coverage every time you execute all of your tests, but you might create a template that caters specifically to coverage or any other options not normally executed in your test runs.
- See django-nose for changes you’ll need to make to settings.py in order to run tests using nose. Depending on your development environment, you may prefer to place these edits in a different file that gets pulled into settings.py.
Finally, cd into your Django project, and type python manage.py test as you normally would. Now you have nose!
Command differences between django-nose and the Django test runner
Classes that inherit from Django’s TestCase class and their test methods require special syntax. See below for examples.
python manage.py test app.tests:YourTestCaseClass
python manage.py test app.tests:YourTestCaseClass.your_test_method
More nose plugins
Take a look at the plugins page for nose, or just type nosetests --help for more info. Enjoy!