I have a Django app that requires a settings
attribute in the form of:
RELATED_MODELS = ('appname1.modelname1.attribute1', 'appname1.modelname2.attribute2', 'appname2.modelname3.attribute3', ...)
Then hooks their post_save signal to update some other fixed model depending on the attributeN
defined.
I would like to test this behaviour and tests should work even if this app is the only one in the project (except for its own dependencies, no other wrapper app need to be installed). How can I create and attach/register/activate mock models just for the test database? (or is it possible at all?)
Solutions that allow me to use test fixtures would be great.
As of [5163], Django models can now be created dynamically at run-time, rather than being defined in a Python source file. While this may seem useless on the surface, it actually provides a powerful way to prototype a Django project, even by users who don't know a thing about Python!
def str(self): is a python method which is called when we use print/str to convert object into a string. It is predefined , however can be customised.
If the code in question is built into Django, don't test it. Examples like the fields on a Model or testing how the built-in template. Node renders included tags. If your model has custom methods, you should test that, usually with unit tests.
Automated Testing is a widely used tool that uses a collection of predefined test cases. Learn how Django and Selenium to ensure a bug free system. Table of contents.
You can put your tests in a tests/
subdirectory of the app (rather than a tests.py
file), and include a tests/models.py
with the test-only models.
Then provide a test-running script (example) that includes your tests/
"app" in INSTALLED_APPS
. (This doesn't work when running app tests from a real project, which won't have the tests app in INSTALLED_APPS
, but I rarely find it useful to run reusable app tests from a project, and Django 1.6+ doesn't by default.)
(NOTE: The alternative dynamic method described below only works in Django 1.1+ if your test case subclasses TransactionTestCase
- which slows down your tests significantly - and no longer works at all in Django 1.7+. It's left here only for historical interest; don't use it.)
At the beginning of your tests (i.e. in a setUp method, or at the beginning of a set of doctests), you can dynamically add "myapp.tests"
to the INSTALLED_APPS setting, and then do this:
from django.core.management import call_command from django.db.models import loading loading.cache.loaded = False call_command('syncdb', verbosity=0)
Then at the end of your tests, you should clean up by restoring the old version of INSTALLED_APPS and clearing the app cache again.
This class encapsulates the pattern so it doesn't clutter up your test code quite as much.
@paluh's answer requires adding unwanted code to a non-test file and in my experience, @carl's solution does not work with django.test.TestCase
which is needed to use fixtures. If you want to use django.test.TestCase
, you need to make sure you call syncdb
before the fixtures get loaded. This requires overriding the _pre_setup
method (putting the code in the setUp
method is not sufficient). I use my own version of TestCase
that lets me add apps with test models. It is defined as follows:
from django.conf import settings from django.core.management import call_command from django.db.models import loading from django import test class TestCase(test.TestCase): apps = () def _pre_setup(self): # Add the models to the db. self._original_installed_apps = list(settings.INSTALLED_APPS) for app in self.apps: settings.INSTALLED_APPS.append(app) loading.cache.loaded = False call_command('syncdb', interactive=False, verbosity=0) # Call the original method that does the fixtures etc. super(TestCase, self)._pre_setup() def _post_teardown(self): # Call the original method. super(TestCase, self)._post_teardown() # Restore the settings. settings.INSTALLED_APPS = self._original_installed_apps loading.cache.loaded = False
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With