2016-09-27 24 views
3

請考慮以下測試代碼,它將模擬運行結果與預期結果進行比較。運行結果的值取決於參數化夾具paramfixture的值,該參數提供了兩個值,因此有兩種可能的運行結果變量。由於它們都是會話裝置,因此我們應該期望run_result fixture只執行兩次。Pytest參數化會話夾具執行的次數太多

現在,請查看測試用例test_run_result,它接收要比較的run_result和expected_result燈具,並接收容差夾具,該夾具用兩個值進行參數化。測試用例檢查預期和結果之間的差異是否在容差範圍內。請注意,運行不依賴於容差。

由於某些原因,我不明白Pytest執行run_result()三次。你能解釋爲什麼嗎?

這是使用pytest進行測試。 2.9.1

順便說一句,如果測試用例沒有被參數化,或者使用decoractor而不是夾具進行參數化,那麼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 =================================================== 

回答

1

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 

世界爲什麼將這項工作?它將公差參數移除到與其他設備上的參數相同的「等級」。有了這個,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 ========================================== 

你應該使用的代碼?請儘量不要,因爲這太難了,如果你使用這種黑客攻擊,請嚴肅評論自己。

你問「爲什麼」,這裏的關鍵是容差和paramfixture的參數處於不同的嵌套層次,而「最接近」的是最慢的迭代層次。燈具不在這裏緩存,它們只是按照邏輯順序使用,最內層迭代速度最快。

0

這似乎是運行測試的4倍,而不是3,這是有道理的,如果它做的所有組合運行。

  • 試驗#1:參數1,容差1
  • 執行命令#2:參數2,容差1
  • 試驗#3:參數1,偏差2
  • 執行命令#4:參數2,公差2

對我來說,運行四次似乎是考慮到測試定義的合理方法。

+0

您使用的是哪個版本的py.test?夾具只需要運行兩次,但會有四個測試排列:2個參數x 2個容差水平。 –