the*_*man 7 unit-testing decorator pytest python-3.x
我是测试新手,我偶然发现了 pytest 固定装置,但我不完全确定何时使用它们以及它们为什么有用。
例如,请参阅以下代码:
import pytest
@pytest.fixture
def input_value():
input = 39
return input
def test_divisible_by_3(input_value):
assert input_value % 3 == 0
def test_divisible_by_6(input_value):
assert input_value % 6 == 0
Run Code Online (Sandbox Code Playgroud)
这里pytest.fixture的作用是什么?为什么我们不能简单地创建一个被调用的函数input_value()并在测试函数内运行该函数?例如:
import pytest
def input_value():
input = 39
return input
def test_divisible_by_3():
assert input_value() % 3 == 0
def test_divisible_by_6():
assert input_value() % 6 == 0
Run Code Online (Sandbox Code Playgroud)
为什么我们不能这样做?使用fixture有什么用?
Mic*_*ert 26
Pytest Fixtures 和常规函数都可以用来构建测试代码并减少代码重复。乔治·乌多森(George Udosen)提供的答案很好地解释了这一点。
然而,OP 特别询问了 a 和常规 Python 函数之间的差异pytest.fixture,并且存在许多差异:
默认情况下,pytest.fixture每个引用夹具的测试函数都会执行 a 。但在某些情况下,夹具设置可能在计算上昂贵或耗时,例如初始化数据库。为此,pytest.fixture可以将 a 配置为更大的范围。这允许pytest.fixture在模块(模块范围)中的测试之间或什至在 pytest 运行(会话范围)的所有测试之间重用。以下示例使用模块范围的固定装置来加速测试:
from time import sleep
import pytest
@pytest.fixture(scope="module")
def expensive_setup():
return sleep(10)
def test_a(expensive_setup):
pass # expensive_setup is instantiated for this test
def test_b(expensive_setup):
pass # Reuses expensive_setup, no need to wait 10s
Run Code Online (Sandbox Code Playgroud)
尽管可以通过常规函数调用来实现不同的作用域,但作用域固定装置使用起来更加愉快。
Pytest 在测试收集阶段注册所有固定装置。当测试函数需要名称与注册的固定装置名称匹配的参数时,Pytest 将负责为测试实例化固定装置并将实例提供给测试函数。这是依赖注入的一种形式。
与常规函数相比的优点是您可以通过pytest.fixture名称引用任何函数,而无需显式导入它。例如,Pytest 附带了一个tmp_path固定装置,任何测试都可以使用它来处理临时文件。以下示例取自Pytest 文档:
CONTENT = "content"
def test_create_file(tmp_path):
d = tmp_path / "sub"
d.mkdir()
p = d / "hello.txt"
p.write_text(CONTENT)
assert p.read_text() == CONTENT
assert len(list(tmp_path.iterdir())) == 1
assert 0
Run Code Online (Sandbox Code Playgroud)
用户使用前无需导入,tmp_path非常方便。
甚至可以在测试功能没有请求的情况下将夹具应用于测试功能(请参阅自动使用夹具)。
与测试参数化 非常相似,夹具参数化允许用户指定夹具的多个“变体”,每个变体具有不同的返回值。使用该夹具的每个测试都将执行多次,每个变体一次。假设您想要测试所有代码是否都针对 HTTP 和 HTTPS URL 进行了测试,您可以执行以下操作:
import pytest
@pytest.fixture(params=["http", "https"])
def url_scheme(request):
return request.param
def test_get_call_succeeds(url_scheme):
# Make some assertions
assert True
Run Code Online (Sandbox Code Playgroud)
参数化夹具将导致每个引用测试都使用每个版本的夹具执行:
$ pytest
tests/test_fixture_param.py::test_get_call_succeeds[http] PASSED [ 50%]
tests/test_fixture_param.py::test_get_call_succeeds[https] PASSED [100%]
======== 2 passed in 0.01s ========
Run Code Online (Sandbox Code Playgroud)
与常规函数调用相比,Pytest 装置提供了许多生活质量的改进。我建议始终优先选择 Pytest 固定装置而不是常规函数,除非您必须能够直接调用固定装置。直接调用 pytest 装置是不符合预期的,并且调用将失败。
我自己对 pytest 很陌生,但我知道它减少了编写多次测试多次使用的代码的需要,因为在您的情况下,您需要分别重写该函数,并且此代码片段将是一个入门:
Fixtures 用于向测试提供一些数据,例如数据库连接、要测试的 URL 和某种输入数据。
因此,我们可以将固定功能附加到测试中,而不是为每个测试运行相同的代码,它会在执行每个测试之前运行并将数据返回到测试。
-- 来源: https: //www.tutorialspoint.com/pytest/pytest_fixtures.htm
一般来说,它有助于在测试之间共享通用的资源,并大大减少重复。同样,这些固定功能的返回值可以作为“输入参数”传递到各个测试中,如下所示:
@pytest.fixture
def input_value():
input = 39
return input
def test_divisible_by_3(input_value):
assert input_value % 3 == 0
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
801 次 |
| 最近记录: |