Skip to content

Unexpected test order when mixing pytest / unittest tests and transactional tests #827

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

Closed
pmourlanne opened this issue Mar 18, 2020 · 4 comments · Fixed by #830
Closed

Comments

@pmourlanne
Copy link
Contributor

Let's say I have the following tests:

import pytest
from django.test import TestCase, TransactionTestCase

@pytest.mark.django_db()
def test_function_with_db():
    ...

@pytest.mark.django_db(transaction=True)
def test_function_with_transactional_db():
    ...

class MyTestCase(TestCase):
    def test_method(self):
        ...

class MyTransactionTestCase(TransactionTestCase):
    def test_method(self):
        ...

I expect transactional tests, here test_function_with_transactional_db and MyTransactionTestCase.test_method to run last.

Running pytest yields:

$ pytest -v

prototype/test_prototype.py::test_function_with_db PASSED
prototype/test_prototype.py::test_function_with_transactional_db PASSED
prototype/test_prototype.py::MyTestCase::test_method PASSED
prototype/test_prototype.py::MyTransactionTestCase::test_method PASSED

I tried fixing this by adding a pytest_collection_modifyitems in my project but my custom ordering runs before pytest-django's ordering. So pytest-django gets the last word, and in this case it's not what I want :>

I think this can be fixed by improving on what's being done in pytest_collection_modifyitems, I'll try something out and hopefully open a PR.

@blueyed
Copy link
Contributor

blueyed commented Mar 18, 2020

Does #820 (in master) fix it?

@blueyed
Copy link
Contributor

blueyed commented Mar 18, 2020

Anyway, it might also just not work as expected.
The code that should take care of running it like Django is

def pytest_collection_modifyitems(items):
def get_order_number(test):
marker_db = test.get_closest_marker('django_db')
if marker_db:
transaction = validate_django_db(marker_db)[0]
if transaction is True:
return 1
else:
transaction = None
fixtures = getattr(test, 'fixturenames', [])
if "transactional_db" in fixtures:
return 1
if transaction is False:
return 0
if "db" in fixtures:
return 0
return 2
items[:] = sorted(items, key=get_order_number)
.
(I've not investigated/looked closer at your report yet)

It likely needs to look at classes also then?

@pmourlanne
Copy link
Contributor Author

I'll look at #820 👍

About the code yes, that's what I've been looking at, and yes it should look at classes if we want to change the behaviour :>
I've found this pytest-django-ordering plugin https://github.com/rlucioni/pytest-django-ordering/blob/master/pytest_django_ordering/plugin.py which kinda does what I want? I need to look a bit deeper into it.

Thank you for your quick answers :)

@pmourlanne
Copy link
Contributor Author

#820 is going to make it so my custom ordering is applied after so yes, it should fix my current issue. I could also apply @pytest.hookimpl(trylast=True) to my project's pytest_collection_modifyitems.
This will be a fine workaround 👍

I still think pytest-django's behaviour could be improved, I'll keep digging for now :)

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

Successfully merging a pull request may close this issue.

2 participants