You can get django-nose from PyPI with...
pip install django-nose
The development version can be installed with...
pip install -e git://github.com/jbalogh/django-nose.git#egg=django-nose
Since django-nose extends Django's built-in test command, you should add it to your INSTALLED_APPS in settings.py:
INSTALLED_APPS = ( ... 'django_nose', ... )
Then set TEST_RUNNER in settings.py:
TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
The day-to-day use of django-nose is mostly transparent; just run ./manage.py test as usual.
You can save several seconds at the beginning and end of your test suite by reusing the test database from the last run. To do this, set the environment variable REUSE_DB to 1:
REUSE_DB=1 ./manage.py test
The one new wrinkle is that, whenever your DB schema changes, you should leave the flag off the next time you run tests. This will cue the test runner to reinitialize the test database.
Also, REUSE_DB is not compatible with TransactionTestCases that leave junk in the DB, so be sure to make your TransactionTestCases hygienic (see below) if you want to use it.
django-nose includes a fixture bundler which drastically speeds up your tests by eliminating redundant setup of Django test fixtures. To use it...
The fixture bundler reorders your test classes so that ones with identical sets of fixtures run adjacently. It then advises the first of each series to load the fixtures once for all of them (and the remaining ones not to bother). It also advises the last to tear them down. Depending on the size and repetition of your fixtures, you can expect a 25% to 50% speed increase.
Incidentally, the author prefers to avoid Django fixtures, as they encourage irrelevant coupling between tests and make tests harder to comprehend and modify. For future tests, it is better to use the "model maker" pattern, creating DB objects programmatically. This way, tests avoid setup they don't need, and there is a clearer tie between a test and the exact state it requires. The fixture bundler is intended to make existing tests, which have already committed to fixtures, more tolerable.
If using --with-fixture-bundling causes test failures, it likely indicates an order dependency between some of your tests. Here are the most frequent sources of state leakage we have encountered:
It's also possible that you have post_save signal handlers which create additional database rows while loading the fixtures. FastFixtureTestCase isn't yet smart enough to notice this and clean up after it, so you'll have to go back to plain old TestCase for now.
In some unusual cases, it is desirable to exempt a test class from fixture bundling, forcing it to set up and tear down its fixtures at the class boundaries. For example, we might have a TestCase subclass which sets up some state outside the DB in setUpClass and tears it down in tearDownClass, and it might not be possible to adapt those routines to heed the advice of the fixture bundler. In such a case, simply set the exempt_from_fixture_bundling attribute of the test class to True.
Unlike the stock Django test runner, django-nose lets you write custom TransactionTestCase subclasses which expect to start with an unmarred DB, saving an entire DB flush per test.
The default Django TransactionTestCase class can leave the DB in an unclean state when it's done. To compensate, TransactionTestCase does a time-consuming flush of the DB before each test to ensure it begins with a clean slate. Django's stock test runner then runs TransactionTestCases last so they don't wreck the environment for better-behaved tests. django-nose replicates this behavior.
Some people, however, have made subclasses of TransactionTestCase that clean up after themselves (and can do so efficiently, since they know what they've changed). Like TestCase, these may assume they start with a clean DB. However, any TransactionTestCases that run before them and leave a mess could cause them to fail spuriously.
django-nose offers to fix this. If you include a special attribute on your well-behaved TransactionTestCase...
class MyNiceTestCase(TransactionTestCase): cleans_up_after_itself = True
...django-nose will run it before any of those nasty, trash-spewing test cases. You can thus enjoy a big speed boost any time you make a TransactionTestCase clean up after itself: skipping a whole DB flush before every test. With a large schema, this can save minutes of IO.
django-nose's own FastFixtureTestCase uses this feature, even though it ultimately acts more like a TestCase than a TransactionTestCase.
If you have a model that is used only by tests (for example, to test an abstract model base class), you can put it in any file that's imported in the course of loading tests. For example, if the tests that need it are in test_models.py, you can put the model in there, too. django-nose will make sure its DB table gets created.
django-nose.tools provides pep8 versions of Django's TestCase asserts and some of its own as functions.
assert_redirects(response, expected_url, status_code=302, target_status_code=200, host=None, msg_prefix='') assert_contains(response, text, count=None, status_code=200, msg_prefix='') assert_not_contains(response, text, count=None, status_code=200, msg_prefix='') assert_form_error(response, form, field, errors, msg_prefix='') assert_template_used(response, template_name, msg_prefix='') assert_template_not_used(response, template_name, msg_prefix='') assert_queryset_equal(qs, values, transform=repr) assert_num_queries(num, func=None, *args, **kwargs) assert_code(response, status_code, msg_prefix='') assert_ok(response, msg_prefix='') assert_mail_count(count, msg=None)
South installs its own test command that turns off migrations during testing. Make sure that django-nose comes after south in INSTALLED_APPS so that django_nose's test command is used.
NOSE_ARGS = ['--failed', '--stop']
NOSE_PLUGINS = [ 'yourapp.tests.plugins.SystematicDysfunctioner', # ... ]
Just like middleware or anything else, each string must be a dot-separated, importable path to an actual class. Each plugin class will be instantiated and added to the Nose test runner.
In versions of Django < 1.4 the project folder was in fact a python package as well (note the __init__.py in your project root). In Django 1.4, there is no such file and thus the project is not a python module.
When you upgrade your Django project to the Django 1.4 layout, you need to remove the __init__.py file in the root of your project (and move any python files that reside there other than the manage.py) otherwise you will get a `ImportError: No module named urls` exception.
This happens because Nose will intelligently try to populate your sys.path, and in this particular case includes your parent directory if your project has a __init__.py file (see: https://github.com/nose-devs/nose/blob/release_1.1.2/nose/importer.py#L134).
This means that even though you have set up your directory structure properly and set your ROOT_URLCONF='my_project.urls' to match the new structure, when running django-nose's test runner it will try to find your urls.py file in 'my_project.my_project.urls'.
Django 1.2 switches to a class-based test runner. To use django-nose with Django 1.2, change your TEST_RUNNER from django_nose.run_tests to django_nose.NoseTestSuiteRunner.
django_nose.run_tests will continue to work in Django 1.2 but will raise a warning. In Django 1.3, it will stop working.
If you were using django_nose.run_gis_tests, you should also switch to django_nose.NoseTestSuiteRunner and use one of the spatial backends in your DATABASES settings.
If you want to use django-nose with Django 1.1, use https://github.com/jbalogh/django-nose/tree/django-1.1 or http://pypi.python.org/pypi/django-nose/0.0.3.
django-nose does not support Django 1.0.
See more in changelog.txt.
|File||Type||Python Version||Uploaded On||Downloads|
|django-nose-1.2.tar.gz||Source||July 23, 2013||639,735|
|1.2||July 23, 2013|
|1.1||May 20, 2012|
|1.0||March 13, 2012|
|0.1.3||April 15, 2011|
|0.1.2||Aug. 15, 2010|
|0.1||May 18, 2010|
|0.0.3||Dec. 31, 2009|
|0.0.2||Oct. 1, 2009|
|0.0.1||Oct. 1, 2009|
|Nov. 4, 2014, 1:30 p.m.||django-nose||0.1.3||Release Created|
|Nov. 4, 2014, 1:30 p.m.||django-nose||0.1.2||Release Created|
|Nov. 4, 2014, 1:30 p.m.||django-nose||0.0.1||Release Created|
|Nov. 4, 2014, 1:30 p.m.||django-nose||0.0.2||Release Created|
|Nov. 4, 2014, 1:30 p.m.||django-nose||0.1||Release Created|
|Nov. 4, 2014, 1:30 p.m.||django-nose||0.0.3||Release Created|
|Nov. 4, 2014, 1:30 p.m.||django-nose||1.2||Release Created|
|Nov. 4, 2014, 1:30 p.m.||django-nose||1.1||Release Created|
|Nov. 4, 2014, 1:30 p.m.||django-nose||1.0||Release Created|
|Nov. 4, 2014, 1:30 p.m.||django-nose||Package Created|