This part explains how to use django-sane-testing to create a workable test suite. For test writers, most important part is about creating tests, testers and CI admins may be more interested in executing them.
Various test types were identified when taking look at developer tests. Every test type has it’s corresponding class in djangosanetesting.cases, namely:
However, you are not required to inherit from those, althrough it’s much advised to keep test cases intent-revealing. Job of the library is to:
Those are done by plugins, and they dermine their jobs by looking at class attributes, namely:
All of those are booleans. Because class attributes are currently used to determine behaviour, nor doctest nor function tests are supported (they will not break things, but you’ll get no goodies from library).
To support proper test selection and error-handling, tests also has class atribute required_sane_plugins, which specifies list of plugins (from those available) that are required for this type of test; if it’s not, test automatically skip itself.
Proper defaults are selected when using library test cases; however, if you have your own and complicated test inheritance model, you can integrate it on your own.
When writing tests, keep in mind limitations of the individual test cases to prevent interacting tests:
Easiest way to run tests is to put TEST_RUNNER=’djangosanetesting.testrunner.run_tests’ into your settings.py. This still allows you to select individual tests by running ./manage.py test testpackage.module.module:Class.method, however there is no way to disable some tests (by not using some plugin) or to use additional nose plugins.
More flexible and granular way is using standard nosetests command. However, keep in mind:
Most likely, you’ll end up with something like DJANGO_SETTINGS_MODULE="settings" PYTHONPATH=".:.." nosetests --with-django; you can, however, flexibly add another nose modules (like --with-coverage).
#TODO: Test type selection is not supported yet (= run all selenium tests but do not run unittests et al). This is considered a bug and will be fixed in next releases.
Provided plugins:
DjangoPlugin takes care about basic Django environment setup. It must be loaded in order to use other plugins with Django (obviously). This plugin takes care about DatabaseTestCase and DestructiveDatabaseTestCase:
Responsible for starting HTTP server, sort of same as ./manage.py runserver, however testing server is multithreaded (as if with patch from #3357, but always enabled: if you’ll any problems with it, write me).
Server is first started when start_live_server attribute is first encountered, and is stopped after whole testsuite.
Warning
Because application logic is always executed in another thread (even when server would be single-threaded), it’s not possible to use HttpTestCase‘s with in-memory databases (well, theoretically, we could do database setup in each thread and have separate databases, but that will be really nasty).
Thus, if encountered with in-memory database, server is not started and SkipTest is raised instead.
Responsible for starting HTTP server, in similar way to DjangoLiveServerPlugin. However, CherryPy WSGI is used instead, as it’s much more mature and considered to be production-ready, unlike Django’s development server.
Use when in need of massive parallel requests, or when encountering a bug (like #10117).
Note
When using ./manage.py test, Django server is used by default. You can use CherryPy‘s by setting CHERRYPY_TEST_SERVER = True in settings.py.
Warning
DjangoLiveServerPlugin (--with-djangoliveserver) and CherryPyLiveServerPlugin (--with-cherrypyliveserver) are mutually exclusive. Using both will cause errors, and You’re responsible for choosing one when running tests with nosetests (see Running tests for details).
Selenium is excellent tool for regression (web application) testing. SeleniumPlugin easily allows you to use xUnit infrastructure together with Selenium RC and enjoy unified, integrated infrastructure.
Selenium proxy server must be set up and running, there is no support for auto-launching (yet).
SeleniumPlugin recognizes following configuration variables in settings.py:
When plugin encounters selenium_start attribute (set to True), it tries to start browser on selenium proxy. If exception occurs (well, I’d catch socket errors, but this seems to be impossible on Windows), it assumes that proxy is not running, thus environment conditions are not met and SkipTest is raised. If FORCE_SELENIUM_TESTS is set to True, then original exceptin is raised instead, causing test to fail (usable on web testing CI server to ensure tests are runnig properly and are not mistakenly skipped).