|Version 2 (modified by Carl Karsten <carl@…>, 8 years ago) (diff)|
Unit test tools
Disclaimer: I am the author of nose (http://somethingaboutorange.com/mrl/projects/nose).
Test runners like nose and py.test make writing and running unittests easier, and they also make setting up your django enviroment for testing fairly painless. With either package, you can write module-level fixtures (setup/teardown) to install your app models before you run your tests and get rid of them after you're done. Here's a simple example, using sqlite in memory for the test database:
DEBUG = True TEMPLATE_DEBUG = DEBUG DATABASE_ENGINE = 'sqlite3' DATABASE_NAME = ':memory:' INSTALLED_APPS = ( 'your.app', )
def setup(module): os.environ["DJANGO_SETTINGS_MODULE"] = "your.app.test_settings" from django.core import management from django.db.models.loading import get_app try: management.install(get_app("your.app")) except SystemExit: pass def teardown(module): from django.db import connection # explicit disconnect to destroy the in-memory db connection.close() # write your tests
If you want to use a persistent db for testing, you'll probably want to follow the lead of runtests.py in django/tests and drop your test database when you're done with it.
When writing doctests, creating model classes in the doctest is a natural thing to want to do, but it can be hard to get just the right incantation to create the test models' database tables, especially if you have other apps in your test settings. This function can make things quite a bit easier, as its own doctest demonstrates:
def create(module_name, *models): """Create tables for a group of models in the current db. This makes it a bit easier to create django models in doctests. You have to have set up your django.settings, etc, properly beforehand, of course. But assuming that is done, you can use create to create test models in fake modules like so: >>> class Baz(models.Model): ... name = models.CharField(maxlength=10) ... def __repr__(self): ... return self.name ... class Meta: ... app_label = 'baz' >>> create('foo.bar.baz.models', Baz) >>> b = Baz(name='a baz') >>> b.save() >>> Baz.objects.all() [a baz] Take special care with the app_label setting. It must be present, and it must match the 2nd to last part of the fake module name passed to create. """ # create a fake module to hold the models import imp testmod = imp.new_module(module_name) for model in models: setattr(testmod, model.__name__, model) # create them in the db from django.db import connection from django.core import management sql = management.get_sql_create(testmod) cursor = connection.cursor() for statement in sql: cursor.execute(statement)
See Also: TestingDjango