Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django test runner not respecting unittest.TestCase?

For one of my functional tests, I decided to use unittest.TestCase instead of a Django test class because it was convenient when cleaning up the test to have direct access to my local development database in the test itself.

Running the test in isolation like so passes as I'd expect:

$ python manage.py test functional_tests.test_functionality
System check identified no issues (0 silenced).
...
----------------------------------------------------------------------
Ran 3 tests in 0.040s

OK

When I try to run all tests at the same time, however, that test specifically errors out, complaining that an object DoesNotExist, as though it were using the Django test database:

$ python manage.py test functional_tests
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
..................E..
======================================================================
ERROR: some_functional_test (functional_tests.test_functionality.FunctionalTest)
----------------------------------------------------------------------
Traceback (most recent call last):

... etc.

app.models.Object.DoesNotExist: Object matching query does not exist.

----------------------------------------------------------------------
Ran 21 tests in 0.226s

FAILED (errors=1)
Destroying test database for alias 'default'...

I assume the error is with my trying use Object.objects.latest('created') when no Objects exist in Django's test database.

Is there some way to prevent Django from wrapping all tests in whatever it is about the test runner that prevents my test from accessing an Object directly?

like image 812
Derek Avatar asked Nov 23 '25 09:11

Derek


1 Answers

First a little explanation.

By default when you run ./manage.py test django test-runner make few steps which involves creating test database (with test_ prefix to each database name from app settings), running migration and destroying test database (more details on runner steps could find here)

A good explanation on how django treat test database is described here


In your case when you run unittest.TestCase in isolation no test database is created:

$ python manage.py test functional_tests.test_functionality
System check identified no issues (0 silenced).
...
----------------------------------------------------------------------
Ran 3 tests in 0.040s

OK

( ^no logs about creating test database)

That's because there were no django.test.TestCase called. We can see it from sources (virgin unittest.TestCase doesn't have databases property, when django.TestCase it has)

But when you call whole module (python manage.py test functional_tests) looks like you have some django.test.TestCase tests in suite so that's why new test database is creating:

$ python manage.py test functional_tests
Creating test database for alias 'default'...  # <-- THIS ONE
##<skipped for readability>
Destroying test database for alias 'default'...

And as you mentioned tests failed because there were no prepared objects for them.


Solution

At this point I see few options to solve this.

  1. Prepare test data for tests explicitly (by fixtures or manually in tests or setups) so they would be independent from current state of database

  2. Explicitly use desired database.

    Run tests with --keepdb option (ie ./manage.py test --keepdb, it will use the existing database and will not destroy it after test runs) and set same test database name in app settings as working database (in such case it will not append test_ prefix for test db)

  3. Since you don't want to use django.TestCase, so don't use them at all? Replace them with unittest.TestCase and it will not create test database

like image 167
ujlbu4 Avatar answered Nov 24 '25 22:11

ujlbu4



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!