Ho un dispositivo chiamato n_groups
che vorrei parametrizzare in alcuni casi, ma non in altri. La ragione di questo è dovuta al modo in cui è strutturato il mio modello di dati simile a MVC, provo il più possibile nelle classi "modello", ma le classi "controller" non hanno bisogno di test così estesi perché ho già fatto nel "modello". Quindi l'esecuzione dei test con tutte le parametrizzazioni è ridondante nel controller e vorrei limitare il numero di test e quindi il tempo di test. Attualmente per testare l'inizializzazione del mio controller, vengono generati oltre 18.000 test e ci vogliono 42 minuti per essere eseguito! Vedi lo Travis-CI output.Utilizzare solo alcune parametrizzazioni di fixture in diversi test in pytest
Attualmente, il mio soluzione è quello di fare,
# 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
Poi, passo sia n_groups
o n_groups_fixed
alla prossima catena di apparecchi che creano i dati per il test. Gli apparecchi outliers
, , samples
, n_samples
e metadata_phenotype_col
sono anche parametrizzati, ma non rientrano nell'ambito di questa domanda.
# 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
sembra piuttosto ingombrante per avere una versione *_fixed
per ciascuno di questi apparecchi.
Esempi di prove sarebbero una serie di test all'interno del modello dati testare entrambi parametrizzazioni n_groups
, e meno estesa prova all'interno del regolatore, che verifica una sola "parametrizzazione" utilizzando groups_fixed
(queste non sono prove reali, basta esempi per dimostrazione):
# 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, ...):
...
C'è un altro modo per farlo? Ho letto la documentazione di pytest parameterize, ma sembra solo impostare le parametrizzazioni a livello globale e non in base al test.
mi piacerebbe fare qualcosa di simile:
# 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: Aggiunta di un n_groups
apparecchio all'interno TestController
non aiuta, vale a dire questo non funziona:
# Contents of test_controller.py
class TestController(object):
@pytest.fixture
def n_groups():
return 3
def test__init(metadata_data_fixed, ...):
...
Sono non so perché, perché sembra che questa apparecchiatura dovrebbe sovrascrivere il globale n_groups
definito in conftest.py
Grazie! Questo funziona per 'TestController' perché posso averlo nel file' test_controller.py', e si applicherebbe a tutti i test nel file. Per 'TestModel', dovrei controllare' metafunc.function .__ name__' per controllare lì? Sembra che questo genere di cose possa essere incapsulato in un decoratore per le funzioni di test. Sai se una tale funzionalità è pianificata in 'pytest'? –
Sì, controlla metafunc.function .__ name__ potrebbe funzionare. Non penso che ci siano piani per implementarlo come un decoratore incorporato, però. –