8

I'm writing an app that has a custom model field. I want to test that field, using a model that is only used within tests, but I'm struggling to get the model working in tests.

Some of my app structure is like this:

myapp/
    fields.py
    models.py
tests/
    fields/
        models.py
        tests.py
    settings.py
    test_models.py
    test_views.py

tests/fields/models.py is like this:

from django.db import models
from myapp.fields import MyCustomField

class MyTestModel(models.Model):
    custom_field = MyCustomField()

I then import MyTestModel and try to use it in tests/fields/tests.py.

Things I've tried...

1. Initially I got:

RuntimeError: Model class tests.fields.models.MyTestModel doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.

2. So I added "tests", to INSTALLED_APPS in tests/settings.py. But then I get:

django.db.utils.OperationalError: no such table: tests_mytestmodel

3. I've seen this in the docs about isolating model registration in tests. So I've tried moving the models into tests/fields/tests.py:

from django.db import models
from django.test import TestCase
from django.test.utils import isolate_apps
from myapp.fields import MyCustomField

@isolate_apps('tests')
class MyTestCase(TestCase):

    def test_things_work(self):
        class MyTestModel(models.Model):
            custom_field = MyCustomField()

        obj = MyTestModel.objects.create(custom_field='foo')
        self.assertEqual(...)

But that still gets me:

django.db.utils.OperationalError: no such table: tests_mytestmodel

I've tried looking through the tests of lots of other Django projects that provide custom fields and can't see what I'm missing that (apparently) makes their tests with models work.

It sounds like, somehow, there need to be migrations for these models that are only used in the tests... is that right? How? Or something else?

Phil Gyford
  • 13,432
  • 14
  • 81
  • 143
  • What if you run the `makemigrations` command while pointing it to your test settings with `--settings`? It should give you initial migrations for your test app that then are picked up when tests are run. – djangonaut Mar 14 '17 at 13:45
  • Hmm, it doesn't notice the models ("No changes detected"). I could maybe put them in ``tests/models.py`` but I haven't seen it done this way anywhere else. – Phil Gyford Mar 14 '17 at 14:03
  • I'm just thinking you need to add `tests.fields` to `INSTALLED_APPS` instead of only `tests`. – djangonaut Mar 14 '17 at 14:38
  • That's it! So simple after all that! I don't even need do the `makemigrations`. If you want to add that as an answer I'll mark it correct. Thanks! – Phil Gyford Mar 14 '17 at 17:20
  • related: https://stackoverflow.com/q/502916 – djvg Jun 06 '23 at 07:46

1 Answers1

2

Since your test app is in a nested folder you need to specify the whole path to it in INSTALLED_APPS instead of the parent folder, like:

INSTALLED_APPS = [
    ...,
    "tests.fields"
]
djangonaut
  • 7,233
  • 5
  • 37
  • 52
  • Yeah, I hadn't thought of that folder as an app - the rest of the tests aren't in folders, but as that set needed the `models.py` they're in a folder together. And I guess that `models.py` makes it an app, hence the need for inclusion in `INSTALLED_APPS`. – Phil Gyford Mar 14 '17 at 18:47