Opened 3 months ago

Closed 2 months ago

#35660 closed Bug (fixed)

serialized_rollback fixture is not available in TransactionTestCase.setUpClass

Reported by: Jacob Walls Owned by: Jacob Walls
Component: Testing framework Version: 4.2
Severity: Normal Keywords: rollback emulation setUpClass TransactionTestCase
Cc: Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

serialized_rollback=True allows subsequent TransactionTestCase classes to continue depending on the data created in the app's initial migration after a previous TransactionTestCase truncated tables.

By trial and error, I found that I couldn't depend on this emulated rollback during the setUpClass() phase, but rather during the setUp() phase only. This results in a difficult DX when debugging setUpClass() failures in tests that pass in isolation, and resorting to setUp() (as I ultimately did) has a performance penalty.

TestCase loads fixtures before running setUpClass(). Can we explore letting TransactionTestCase do the same? I imagine the refactor involves implementing TransactionTestCase.setUpClass().

Nothing in the docs advises that the emulated rollback is only available during certain parts of the test lifecycle, so at the very least I'd suggest a docs update. Happy to cross-post to forum if this isn't a "bug".


Sample project

models.py

from django.db import models

class MyModel(models.Model):
    flag = models.BooleanField()

migrations/0001_initial.py

# Generated by Django 4.2.15 on 2024-08-06 19:34

from django.db import migrations, models

def seed_data(apps, schema_editor):
    MyModel = apps.get_model("fooapp", "MyModel")
    MyModel.objects.create(flag=True)


class Migration(migrations.Migration):

    initial = True

    dependencies = []

    operations = [
        migrations.CreateModel(
            name="MyModel",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                ("flag", models.BooleanField()),
            ],
        ),
        migrations.RunPython(seed_data, migrations.RunPython.noop),
    ]

tests.py

from django.test import TransactionTestCase

from .models import MyModel

def depend_on_fixture():
    assert MyModel.objects.count()


class A(TransactionTestCase):
    serialized_rollback = True

    @classmethod
    def setUpClass(cls):
        depend_on_fixture()

    def test_a(self):
        pass


class B(TransactionTestCase):
    serialized_rollback = True

    @classmethod
    def setUpClass(cls):
        depend_on_fixture()

    def test_b(self):
        pass

Gives only one failure, which you'll miss if developing the tests in isolation:

======================================================================
ERROR: setUpClass (fooapp.tests.B)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/jwalls/foo/fooapp/tests.py", line 25, in setUpClass
    depend_on_fixture()
  File "/Users/jwalls/foo/fooapp/tests.py", line 6, in depend_on_fixture
    assert MyModel.objects.count()
AssertionError

----------------------------------------------------------------------
Ran 1 test in 0.004s

FAILED (errors=1)

Change History (9)

comment:1 by Sarah Boyce, 3 months ago

Triage Stage: UnreviewedAccepted

Replicated on main thank you for the detailed report
We could class this as a new feature to add support for this but I do agree that it isn't intuitive and so will leave it as a bug

comment:2 by Jacob Walls, 3 months ago

Has patch: set

comment:3 by Sarah Boyce, 2 months ago

Patch needs improvement: set

comment:4 by Jacob Walls, 2 months ago

Patch needs improvement: unset

comment:5 by Sarah Boyce, 2 months ago

Patch needs improvement: set

comment:6 by Jacob Walls, 2 months ago

Patch needs improvement: unset

comment:7 by Sarah Boyce, 2 months ago

Triage Stage: AcceptedReady for checkin

comment:8 by Sarah Boyce <42296566+sarahboyce@…>, 2 months ago

In 8eca3e9b:

Refs #35660 -- Updated TransactionTestCase methods into class or static methods.

comment:9 by Sarah Boyce <42296566+sarahboyce@…>, 2 months ago

Resolution: fixed
Status: assignedclosed

In a060a22e:

Fixed #35660 -- Made serialized_rollback and fixture data available in TransactionTestCase.setUpClass().

Note: See TracTickets for help on using tickets.
Back to Top