2011-02-07 30 views
15

Najpierw pytanie, a następnie wyjaśnienie, jeśli jesteś zainteresowany.Generowanie testów py.test w python

W kontekście py.test, w jaki sposób wygenerować duży zestaw funkcji testowych z małego zestawu szablonów funkcji testowych?

Coś jak:

models = [model1,model2,model3] 
data_sets = [data1,data2,data3] 

def generate_test_learn_parameter_function(model,data): 
    def this_test(model,data): 
     param = model.learn_parameters(data) 
     assert((param - model.param) < 0.1) 
    return this_test 

for model,data in zip(models,data_sets): 
    # how can py.test can see the results of this function? 
    generate_test_learn_parameter_function(model,data) 

Objaśnienie:

Próbuję ciężko dostać się do testów jednostkowych. Koduję dla "nauki", ponieważ piszę kod, który, jak sądzę, jest skomplikowany matematycznie, ale nie aż tak źle z punktu widzenia programowania, tj. Mam do wyboru pięć funkcji do przetestowania. To, że pochodzę z "nauki" oznacza, że ​​jestem całkiem nowy w testowaniu jednostkowym, ale przekonałem moich kumpli z CS, że to The Thing To Do.

Kod, który piszę, ma strukturę modelu, niektóre dane i uczy się parametrów modelu. Zatem moje testy jednostkowe składają się z kilku struktur modelowych i wstępnie wygenerowanych zestawów danych, a następnie zestawu około 5 zadań uczenia maszynowego, które należy wykonać dla każdej struktury + danych.

Więc jeśli to zaksięguję, potrzebuję jednego testu na model na zadanie. Za każdym razem, gdy wymyślam nowy model, muszę skopiować i wkleić 5 zadań, zmieniając, która marynowana struktura + dane wskazuję. Wydaje mi się, że to kiepska praktyka. Idealnie byłoby 5 funkcji szablonu, które definiują każde z 5 zadań, a następnie wypluwają funkcje testowe dla listy struktur, które określam.

Googling o prowadzi mnie do a) fabryk lub b) zamknięć, z których oba powodują mój mózg i sugerują mi, że musi być łatwiejszy sposób, ponieważ problem ten musi być regularnie napotykany przez odpowiednich programistów. Więc jest tam?


EDYCJA: A oto jak rozwiązać ten problem!

def pytest_generate_tests(metafunc): 
    if "model" in metafunc.funcargnames: 
     models = [model1,model2,model3] 
     for model in models: 
      metafunc.addcall(funcargs=dict(model=model)) 

def test_awesome(model): 
    assert model == "awesome" 

ten będzie miał zastosowanie testu test_awesome do każdego modelu w moim liście modeli! Dzięki @dfichter!

(UWAGA: Zawsze twierdzą, że przechodzi, btw)

+0

Generalnie jest to zły pomysł, aby wygenerować kod testowy dynamicznie tak. Ponieważ musisz napisać testy kodu testowego itp. "Skopiuj i wklej 5 zadań" Myślę, że to pokazuje, że zamiast generować nowy kod lub wklejać kopie, możesz znaleźć podobieństwa, które twoje funkcje mogą przetestować, nie wiedząc dokładnie, co one "Testowanie. – Falmarri

+2

W tej chwili piszę testy, które wyglądają jak def test_learn: dla modelu w modelach: assert (błąd

+1

@Falmarri: http://en.wikipedia.org/wiki/Copy_and_paste_programming Unikajcie tego prawie na wszystkie koszty. – lpapp

Odpowiedz

15

dobre instynkty. py.test obsługuje dokładnie to, o czym mówisz, dzięki haczykowi pytest_generate_tests(). Wyjaśniają to here.

+0

To jest niesamowite. Będę edytować moje pytanie, aby dodać to, co zrobiłem w końcu, na wypadek, gdyby ktoś tu przyszedł szukając podobnych rzeczy .. –

+0

dfichter, czy mógłbyś podać przykładowy wiersz do OP? – lpapp

+0

To jest teraz uszkodzony link –

4

Możesz to również zrobić, używając parametrized fixtures. Haczyki to API do budowania wtyczek dla Py.test, sparametryzowane urządzenia to uogólniony sposób tworzenia urządzeń, które generują wiele wartości i generują dla nich dodatkowe przypadki testowe.

Wtyczki mają być niektórymi funkcjami obejmującymi cały projekt (lub pakietami), a nie specyficzne dla testowania i sparametryzowane urządzenia są dokładnie tym, czego potrzeba do parametryzowania niektórych zasobów dla przypadków testowych.

Więc rozwiązaniem mogłoby być zapisane jako że:

@pytest.fixture(params=[model1, model2, model3]) 
def model(request): 
    return request.param 

def test_awesome(model): 
    assert model == "awesome" 
Powiązane problemy