2015-01-01 23 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__会起作用。不过,我不认为有任何计划将其作为内置装饰器来实现。 –