| 1 | == Unit test tools == |
| 2 | |
| 3 | Disclaimer: I am the author of nose (http://somethingaboutorange.com/mrl/projects/nose). |
| 4 | |
| 5 | Test runners like nose and [http://codespeak.net/py/current/doc/test.html 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: |
| 6 | |
| 7 | basic test_settings.py: |
| 8 | |
| 9 | {{{ |
| 10 | #!python |
| 11 | DEBUG = True |
| 12 | TEMPLATE_DEBUG = DEBUG |
| 13 | DATABASE_ENGINE = 'sqlite3' |
| 14 | DATABASE_NAME = ':memory:' |
| 15 | INSTALLED_APPS = ( 'your.app', ) |
| 16 | }}} |
| 17 | |
| 18 | tests.py |
| 19 | {{{ |
| 20 | #!python |
| 21 | def setup(module): |
| 22 | os.environ["DJANGO_SETTINGS_MODULE"] = "your.app.test_settings" |
| 23 | from django.core import management |
| 24 | from django.db.models.loading import get_app |
| 25 | try: |
| 26 | management.install(get_app("your.app")) |
| 27 | except SystemExit: |
| 28 | pass |
| 29 | |
| 30 | def teardown(module): |
| 31 | from django.db import connection |
| 32 | # explicit disconnect to destroy the in-memory db |
| 33 | connection.close() |
| 34 | |
| 35 | # write your tests |
| 36 | }}} |
| 37 | |
| 38 | 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. |
| 39 | |
| 40 | == Doctest tools == |
| 41 | |
| 42 | 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: |
| 43 | |
| 44 | {{{ |
| 45 | #!python |
| 46 | def create(module_name, *models): |
| 47 | """Create tables for a group of models in the current db. This |
| 48 | makes it a bit easier to create django models in doctests. |
| 49 | |
| 50 | You have to have set up your django.settings, etc, properly |
| 51 | beforehand, of course. But assuming that is done, you can use |
| 52 | create to create test models in fake modules like so: |
| 53 | |
| 54 | >>> class Baz(models.Model): |
| 55 | ... name = models.CharField(maxlength=10) |
| 56 | ... def __repr__(self): |
| 57 | ... return self.name |
| 58 | ... class Meta: |
| 59 | ... app_label = 'baz' |
| 60 | >>> create('foo.bar.baz.models', Baz) |
| 61 | >>> b = Baz(name='a baz') |
| 62 | >>> b.save() |
| 63 | >>> Baz.objects.all() |
| 64 | [a baz] |
| 65 | |
| 66 | Take special care with the app_label setting. It must be present, |
| 67 | and it must match the 2nd to last part of the fake module name |
| 68 | passed to create. |
| 69 | """ |
| 70 | |
| 71 | # create a fake module to hold the models |
| 72 | import imp |
| 73 | testmod = imp.new_module(module_name) |
| 74 | for model in models: |
| 75 | setattr(testmod, model.__name__, model) |
| 76 | |
| 77 | # create them in the db |
| 78 | from django.db import connection |
| 79 | from django.core import management |
| 80 | sql = management.get_sql_create(testmod) |
| 81 | cursor = connection.cursor() |
| 82 | for statement in sql: |
| 83 | cursor.execute(statement) |
| 84 | }}} |