2016-03-03 105 views
3

我目前正在爲中型庫(約300個文件)編寫測試。 很多類在這個庫共享其使用pytest編碼相同的測試方案:pytest燈具夾具

文件test_for_class_a.py:爲class_b,class_c等存在

import pytest 

@pytest.fixture() 
def setup_resource_1(): 
    ... 

@pytest.fixture() 
def setup_resource_2(): 
    ... 

@pytest.fixture() 
def setup_class_a(setup_resource_1, setup_resource_2): 
    ... 

def test_1_for_class_a(setup_class_a): 
    ... 

def test_2_for_class_a(setup_class_a): 
    ... 

類似的文件。唯一的區別是內容setup_resource_1 & setup_resource_2。

現在我想重新使用test_for_class_a.py,test_for_class_b.py和test_for_class_c.py中定義的固件setup_class_a,setup_class_b,setup_class_c對它們運行測試。

在一個文件test_all_class.py,這工作,但它是每個測試限制在一個固定設備:

from test_for_class_a import * 

@pytest.mark.usefixtures('setup_class_a')  # Fixture was defined in test_for_class_a.py 
def test_some_things_on_class_a(request) 
    ... 

但是我正在尋找一種方式來執行更多的東西一般:

from test_for_class_a import * 
from test_for_class_b import * # I can make sure I have no collision here 
from test_for_class_c import * # I can make sure I have no collision here 

==> @generate_test_for_fixture('setup_class_a', 'setup_class_b', 'setup_class_c') 
def test_some_things_on_all_classes(request) 
    ... 

有沒有什麼辦法可以做到這一點? 我一直在尋找工廠和抽象pytest工廠的工廠,但我正在努力pytest定義夾具的方式。 有什麼辦法可以解決這個問題嗎?

回答

0

一個解決方案,我發現是濫用測試案例如下:

from test_for_class_a import * 
from test_for_class_b import * 
from test_for_class_c import * 

list_of_all_fixtures = [] 


# This will force pytest to generate all sub-fixture for class a 
@pytest.mark.usefixtures(setup_class_a) 
def test_register_class_a_fixtures(setup_class_a) 
    list_of_fixtures.append(setup_class_a) 


# This will force pytest to generate all sub-fixture for class b 
@pytest.mark.usefixtures(setup_class_b) 
def test_register_class_b_fixtures(setup_class_b) 
    list_of_fixtures.append(setup_class_b) 


# This will force pytest to generate all sub-fixture for class c 
@pytest.mark.usefixtures(setup_class_c) 
def test_register_class_b_fixtures(setup_class_c) 
    list_of_fixtures.append(setup_class_c) 


# This is the real test to apply on all fixtures 
def test_all_fixtures(): 
    for my_fixture in list_of_all_fixtures: 
     # do something with my_fixture 

這含蓄地依賴於所有test_all_fixture是所有test_register_class *之後執行的事實。這顯然很骯髒,但它的工作原理...

2

我們在工作中有同樣的問題,我希望每個案件只寫一次夾具。所以我寫了插件pytest-data這是做。例如:

@pytest.fixture 
def resource(request): 
    resource_data = get_data(reqeust, 'resource_data', {'some': 'data', 'foo': 'foo'}) 
    return Resource(resource_data) 

@use_data(resource_data={'foo': 'bar'}) 
def test_1_for_class_a(resource): 
    ... 

@use_data(resource_data={'foo': 'baz'}) 
def test_2_for_class_a(resource): 
    ... 

什麼是偉大的關於它是你寫的夾具只是一些默認設置一次。當你只需要那個燈具/資源而你不關心具體的設置時,你就可以使用它。當你需要測試一些特定的屬性時,讓我們來看看這個資源是否可以處理100個字符長的值,你可以通過use_data修飾器來傳遞它,而不是寫另一個fixture。

因爲你不必關心衝突,因爲一切都會在那裏一次。然後,您可以將conftest.py用於您的所有燈具,而無需導入測試模塊。例如,我們確實分開了所有燈具的深層模塊,並且全部包含在頂部conftest.py中。

插件文檔pytest-datahttp://horejsek.github.io/python-pytest-data/