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.
Quoting from a related answer:
I chose a slightly different, albeit more coupled, approach to dynamically creating models just for testing.
I keep all my tests in a
tests
subdirectory that lives in myfiles
app. Themodels.py
file in thetests
subdirectory contains my test-only models. The coupled part comes in here, where I need to add the following to mysettings.py
file:I also set db_table in my test model, because otherwise Django would have created the table with the name
tests_<model_name>
, which may have caused a conflict with other test models in another app. Here's my my test model:I've figured out a way for test-only models for django 1.7+.
The basic idea is, make your
tests
an app, and add yourtests
toINSTALLED_APPS
.Here's an example:
And I have different
settings
for different purposes(ref: splitting up the settings file), namely:settings/default.py
: base settings filesettings/production.py
: for productionsettings/development.py
: for developmentsettings/testing.py
: for testing.And in
settings/testing.py
, you can modifyINSTALLED_APPS
:settings/testing.py
:And make sure that you have set a proper label for your tests app, namely,
common/tests/apps.py
common/tests/__init__.py
, set up properAppConfig
(ref: Django Applications).Then, generate db migration by
Finally, you can run your test with param
--settings=<your_project_name>.settings.testing
.If you use py.test, you can even drop a
pytest.ini
file along with django'smanage.py
.py.test
Here's the pattern that I'm using to do this.
I've written this method that I use on a subclassed version of TestCase. It goes as follows:
Then, I create a special test-specific models.py file in something like
myapp/tests/models.py
that's not included in INSTALLED_APPS.In my setUp method, I call create_models_from_app('myapp.tests') and it creates the proper tables.
The only "gotcha" with this approach is that you don't really want to create the models ever time
setUp
runs, which is why I catch DatabaseError. I guess the call to this method could go at the top of the test file and that would work a little better.I shared my solution that I use in my projects. Maybe it helps someone.
pip install django-fake-model
Two simple steps to create fake model:
1) Define model in any file (I usualy define model in test file near a test case)
2) Add decorator
@MyFakeModel.fake_me
to your TestCase or to test function.This decorator creates table in your database before each test and remove the table after test.
Also you may create/delete table manually:
MyFakeModel.create_table()
/MyFakeModel.delete_table()
This solution works only for earlier versions of
django
(before1.7
). You can check your version easily:Original response:
It's quite strange but form me works very simple pattern:
Below I've put some code which defines Article model which is needed only for tests (it exists in someapp/tests.py and I can test it just with: ./manage.py test someapp ):
Unit tests also working with such model definition.