1
# Copyright 2012 Canonical Ltd. This software is licensed under the
2
# GNU Affero General Public License version 3 (see the file LICENSE).
4
"""Django-enabled test cases."""
6
from __future__ import (
16
'TestModelTransactionalTestCase',
17
'TransactionTestCase',
20
from django.conf import settings
21
from django.core.management import call_command
22
from django.core.management.commands import syncdb
23
from django.db import (
27
from django.db.models import loading
29
from maastesting.testcase import TestCase
33
class DjangoTestCase(TestCase, django.test.TestCase):
34
"""`TestCase` for Metal as a Service.
36
Supports test resources and fixtures.
39
def assertAttributes(self, tested_object, attributes):
40
"""Check multiple attributes of `tested_objects` against a dict.
42
:param tested_object: Any object whose attributes should be checked.
43
:param attributes: A dict of attributes to test, and their expected
44
values. Only these attributes will be checked.
46
matcher = testtools.matchers.MatchesStructure.byEquality(**attributes)
47
self.assertThat(tested_object, matcher)
50
class TransactionTestCase(TestCase, django.test.TransactionTestCase):
51
"""`TransactionTestCase` for Metal as a Service.
53
A version of TestCase that supports transactions.
55
The basic Django TestCase class uses transactions to speed up tests
56
so this class should be used when tests involve transactions.
59
def _fixture_teardown(self):
60
# Force a flush of the db: this is done by
61
# django.test.TransactionTestCase at the beginning of each
62
# TransactionTestCase test but not at the end. The Django test runner
63
# avoids any problem by running all the TestCase tests and *then*
64
# all the TransactionTestCase tests. Since we use nose, we don't
65
# have that ordering and thus we need to manually flush the db after
66
# each TransactionTestCase test. Le Sigh.
67
if getattr(self, 'multi_db', False):
68
databases = connections
70
databases = [DEFAULT_DB_ALIAS]
72
call_command('flush', verbosity=0, interactive=False, database=db)
76
# Set the appropriate application to be loaded.
80
# Add the models to the db.
81
self._original_installed_apps = settings.INSTALLED_APPS
82
assert self.app is not None, "TestCase.app must be defined!"
83
settings.INSTALLED_APPS = list(settings.INSTALLED_APPS)
84
settings.INSTALLED_APPS.append(self.app)
85
loading.cache.loaded = False
86
# Use Django's 'syncdb' rather than South's.
87
syncdb.Command().handle_noargs(
88
verbosity=0, interactive=False, database=DEFAULT_DB_ALIAS)
89
super(TestModelMixin, self)._pre_setup()
91
def _post_teardown(self):
92
super(TestModelMixin, self)._post_teardown()
93
# Restore the settings.
94
settings.INSTALLED_APPS = self._original_installed_apps
95
loading.cache.loaded = False
98
class TestModelTestCase(TestModelMixin, TestCase):
99
"""A custom test case that adds support for test-only models.
101
For instance, if you want to have a model object used solely for testing
102
in your application 'myapp1' you would create a test case that uses
103
TestModelTestCase as its base class and:
104
- initialize self.app with 'myapp1.tests'
105
- define the models used for testing in myapp1.tests.models
107
This way the models defined in myapp1.tests.models will be available in
108
this test case (and this test case only).
112
class TestModelTransactionalTestCase(TestModelMixin, TransactionTestCase):
113
"""A TestCase Similar to `TestModelTestCase` but with transaction