Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

django_db_serialized_rollback does not reset to previous db state #1062

Open
Eraldo opened this issue May 8, 2023 · 3 comments
Open

django_db_serialized_rollback does not reset to previous db state #1062

Eraldo opened this issue May 8, 2023 · 3 comments

Comments

@Eraldo
Copy link

Eraldo commented May 8, 2023

Problem description

Ever since I added the live_server to my tests, other tests started to fail, that did previously pass.

Details

The fixture to setup my browser with live_server support:

@pytest.fixture
def live_browser(browser, live_server, django_db_serialized_rollback) -> WebDriver:
    return browser

Example of how I use that fixture:

def test_some_case(live_browser):
    pass

The test that fails when (and after) using the live_server fixture:

def test_user_get_absolute_url(user: User):
    assert user.get_absolute_url() == escape_uri_path(
        f"http://mydomain.com/users/{user.id}"
    )

Context infos:
I am using --reuse-db as part of my pytest.ini file.

Problem Analysis

I understand this happens due to improper reset (flush) of the test database after any test using the live_server fixture.

I did some research and found this issue: #329

This lead me back to the docs of pytest-django where I payed closer attention and found django_db_serialized_rollback: https://pytest-django.readthedocs.io/en/latest/helpers.html#std-fixture-django_db_serialized_rollback
As I understand it, this would in theory restore the content of the test database after a test that uses my fixture.

However this does either not seem to be the case, or not work as expected.

The user.get_absolute_url() uses the django.contrib Site model, for which I have a data migration.
The content seems to get flushed in the tests using live_server and never get restored.
Running only the broken test again after running my full test suit, still fails until I recreate the test database manually.

Solution ideas / requests

Workaround: Removing --reuse-db.
Sadly this is the only reliable way I found so far to get my test to work again.
And even then I need to run pytest twice once excluding the tests using live_server and then running them separately.
Obviously this is considerably slowing down the (TDD) testing process.

At this point I don't really have any proper solution ideas.
I would be happy to clarify any misunderstandings I have,
and maybe even discuss potential solution ideas
(or at least better workarounds). 😊

If I can provide further context to clarify the issue and use case, I'll gladly provide it.
Looking forward to hearing some feedback. 😅

@Eraldo
Copy link
Author

Eraldo commented May 8, 2023

I might have misunderstood the application of the django_db_serialized_rollback fixture.
Am I supposed to do it the other way around?:
Removing django_db_serialized_rollback from the live_browser fixture and adding it to the test_user_get_absolute_url test?

I was hoping I could restore the migration data after running my live_server tests. 🤔
Since these tests are the ones breaking the migration data, it would make more sense to me to fix the db there.

@Tubo
Copy link

Tubo commented Jan 27, 2024

I came across this issue as well, that after adding a live_server test case to my suite, all my other tests started to fail.

My investigation suggest this was not a pytest-django problem, but a django problem. This was first raised in 2015, and here's a summary https://code.djangoproject.com/ticket/25251#comment:38. Essentially LiveServerTestCase is a child of TransactionTestCase, which flushes all data after it finishes, including data migrations.

The same author who summarised the issue in the above link also made a pull request here django/django#14147 but unfortunately it wasn't merged.

If you're using pytest, one solution would be to add --create-db option. Although it defeats the purpose of --reuse-db, at least your tests will now pass consistently.

@mbegoc
Copy link

mbegoc commented Feb 3, 2024

Just running into the same problem and lost 2 days trying to understand what's going on. Didn't know about the serialized_rollback and thought it would solve my problem, but it runs the deserialization before the test run, while I was expecting it to run as a teardown of the test.
So what, we are supposed to emulate the rollback on the next test when it's the one that disable transaction rollback that flush the database in the first place?
Plus, I have no garantee the tests will run in a specific order.
I'm so puzzled.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants