Why does StaticLiveServerTestCase breaks fixtures when dynamically generating tests beside TestCase does not?
Long question with MCVE included.
Goal
I want to challenge the StaticLiveServerTestCase for multiple user flows. The strategy I will use is:
- Writting test mixins for business logic mixins in the code base, then I can duplicate my tests for multiple combinations of mixins and track how they combine and how MRO must resolve ;
- Using fixtures to provision objects tests must rely on, as close as possible to the bare user reality ;
- Reach regression test level by adding Selenium into the play in order to emulate the user flow on the screen.
MCVE
I use the LTS version of Django Django==5.2. I leave this MCVE in order to reproduce my problem.
First we import dependencies:
from django.test import TestCase
from django.contrib.staticfiles.testing import StaticLiveServerTestCase
from core import models
Then we create some Test Mixins in order to fashion our Test Unit, none of them inherits from TestCase or StaticLiveServerTestCase:
class TestMixin:
def test_dummy(self):
self.assertEqual(2, 1 + 1)
class TestUserMixin:
fixtures = [
"core/tests/fixtures/groups.yaml",
"core/tests/fixtures/customusers.yaml",
"core/tests/fixtures/organizations.yaml",
]
def test_fixtures(self):
#print(models.CustomUser.objects.all())
self.assertTrue(models.CustomUser.objects.count() > 0)
class TestMultiUser(TestUserMixin, TestMixin):
def test_user_mapping(self):
self.assertTrue(hasattr(self, "user"))
self.assertTrue(isinstance(self.user, models.CustomUser))
Now, we generate test for all user we have in fixtures:
for i, user in enumerate(models.CustomUser.objects.all()):
# Not because locals()
test_name = f"TestMultiUser_{user.username.replace("-", "_")}"
locals()[test_name] = type(
test_name,
# MRO matters:
# (TestMultiUser, StaticLiveServerTestCase) -> ERROR setUpClass: Key (permission_id)=(40) is not present in table "auth_permission".
# (StaticLiveServerTestCase, TestMultiUser) -> FAIL test_fixtures: models.CustomUser.objects.count() > 0
(TestMultiUser, StaticLiveServerTestCase),
{"user": user}
)
When we use the TestCase class, everything works as expected, but if I change for StaticLiveServerTestCase the fixture flow breaks.
And it breaks in a MRO dependent way:
- If MRO is
(TestMultiUser, StaticLiveServerTestCase), it errors insetUpClassmissing core Django entities such asPermission; - If MRO is
(StaticLiveServerTestCase, TestMultiUser)it fails in checking fixtures that are not installed yet or already saved.
Summary
It seems there is something in the StaticLiveServerTestCase mechanic that breaks the dynamic of Test Unit generation. It might be related to how the setUpClass method of the StaticLiveServerTestCase is implemented.
I have showed by a MCVE that changing TestCase for StaticLiveServerTestCase breaks the dynamic pattern I want to use in order to cover all my users and scenarii before the complexity of available mixins.
Hence my question: Why does StaticLiveServerTestCase breaks fixtures when dynamically generating tests beside TestCase does not?