2015-01-01 18 views
6

我有一個名爲n_groups的燈具,我想在某些情況下進行參數化,但在其他情況下不能。原因是因爲我的MVC類數據模型的構造方式,我儘可能在「模型」類中進行測試,但「控制器」類不需要進行廣泛的測試,因爲我已經在「模型」中完成。因此,在控制器中運行所有參數化測試是多餘的,我想限制測試的次數以及測試時間。目前,爲了測試我的控制器的初始化,生成了超過18,000個測試,運行需要42分鐘!請參閱Travis-CI output在pytest的不同測試中只使用某些燈具參數化

目前,我的解決方法是做,

# Contents of conftest.py 
import pytest 
import pandas as pd 
import numpy as np 

@pytest.fixture(scope='module', params=[2, 3], 
       ids=['2_groups', '3_groups']) 
def n_groups(request): 
    """Number of phenotype groups. 

    For testing that functions work when there's only 2 groups 
    """ 
    return request.param 

@pytest.fixture(scope='module') 
def n_groups_fixed(): 
    """Fixed number of phenotype groups (3)""" 
    return 3 

然後,我通過其中n_groupsn_groups_fixed到測試創建數據燈具的下一個鏈。 outliers,pooled,samples,n_samplesmetadata_phenotype_col固定裝置也被參數化,但超出了這個問題的範圍。

# Contents of conftest.py 
@pytest.fixture(scope='module') 
def groups(n_groups): 
    """Phenotype group names""" 
    return ['group{}'.format(i + 1) for i in np.arange(n_groups)] 

@pytest.fixture(scope='module') 
def groups_fixed(n_groups_fixed): 
    """Phenotype group names""" 
    return ['group{}'.format(i + 1) for i in np.arange(n_groups_fixed)] 

@pytest.fixture(scope='module') 
def groupby(groups, samples): 
    return dict((sample, np.random.choice(groups)) for sample in samples) 

@pytest.fixture(scope='module') 
def groupby_fixed(groups_fixed, samples): 
    return dict((sample, np.random.choice(groups_fixed)) for sample in samples) 

@pytest.fixture(scope='module') 
def metadata_data(groupby, outliers, pooled, samples, 
        n_samples, 
        metadata_phenotype_col): 
    df = pd.DataFrame(index=samples) 
    if outliers is not None: 
     df['outlier'] = df.index.isin(outliers) 
    if pooled is not None: 
     df['pooled'] = df.index.isin(pooled) 
    df[metadata_phenotype_col] = groupby 
    df['subset1'] = np.random.choice([True, False], size=n_samples) 
    return df 

@pytest.fixture(scope='module') 
def metadata_data_groups_fixed(groupby_fixed, outliers, pooled, samples, 
        n_samples, 
        metadata_phenotype_col): 
    df = pd.DataFrame(index=samples) 
    if outliers is not None: 
     df['outlier'] = df.index.isin(outliers) 
    if pooled is not None: 
     df['pooled'] = df.index.isin(pooled) 
    df[metadata_phenotype_col] = groupby_fixed 
    df['subset1'] = np.random.choice([True, False], size=n_samples) 
    return df 

似乎相當麻煩有*_fixed版本這些燈具。

測試的實例將是數據模型中測試的n_groups兩個參數化內的廣泛的測試,和控制器,它僅測試一個「參數化」使用groups_fixed內的更少廣泛試驗(這些是不是真正的試驗,只是示範示例):

# Contents of test_model.py 
class TestModel(object): 
    def test__init(metadata_data, ...): 
     ... 

    def test_plot(metadata_data_fixed, ...); 
     ... 

# Contents of test_controller.py 
class TestController(object): 
    def test__init(metadata_data_fixed, ...): 
     ... 

是否有另一種方法可以做到這一點?我已閱讀pytest的parameterize文檔,但似乎只是在全局範圍內設置參數,而不是按照每個測試。

我想這樣做:

# Contents of test_model.py 
class TestModel(object): 
    def test__init(metadata_data, ...): 
     ... 

    @pytest.mark.parameterize(n_groups=3) 
    def test_plot(metadata_data, ...); 
     ... 

# Contents of test_controller.py 
class TestController(object): 
    @pytest.mark.parameterize(n_groups=3) 
    def test__init(metadata_data_fixed, ...): 
     ... 

UPDATE:內TestController添加一個n_groups夾具沒有幫助,即這不起作用:

# Contents of test_controller.py 
class TestController(object): 
    @pytest.fixture 
    def n_groups(): 
     return 3 

    def test__init(metadata_data_fixed, ...): 
     ... 

我不知道爲什麼,因爲看起來這個夾具應該覆蓋全球n_groups定義在conftest.py

回答

0

我不是sur e你可以用內建parametrize來做到這一點,我想你將不得不實施一個基於正在測試的方法的一些信息的自定義參數化方案(例如,如果一個類的名稱中包含Controller,那麼它將以不同方式參數化),使用pytest_generate_tests hook。一些例子可以發現here

+0

謝謝!這適用於'TestController',因爲我可以在'test_controller.py'文件中找到它,並且將應用於文件中的所有測試。對於'TestModel',我會考慮檢查'metafunc.function .__ name__'來檢查嗎?看起來這種東西可以封裝在一個裝飾器中用於測試功能。你知道這樣的功能是否計劃在'pytest'中嗎? –

+0

是的,檢查metafunc.function .__ name__會起作用。不過,我不認爲有任何計劃將其作爲內置裝飾器來實現。 –