2014-02-13 74 views
16

我想按順序運行每個選定的py.test項目任意次數。
我沒有看到這樣做的任何標準的py.test機制。如何在py.test中多次重複每次測試?

我試圖在pytest_collection_modifyitems()掛鉤中執行此操作。我修改了傳入的項目列表,以便多次指定每個項目。測試項目的第一次執行按預期工作,但這似乎對我的代碼造成了一些問題。

此外,我寧願爲每次運行都有一個唯一的測試項目對象,因爲我在各種報告代碼中使用id(item)作爲關鍵字。不幸的是,我找不到任何py.test代碼來複制測試項目,copy.copy()不起作用,並且copy.deepcopy()得到一個異常。

有人可以提出多次執行測試的策略嗎?

回答

11

爲了運行每個測試的次數,因爲正在生成的測試中,我們將通過編程參數每個測試。

首先,讓我們添加解析器選項(包括下列之一的conftest.py的):

def pytest_addoption(parser): 
    parser.addoption('--repeat', action='store', 
     help='Number of times to repeat each test') 

現在我們添加一個「pytest_generate_tests」掛鉤。這是魔術發生的地方。

def pytest_generate_tests(metafunc): 
    if metafunc.config.option.repeat is not None: 
     count = int(metafunc.config.option.repeat) 

     # We're going to duplicate these tests by parametrizing them, 
     # which requires that each test has a fixture to accept the parameter. 
     # We can add a new fixture like so: 
     metafunc.fixturenames.append('tmp_ct') 

     # Now we parametrize. This is what happens when we do e.g., 
     # @pytest.mark.parametrize('tmp_ct', range(count)) 
     # def test_foo(): pass 
     metafunc.parametrize('tmp_ct', range(count)) 

運行而不重複標誌:

(env) $ py.test test.py -vv 
============================= test session starts ============================== 
platform darwin -- Python 2.7.5 -- py-1.4.20 -- pytest-2.5.2 -- env/bin/python 
collected 2 items 

test.py:4: test_1 PASSED 
test.py:8: test_2 PASSED 

=========================== 2 passed in 0.01 seconds =========================== 

與重複標誌運行:

(env) $ py.test test.py -vv --repeat 3 
============================= test session starts ============================== 
platform darwin -- Python 2.7.5 -- py-1.4.20 -- pytest-2.5.2 -- env/bin/python 
collected 6 items 

test.py:4: test_1[0] PASSED 
test.py:4: test_1[1] PASSED 
test.py:4: test_1[2] PASSED 
test.py:8: test_2[0] PASSED 
test.py:8: test_2[1] PASSED 
test.py:8: test_2[2] PASSED 

=========================== 6 passed in 0.01 seconds =========================== 

延伸閱讀:

+0

儘管這種方法可能工作,我用你的建議找到一個更簡單的方法,它不需要任何參數化的參數等我將它發佈和接受它作爲答案。感謝您的建議;它直接導致我的解決方案。 –

+0

工作在一個新項目上,所以我來這裏弄清楚我以前是如何做到這一點的。我現在明白,這個解決方案不需要我爲每個測試聲明一個夾具參數。所以我選擇這個答案是正確的,我在我的新項目中使用你的策略。謝謝! –

11

一個可能的策略是參數化有問題的測試,但不明確使用該參數。

例如:

@pytest.mark.parametrize('execution_number', range(5)) 
def run_multiple_times(execution_number): 
    assert True 

上述測試應運行五次。

退房參數化文檔:https://pytest.org/latest/parametrize.html

+0

這將執行測試在測試文件中指定的次數。它沒有達到我執行任意次數的目標,正如命令行選項所指定的那樣。 –

+0

我的歉意,我完全誤解了你的問題。我想我已經想出瞭如何做你想做的事情,我將添加另一個答案(因爲這是完全錯誤的:)。 –

+3

我很高興這個答案在這裏。我認爲這會增加未來用戶尋找可能解決方案的背景。 – moorecm

7

基於弗蘭克T的建議,我發現了pytest_generate_tests一個非常簡單的解決方案()標註:

parser.addoption ('--count', default=1, type='int', metavar='count', help='Run each test the specified number of times') 

def pytest_generate_tests (metafunc): 
    for i in range (metafunc.config.option.count): 
     metafunc.addcall() 

立即執行 「py.test --count 5」 使每個測試是在測試中執行五次。

而且它不需要修改我們現有的任何測試。

謝謝Frank T!

+1

metafunc.addcall()已被棄用,這就是爲什麼我在我的實現中首選.parametrize()。另請參閱:https://pytest.org/latest/parametrize.html#_pytest.python.Metafunc.addcall –

+0

您的解決方案要求我爲我的1,000個現有測試中的每一個添加一個參數/ funcarg,我不想做。 有可能是一個.parametrize()等價於我的簡單解決方案,但我無法弄清楚。 –

+1

在一個新項目上工作,所以我來這裏弄清楚我以前是如何做到這一點的。我現在明白你的解決方案不需要我爲每個測試聲明一個夾具參數。所以我選擇你的原始答案是正確的,我正在使用你的策略來處理我的新項目。謝謝! –

14

爲此目的pytest模塊pytest-repeat存在,我建議儘可能使用模塊,而不是自己重新實現它們的功能。

要使用它只需將pytest-repeat添加到您的requirements.txtpip install pytest-repeat,然後使用--count n執行您的測試。

相關問題