2017-08-08 49 views
1

是否有辦法指定pytestpytest.mark.parametrize()參數的可調用參數,以便僅在選擇運行測試時動態生成參數?如何使用callable作爲pytest參數ize()參數?

我有一些昂貴的操作要執行以生成參數,我只想執行它們,如果測試被選中運行。

例如,

import pytest 

def my_callable(): 
    # do expensive operations here 
    return [(1, 2), (3, 6)] 


# I want my_callable to be called only if test_something 
# has been selected to be run 
@pytest.mark.parametrize("my_parm_1,my_parm_2", my_callable) 
def test_something(my_parm_1, my_parm_2): 
    assert my_parm_1 * 2 == my_parm_2 
+0

這一切似乎都是pytest方面的一個小缺陷。也許值得考慮用pytest提交一個bug,以便延遲評估參數到裝飾測試運行的時刻(或者添加一個裝飾參數來實現這一點)... – sophros

回答

0

,而不是直接使用@pytest.mark.parametrizemycallable,你可以創建一個代理:

def my_callable(): 
    # do expensive operations here 
    return [(1, 2), (3, 6)] 

expensive_params = [paramset for paramset in my_callable()] 

@pytest.mark.parametrize("my_parm_1,my_parm_2", expensive_params) 
... 
+0

適用於Python 3.6.1和pytest 3.2 .0 – sophros

+1

但是如果「我只想在測試被選擇運行時執行它們」呢? 'expensive_params'是全局變量,即使未選擇測試,它也會始終被評估,不是嗎? –

+0

同意。 'expensive_params'總是在編譯時進行評估,而我希望只在測試運行時才評估它。 –

0

我想這是你想要的東西 - 昂貴的計算是燈具內部哪些僅在調用測試並且昂貴的計算僅進行一次時才被調用:

class TestSomething: 

    _result = None 

    @pytest.fixture() 
    def my_callable(self): 
     if TestSomething._result is None: 
      # do expensive operations here 
      TestSomething._result = [(1, 2), (3, 6)] 

     def _my_callable(run_number): 
      return TestSomething._result[run_number] 
     return _my_callable 

    @pytest.mark.parametrize("run_number", [0, 1]) 
    def test_something(self, run_number, my_callable): 
     my_param_1, my_param_2 = my_callable(run_number) 
     assert my_param_1 * 2 == my_param_2 
+0

儘管這會將昂貴的操作移動到測試運行時,但它還會強制代碼事先知道由my_callable()返回的可迭代的長度。不幸的是,我不知道迭代器的長度 - 昂貴的操作動態地決定了迭代器的長度。 Iteresting解決方案,但它不完全符合我的要求。 此外,這個解決方案沒有在用pytest -v運行時看到測試名稱中的參數值的好處。只會看到「run_number」。 –

+0

@RobBednark考慮到參數的數目是未知的,唯一想到的其他事情是刪除'parametrize',使用上面的fixture並在測試代碼內部遍歷一組參數。有點難看,但它會起作用。 –

+0

是的,我考慮在單個測試中循環參數。我希望得到一個'parametrize'解決方案,其中每組參數都是它自己的測試,而不是將它們集中到一個測試中。 –