pytest参数化会话夹具执行次数太多

时间:2016-09-27 16:12:06

标签: python pytest

考虑以下测试代码,该代码将模拟运行结果与预期结果进行比较。运行结果的值取决于参数化夹具paramfixture的值,该值提供两个值,因此运行结果有两种可能的变体。由于它们都是会话装置,我们应该期望run_result装置只执行两次。

现在,请查看测试用例test_run_result,它接收要比较的run_result和expected_result灯具,并且还接收公差夹具,该夹具使用两个值进行参数化。测试用例检查预期和结果之间的差异是否在容差范围内。请注意,运行不依赖于公差。

出于某种原因,我不明白Pytest执行run_result()夹具三次。你能解释一下原因吗?

这是使用pytest vers测试的。 2.9.1

顺便说一下,如果测试用例没有参数化或者使用decoractor而不是fixture进行参数化,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

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 ===================================================

2 个答案:

答案 0 :(得分:1)

pytest的参数化就是获得一个固定装置并坚持使用一段合理的生命周期。它不会缓存所有输入&gt;输出映射。这不是你在这里所说的,但如果你认为fixtures是数据库连接或tcp连接(比如示例中的smtp),那就没有意义。

你仍然有一个不错的论据,在pytest的部分进行足够的内省和优化会使你受益(假设run_result非常昂贵并且你希望最小化运行)。

为什么这样做&#34;错误的事情&#34;这里?如果你仔细看看灯具,公差是第一顺序&#34;或最接近的参数化夹具。

一个丑陋,不可理喻的变化,&#34;起作用&#34;:

@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

为什么这个世界会起作用?它将容差参数移除到相同的水平&#34;作为其他灯具的参数。有了这个,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 ==========================================

您应该使用该代码吗?请尽量不要,因为它太难以理解,如果你使用这样的黑客,请大力评论自己。

你问&#34;为什么&#34;这里的关键是宽容和paramfixture的参数在与#34;最接近的&#34;嵌套的不同层次上。一个是迭代最慢的一个。夹具没有在这里缓存,它们只是按逻辑顺序使用,最里面的迭代最快。

答案 1 :(得分:0)

它似乎运行了4次测试,而不是3次,如果它正在进行全组合运行,这是有道理的。

  • 运行#1:Param 1,Tolerance 1
  • 运行#2:Param 2,Tolerance 1
  • 运行#3:Param 1,Tolerance 2
  • Run#4:Param 2,Tolerance 2

在给定测试定义的情况下,运行四次似乎是一种合理的方法。