pytest-django
pytest-django copied to clipboard
Database fixtures are run when they shouldn't be for SimpleTestCase unit tests
pytest-django uses a function internally for checking if a test is a Django test case class, named is_django_unittest
. This class is used to determine if database setup is needed or not. This is implemented with an issubclass
check for SimpleTestCase
. However, the Django documentation states the following:
SimpleTestCase disallows database queries by default. This helps to avoid executing write queries which will affect other tests since each SimpleTestCase test isn’t run in a transaction.
See here: https://docs.djangoproject.com/en/1.10/topics/testing/tools/#django.test.SimpleTestCase.allow_database_queries
If you write a unit test in a TestCase class which inherits SimpleTestCase
, where allow_database_queries
is set to False
, which is the default, you will hit problems when you have a fixture defined like so in your conftest.py
file:
@pytest.fixture(autouse=True)
def setup_db_tenant(db):
# ... Create something in the database here ...
The fixture will be run, and database access will be done, and then Django will print the following error message: (Where YourClassNameHere
is whatever your class name is for your test case.)
AssertionError: Database queries aren't allowed in SimpleTestCase. Either use TestCase
or TransactionTestCase to ensure proper test isolation or set
YourClassNameHere.allow_database_queries to True to silence this failure.
Should pytest-django behave like if the db
fixture would not have been requested then?
Or should it switch the flag on SimpleTestCase
to allow for access?
https://github.com/pytest-dev/pytest-django/blob/master/pytest_django/plugin.py#L383 I think my problem actually lies here. The fixture scoped to a class calls getfixturevalue(request, 'django_db_setup')
, which sets up the database, including some tests which don't need database access.
I'm not sure if there is an existing fixture which will let me run some database setup code for each function, only if database setup is needed. Generally, I want to automatically only create a database when running at least one test which needs database access. My project now has a conftest.py
file which does this, but it requires rewriting a few fixtures which come with this module.
I ended up writing an if statement with request.getfixturevalue('db')
to implement a function-scoped fixture for database setup.
I think I realised what could be done for potentially supporting function-scoped fixtures which conditionally do database setup. If db
results in a value which could be simply True
or False
, or maybe some object or None
, you would be able to write this:
@pytest.fixture(autouse=True)
def setup_whatever(db):
if db:
do_some_database_setup()
I think there are two separate matters here.
- A subtle bug with the built-in session-scoped database setup being done some times where it isn't needed.
_django_setup_unittest
callsdjango_db_setup
when your tests don't need database access. - A feature request for a "conditional database setup" fixture, described above.
Feel free to split this into two separate issues, etc.
I ran into this same problem just now. My conftest.py contains django_db_setup
fixture which is always ran. Regardless of the sort of test I'm trying run. In this case a testcase inherting from SimpleTestCase
. And since it's part of a git push hook, it should be fast as possible, not doing anything in the database. Just a test to see if we had to ran makemessages or not.
Would be nice to have a good solution for this.
see also #13 "Easy fixture loading"
How does #13 help NOT run fixtures for SimpleTestCase @westurner ? :)
A standard way to do this could solve for both use cases.
On Tuesday, November 13, 2018, Peter Uittenbroek [email protected] wrote:
How does #13 https://github.com/pytest-dev/pytest-django/issues/13 help NOT run fixtures for SimpleTestCase @westurner https://github.com/westurner ? :)
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/pytest-dev/pytest-django/issues/472#issuecomment-438166561, or mute the thread https://github.com/notifications/unsubscribe-auth/AADGy7YcFaUs9S5PtlRAl4mh-jOyLFg3ks5uunchgaJpZM4Mqis5 .
Bumping this. I ran into a similar issue, even without a default fixture in conftest.py
. I have an existing project with some SimpleTestCase
subclasses that don't perform any db operations. The tests run fine with python manage.py test
. With pytest
, they fail with the following error:
django.test.testcases.DatabaseOperationForbidden: Database queries to 'default' are not allowed in SimpleTestCase subclasses. Either subclass TestCase or TransactionTestCase to ensure proper test isolation or add 'default' to apps.pages.tests.HomepageTests.databases to silence this failure.