简体   繁体   中英

PyTest fixture with session scope does not maintains continuity of db data

This test session works properly :

from myapp.models import MyModel
@pytest.fixture(scope='function')
def mymodel():
    return G(MyModel)

@pytest.mark.django_db
def test_mymodel_one(mymodel):
    assert MyModel.objects.count() > 0

@pytest.mark.django_db
def test_mymodel_two(mymodel):
    assert MyModel.objects.count() > 0

and produces this output:

========= test session starts =========
tests/myapp/test_pp.py::test_mymodel_one PASSED
tests/myapp/test_pp.py::test_mymodel_two PASSED

but if I change the scope of my fixture to 'session', test two fails:

========= test session starts =========
tests/myapp/test_pp.py::test_mymodel_one PASSED
tests/myapp/test_pp.py::test_mymodel_two FAILED

========= FAILURES ==============
_________ test_mymodel_two ________
tests/myapp/test_pp.py:85: in test_mymodel_two
    assert MyModel.objects.count() > 0
E   assert 0 > 0

The object created is correctly returned from fixture (I can access his values) but it isn't stored no more. How can I use session scope and maintain the storage in my test db?

I tried to replicate the context in my tests package and I've found the same situation you exposed.

First of all, I want to share with you two page of the pytest documentation, where we could find the answer to this question. In the documentation ¹ the organization of the methods is a little bit different, in fact the method which is delegated to create the fixture is inside the conftest.py .

    # content of conftest.py
    @pytest.fixture(scope="session")
    def smtp(...):
    # the returned fixture value will be shared for
    # all tests needing it

According to your tests settings, you can try moving the mymodel method inside the conftest module. I've tried to move my fixture generator inside the conftest file, but I found several traversal problems due to the required django_db mark, which might conflict with the session scope (I guess?).

I also found another help inside the examples page ² of pytest, where is used the session scope widely for different python modules, where is pointed out the impossibility to an internal module test to access to the same session scope defined at the same level of the parents' one.

    # content of a/conftest.py
import pytest

class DB:
    pass

@pytest.fixture(scope="session")
def db():
    return DB()

# content of a/test_db.py
def test_a1(db):
    assert 0, db  # to show value

# content of a/test_db2.py
def test_a2(db):
    assert 0, db  # to show value

if

# content of b/test_error.py
def test_root(db):  # no db here, will error out
    pass

will fail the test, because

The two test modules in the a directory see the same db fixture instance while the one test in the sister-directory b doesn't see it. We could of course also define a db fixture in that sister directory's conftest.py file. Note that each fixture is only instantiated if there is a test actually needing it (unless you use “autouse” fixture which are always executed ahead of the first test executing).

In the second example I've noticed that the method for generating the fixture is instantiated for each test and even though the scope is set to session or module , it works like function scope.

Which version of pytest are you using?

Could try moving from the current module to the conftest module your mymodel method?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM