我正在学习 pytest 并研究不同固定范围的行为。当我运行测试时,我看到类范围的固定装置的意外行为。这是我的项目结构。
\nPytest_Basics\n\xe2\x94\x82 conftest.py\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80pack1\n test_a.py\n test_b.py\nRun Code Online (Sandbox Code Playgroud)\n以下是每个文件的内容。
\nimport pytest\n\n\n@pytest.fixture(scope='session', autouse=True)\ndef ses_fix():\n print('In session fixture')\n\n\n@pytest.fixture(scope='package', autouse=True)\ndef pak_fix():\n print('In package fixture')\n\n\n@pytest.fixture(scope='module', autouse=True)\ndef mod_fix():\n print('In module fixture')\n\n\n@pytest.fixture(scope='class', autouse=True)\ndef cls_fix():\n print('In class fixture')\n\n\n@pytest.fixture(scope='function', autouse=True)\ndef func_fix():\n print('In functon fixture')\nRun Code Online (Sandbox Code Playgroud)\nclass TestA:\n\n def test_a1(self):\n assert True\n\n def test_a2(self):\n assert True\n\n def test_a3(self):\n assert True\nRun Code Online (Sandbox Code Playgroud)\ndef test_b1():\n assert True\n\n\ndef test_b2():\n assert True\n\n\ndef test_b3():\n assert True\nRun Code Online (Sandbox Code Playgroud)\n当我使用 运行测试时pytest -v -s。我得到以下输出。
pack1/test_a.py::TestA::test_a1 In session fixture\nIn package fixture\nIn module fixture\nIn class fixture\nIn functon fixture\nPASSED\npack1/test_a.py::TestA::test_a2 In functon fixture\nPASSED\npack1/test_a.py::TestA::test_a3 In functon fixture\nPASSED\npack1/test_b.py::test_b1 In module fixture \nIn class fixture\nIn functon fixture\nPASSED\npack1/test_b.py::test_b2 In class fixture\nIn functon fixture\nPASSED\npack1/test_b.py::test_b3 In class fixture\nIn functon fixture\nPASSED\nRun Code Online (Sandbox Code Playgroud)\n我预计类范围的固定装置只会运行一次,因为我在test_a.py模块中只有一个类。但是,我看到它在test_b.py模块中执行测试时正在运行。
是什么导致了这种行为?这是一个错误还是我对班级级别的装置了解有限。
\n环境:Python - 3.9.5,Pytest - 6.2.4
\n这确实是类范围的装置的行为方式。文档中没有直接提及,但可以从中推断出来。就像声明的那样:
夹具在测试首次请求时创建,并根据其范围销毁
夹具autouse=True应用于会话中的每个测试功能。它们根据其范围被销毁,这意味着基于会话、模块或函数的固定装置在每个测试函数所在的会话、模块或函数结束时被销毁。然而,基于类的固定装置可以在类之外调用,并且为了保持一致,在这种情况下,它们必须在函数之后被销毁 - 否则它们可能永远不会被销毁(如果没有类),或者会跨类边界存在。重要的一点是类范围(或任何其他范围)并不意味着固定装置仅应用于该范围(例如在类内部),而是应用于任何测试函数,并且范围仅在其被销毁时应用。
对于不在类中的函数,类范围的固定装置的行为就像函数范围的固定装置一样,但它们在函数范围的固定装置之前调用,并在基于函数的固定装置之后关闭:
测试.py
@pytest.fixture(scope="function", autouse=True)
def fct_fixt():
print("function fixture start")
yield
print("function fixture end")
@pytest.fixture(scope="class", autouse=True)
def class_fixt():
print("class fixture start")
yield
print("class fixture end")
Run Code Online (Sandbox Code Playgroud)
test_fixt.py
def test_1():
print("test_1 outside class")
class TestClass:
def test_1(self):
print("test_1 inside class")
def test_class_2(self):
print("test_2 inside class")
Run Code Online (Sandbox Code Playgroud)
$ python -m pytest -s test_fixt.py
...
class fixture start
function fixture start
test_1 outside class
function fixture end
class fixture end
class fixture start
function fixture start
test_1 inside class
function fixture end
function fixture start
test_2 inside class
function fixture end
class fixture end
Run Code Online (Sandbox Code Playgroud)
(为了清晰起见添加了缩进)