模块化fixture时,PyTest在包含多个测试文件的目录上失败



我使用Py.Test来测试Python-Flask应用程序中的函数。

当我使用一个包含所有固定装置和测试的"app_test.py"文件时,测试通过得很好。现在,我已经将fixture拆分为它们自己的模块,并将测试拆分为不同的模块,每个模块都导入我遇到问题的fixture模块。

如果我在每个模块上单独运行测试,一切都很顺利:pytest tests/test_1.pypytest tests/test_2.pypytest tests/test_3.py等。但是,如果我想用一个命令(例如pytest tests)按顺序运行所有测试,就会出现问题。

我通过了第一个模块的测试,所有未来的模块都报告了一个错误:

AssertionError: A setup function was called after the first request was handled.  
This usually indicates a bug in the application where a module was not imported 
and decorators or other functionality was called too late.
E  To fix this make sure to import all your view modules, database models 
and everything related at a central place before the application starts 
serving requests.

一个文件中的所有测试和固定装置看起来像这样:

# app_test.py
from flask_app import create_app
@pytest.fixtures(scope="session")
def app(request):
app = create_app()
with app.app_context():
yield app
@pytest.fixture(scope="session"):
def client(request, app):
client = app.test_client()
return client

def test1(client):
# test body
def test2(client):
# test body
...

我运行$ pytest app_test.py,一切都运行得很完美。

现在让我们把它们分成三个不同的模块:fixures.py、test_1.py和test_2.py。

# tests/fixtures.py
from flask_app import create_app
@pytest.fixtures(scope="session")
def app(request):
app = create_app()
with app.app_context():
yield app
@pytest.fixture(scope="session"):
def client(request, app):
client = app.test_client()
return client

# tests/test_1.py
from tests.fixtures import app, client
def test_1(client):
# test body

# tests/test_2.py
from tests.fixtures import app, client
def test_2(client):
# test body

如果我们运行$ pytest tests,那么tests/test_1.py将通过,tests/test_2.py将引发错误。

我已经了解了这个要点,并尝试用@pytest.mark.usefixture标记测试函数,但没有成功。

如何在包含多个测试文件的目录中使用模块化的fixture运行Py.Test?

您使用固定装置有点不正确。

具体来说,您声明了多个具有相同名称和相同函数对象的fixture,但在不同的模块中检测到这些fixture。从pytest的角度来看,这些应该是单独的函数,因为pytest执行dir(module)来检测测试&文件中的装置。但不知何故,由于相同的函数对象,我认为pytest记得它们是相同的;因此,一旦到达第二个测试文件,它就会尝试本地检测到的fixture名称,但发现它已经准备好了,并且失败了。

正确的用途是创建一个伪插件conftest.py,并将所有的fixture都放在那里。一旦声明,这些fixture将可用于该目录和所有子目录中的所有文件。

注意:此类夹具不得导入到测试文件中。固定装置不是功能。Pytest会自动准备它们并将它们提供给测试。

# tests/conftest.py
import pytest
from flask_app import create_app
@pytest.fixtures(scope="session")
def app(request):
app = create_app()
with app.app_context():
yield app
@pytest.fixture(scope="session")
def client(request, app):
client = app.test_client()
return client

和测试文件(注意没有导入!):

# tests/test_1.py
def test_1(client):
# test body
# tests/test_2.py
def test_2(client):
# test body

查看更多信息:https://docs.pytest.org/en/latest/writing_plugins.html

如果您正在使用应用程序实例,那么这将适用于您:

import os
import tempfile
import pytest
from my_app import app, db
@pytest.fixture
def client():
db_fd, app.config["DATABASE"] = tempfile.mkstemp()
app.config["TESTING"] = True
with app.app_context():
db.init_app(app)
yield app
os.close(db_fd)
os.unlink(app.config["DATABASE"])
@pytest.fixture
def client(request):
client = app.test_client()
return client

最新更新