考虑以下测试代码,该代码将模拟运行结果与预期结果进行比较。运行结果的值取决于提供两个值的参数化灯具参数的值,因此运行结果有两种可能的变体。由于它们都是会话固定装置,因此我们应该期望run_result固定装置仅执行两次。
现在,请看一下测试用例test_run_result,它接收run_result和Expected_result夹具进行比较,并且还接收用两个值参数化的公差夹具。测试用例检查预期结果与结果之间的差异是否在公差范围内。注意,运行不取决于公差。
出于某种原因,我不理解Pytest会执行run_result()夹具三次。你能解释为什么吗?
这是使用pytest vers测试的。2.9.1
顺便说一句,如果未对测试用例进行参数化或使用装饰器而不是夹具对参数进行参数化,则run_result夹具将仅执行两次,即:@ pytest.mark.parametrize('tolerance',[1e-8,1e- 11])。
import pytest
runcounter = 0
@pytest.fixture(scope="session", params=[1e-8, 1e-11])
def tolerance(request):
"""Precision in floating point compare."""
return request.param
@pytest.fixture(scope='session', params=[1, 2])
def paramfixture(request):
return request.param
@pytest.fixture(scope="session")
def expected_result(paramfixture):
return 1 + paramfixture
@pytest.fixture(scope='session')
def run_result(paramfixture):
global runcounter
runcounter = runcounter + 1
print "Run #", runcounter, 'param:', paramfixture
return 1 + paramfixture
def test_run_result(run_result, expected_result, tolerance):
print "run_result: %d, expected_result: %d" % (run_result, expected_result)
assert abs(run_result - expected_result) < tolerance
Run Code Online (Sandbox Code Playgroud)
Pytest屏幕截图:
$ py.test -vs test/end2end/test_temp.py
===================================================== test session starts ======================================================
platform linux2 -- Python 2.7.11, pytest-2.9.1, py-1.4.31, pluggy-0.3.1 -- /home/f557010/.conda/envs/sfpdev/bin/python
cachedir: .cache
rootdir: /home/f557010/svndev/SFP, inifile: pytest.ini
collected 4 items
test/end2end/test_temp.py::test_run_result[1e-08-1] Run # 1 param: 1
run_result: 2, expected_result: 2
PASSED
test/end2end/test_temp.py::test_run_result[1e-08-2] Run # 2 param: 2
run_result: 3, expected_result: 3
PASSED
test/end2end/test_temp.py::test_run_result[1e-11-2]
run_result: 3, expected_result: 3
PASSED
test/end2end/test_temp.py::test_run_result[1e-11-1] Run # 3 param: 1
run_result: 2, expected_result: 2
PASSED
=================================================== 4 passed in 0.01 seconds ===================================================
Run Code Online (Sandbox Code Playgroud)
pytest 的参数化就是获取一个固定装置并在合理的生命周期内保留它。它不会缓存所有输入->输出映射。这不是您在这里所期待的,但如果您将固定装置视为数据库连接或 tcp 连接(如示例中的 smtp)之类的东西,那么它是有意义的。
您仍然有一个不错的论据可以在这里提出,即 pytest 方面足够的内省和优化将使您受益(假设这里 run_result 非常昂贵并且您希望最小化运行)。
为什么它在这里做“错误的事情”?如果仔细观察夹具,就会发现公差是“一阶”或最接近的参数化夹具。
一个丑陋、难以理解的改变却“有效”:
@pytest.fixture(scope="session", params=[0.01, 0.0002])
def tol(request):
"""Precision in floating point compare."""
return request.param
@pytest.fixture(scope="session")
def tolerance(tol):
"""Precision in floating point compare."""
return tol
Run Code Online (Sandbox Code Playgroud)
为什么这会起作用?它将公差参数删除到与其他灯具上的参数相同的“级别”。这样,pytest 实际上只运行 run_tests 两次。
============================================ test session starts ============================================
<snip>
collected 4 items
test_tolerance.py::test_run_result[1-0.01] Run # 1 param: 1
run_result: 2, expected_result: 2 tolerance: 0.010000
PASSED
test_tolerance.py::test_run_result[1-0.0002]
run_result: 2, expected_result: 2 tolerance: 0.000200
PASSED
test_tolerance.py::test_run_result[2-0.0002] Run # 2 param: 2
run_result: 3, expected_result: 3 tolerance: 0.000200
PASSED
test_tolerance.py::test_run_result[2-0.01]
run_result: 3, expected_result: 3 tolerance: 0.010000
PASSED
========================================= 4 passed in 0.01 seconds ==========================================
Run Code Online (Sandbox Code Playgroud)
您应该使用该代码吗?请尽量不要这么做,因为这太难理解了,如果你使用这样的 hack,请大量评论以“解释自己”。
您问“为什么”,这里的关键是容差和参数固定器的参数处于不同的嵌套级别,“最接近”的参数是迭代最慢的参数。固定装置不缓存在这里,它们只是按逻辑顺序使用,最里面的迭代速度最快。
| 归档时间: |
|
| 查看次数: |
733 次 |
| 最近记录: |