Pytest 中 class 作用域夹具的意外行为
Unexpected behavior of class scoped fixture in Pytest
我正在学习 pytest 并研究不同夹具范围的行为。当我 运行 测试时,我看到 class 作用域固定装置的意外行为。这是我的项目结构。
Pytest_Basics
│ conftest.py
└───pack1
test_a.py
test_b.py
这是每个文件的内容。
conftest.py
import pytest
@pytest.fixture(scope='session', autouse=True)
def ses_fix():
print('In session fixture')
@pytest.fixture(scope='package', autouse=True)
def pak_fix():
print('In package fixture')
@pytest.fixture(scope='module', autouse=True)
def mod_fix():
print('In module fixture')
@pytest.fixture(scope='class', autouse=True)
def cls_fix():
print('In class fixture')
@pytest.fixture(scope='function', autouse=True)
def func_fix():
print('In functon fixture')
test_a.py
class TestA:
def test_a1(self):
assert True
def test_a2(self):
assert True
def test_a3(self):
assert True
test_b.py
def test_b1():
assert True
def test_b2():
assert True
def test_b3():
assert True
当我运行测试时使用pytest -v -s
。我得到低于输出。
pack1/test_a.py::TestA::test_a1 In session fixture
In package fixture
In module fixture
In class fixture
In functon fixture
PASSED
pack1/test_a.py::TestA::test_a2 In functon fixture
PASSED
pack1/test_a.py::TestA::test_a3 In functon fixture
PASSED
pack1/test_b.py::test_b1 In module fixture
In class fixture
In functon fixture
PASSED
pack1/test_b.py::test_b2 In class fixture
In functon fixture
PASSED
pack1/test_b.py::test_b3 In class fixture
In functon fixture
PASSED
我预计 class scoped fixture 只会 运行 一次,因为我在 test_a.py
模块中只有一个 class。但是,我在 test_b.py
模块中执行测试时看到它是 运行ning。
是什么导致了这种行为?这是一个错误还是我对 class 级装置的了解有限。
环境:Python - 3.9.5,Pytest - 6.2.4
这确实是 class 范围内装置的行为方式。 documentation中没有直接提到,但可以从中推导出来。如所述:
Fixtures are created when first requested by a test, and are destroyed based on their scope
具有 autouse=True
的夹具应用于会话中的每个测试函数。它们根据它们的范围被销毁,这意味着
基于会话、模块或函数的固定装置在每个测试函数所在的会话、模块或函数结束时被销毁。然而,基于 Class 的固定装置可以在 classes 之外调用,并且为了保持一致,在这种情况下,它们必须在函数之后被销毁——否则它们永远不会被销毁(如果没有 classes),或者会跨越 class 边界。重要的一点是 class-scope(或任何其他范围)并不意味着 fixture 仅应用于该范围(例如在 class 内),而是应用于任何测试函数,并且范围只是大约在它被摧毁的时候。
对于不存在于 class 中的函数,class 范围的固定装置的行为与函数范围的固定装置一样,但它们在函数范围的固定装置之前被调用并在基于功能的装置:
conftest.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")
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")
$ 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
(为清楚起见添加了缩进)
我正在学习 pytest 并研究不同夹具范围的行为。当我 运行 测试时,我看到 class 作用域固定装置的意外行为。这是我的项目结构。
Pytest_Basics
│ conftest.py
└───pack1
test_a.py
test_b.py
这是每个文件的内容。
conftest.py
import pytest
@pytest.fixture(scope='session', autouse=True)
def ses_fix():
print('In session fixture')
@pytest.fixture(scope='package', autouse=True)
def pak_fix():
print('In package fixture')
@pytest.fixture(scope='module', autouse=True)
def mod_fix():
print('In module fixture')
@pytest.fixture(scope='class', autouse=True)
def cls_fix():
print('In class fixture')
@pytest.fixture(scope='function', autouse=True)
def func_fix():
print('In functon fixture')
test_a.py
class TestA:
def test_a1(self):
assert True
def test_a2(self):
assert True
def test_a3(self):
assert True
test_b.py
def test_b1():
assert True
def test_b2():
assert True
def test_b3():
assert True
当我运行测试时使用pytest -v -s
。我得到低于输出。
pack1/test_a.py::TestA::test_a1 In session fixture
In package fixture
In module fixture
In class fixture
In functon fixture
PASSED
pack1/test_a.py::TestA::test_a2 In functon fixture
PASSED
pack1/test_a.py::TestA::test_a3 In functon fixture
PASSED
pack1/test_b.py::test_b1 In module fixture
In class fixture
In functon fixture
PASSED
pack1/test_b.py::test_b2 In class fixture
In functon fixture
PASSED
pack1/test_b.py::test_b3 In class fixture
In functon fixture
PASSED
我预计 class scoped fixture 只会 运行 一次,因为我在 test_a.py
模块中只有一个 class。但是,我在 test_b.py
模块中执行测试时看到它是 运行ning。
是什么导致了这种行为?这是一个错误还是我对 class 级装置的了解有限。
环境:Python - 3.9.5,Pytest - 6.2.4
这确实是 class 范围内装置的行为方式。 documentation中没有直接提到,但可以从中推导出来。如所述:
Fixtures are created when first requested by a test, and are destroyed based on their scope
具有 autouse=True
的夹具应用于会话中的每个测试函数。它们根据它们的范围被销毁,这意味着
基于会话、模块或函数的固定装置在每个测试函数所在的会话、模块或函数结束时被销毁。然而,基于 Class 的固定装置可以在 classes 之外调用,并且为了保持一致,在这种情况下,它们必须在函数之后被销毁——否则它们永远不会被销毁(如果没有 classes),或者会跨越 class 边界。重要的一点是 class-scope(或任何其他范围)并不意味着 fixture 仅应用于该范围(例如在 class 内),而是应用于任何测试函数,并且范围只是大约在它被摧毁的时候。
对于不存在于 class 中的函数,class 范围的固定装置的行为与函数范围的固定装置一样,但它们在函数范围的固定装置之前被调用并在基于功能的装置:
conftest.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")
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")
$ 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
(为清楚起见添加了缩进)