Jako kontynuacja poprzedniej odsłony z serii pyTest Tutorial, skupimy się na parametrach z którymi możemy uruchomić pyTest’a, pod kątem testów zakończonych niepowodzeniem. Jeśli po poprzedniej części myślicie, że uruchamianie testów z parametrami nie ma przed wami tajemnic – zapraszam do lektury poniższego tekstu! Jak w całym tutorialu, większość opisywanych parametrów poprę odpowiednimi przykładami. W tej części bazujemy na stworzonym drzewie testów z poprzedniego artykułu z tej serii:
├── base.py├── calculation_test.py├── test_calc.py├── other└── test_calc└── subfolder├──test_calculator.py└── calculator.py
Na obecne potrzeby musimy dokonać małej modyfikacji w pliku test_calc.py, w którym zmienimy asercję w teście test_addition, oraz w pliku calculation_test.py zmienimy w teście test_subtraction, zgodnie z poniższym:
test_calc.py def test_addition(): (...) assert object.show_result()[0] == 11 calculation_test.py def test_subtraction(): (...) assert object.show_result()[0] == 8
Wynik testów niezaliczonych
Zacznijmy może od przyjrzenia się, co się stanie, gdy test zakończy się niepowodzeniem:
(env) qabrio@test:~/basic_calculator$ pytest test_calc.py::test_addition========================================= test session starts =========================================platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1rootdir: /home/qabrio/basic_calculator, inifile:collected 1 itemtest_calc.py F [100%]=============================================== FAILURES ==============================================____________________________________________ test_addition ____________________________________________def test_addition():object = BasicCalculator()object.provide_number(10)object.provide_operand('+')object.provide_number(5)> assert object.show_result()[0] == 11E assert 15 == 11test_calc.py:9: AssertionError---------------------------------------- Captured stdout call -----------------------------------------10 + 5 = 15====================================== 1 failed in 0.01 seconds =======================================(env) qabrio@test:~/basic_calculator$
Jak widzimy, dostaliśmy sporo informacji. W pierwszej części test session start, będącej niejako streszczeniem tego co działo się testach, przy test_calc.py znajduje się oznaczenie F (zamiast kropki). Oznacza to, że wykonał się jeden test, który dał wynik negatywny. Najbardziej interesująće rzeczy, są umieszczone poniżej w FAILURES, czyli części w której są zawarte detale dotyczące niezaliczonych testów. Mamy tam informacje dotyczące konkretnej linii w kodzie, która wywołała niezaliczenie testu. Ponadto znajduje się tam opis niezaliczonej asercji wraz z przyrównaniem konkretnych wartości. Poniżej jest jeszcze zawarty rezultat z testu, niezależnie czy użyliśmy opcji -s czy nie. Szukanie przyczyny z takimi informacjami staje się znacznie łatwiejsze.
Zarządzanie szczegółami testów niezaliczonych
Jeśli opis negatywnego rezultatu jest dla kogoś nieodpowiedni, istnieje możliwość jego zmiany. Głownie chodzi tutaj o ograniczenie wyświetlania logów, gdyż domyślnie widzimy pełne informacje. Rezultat możemy ograniczyć wykorzystując parametr –tb, który może przyjmować następujące wartości:
– auto lub long – domyślna długość detali, jak w poprzednim przykładzie,
– line – jedna linia z detalami:
(env) qabrio@test:~/basic_calculator$ pytest test_calc.py::test_addition --tb=line========================================= test session starts =========================================platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1rootdir: /home/qabrio/basic_calculator, inifile:collected 1 itemtest_calc.py F [100%]============================================== FAILURES ===============================================/home/qabrio/basic_calculator/test_calc.py:9: assert 15 == 11====================================== 1 failed in 0.01 seconds =======================================(env) qabrio@test:~/basic_calculator$
– native – detale w języku natywnym:
(env) qabrio@test:~/basic_calculator$ pytest test_calc.py::test_addition --tb=native========================================= test session starts =========================================platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1rootdir: /home/qabrio/basic_calculator, inifile:collected 1 itemtest_calc.py F [100%]============================================== FAILURES ===============================================____________________________________________ test_addition ____________________________________________Traceback (most recent call last):File "/home/qabrio/basic_calculator/test_calc.py", line 9, in test_additionassert object.show_result()[0] == 11AssertionError: assert 15 == 11----------------------------------------- Captured stdout call ----------------------------------------10 + 5 = 15====================================== 1 failed in 0.00 seconds =======================================(env) qabrio@test:~/basic_calculator$
– no – brak detali niepowodzenia:
(env) qabrio@test:~/basic_calculator$ pytest test_calc.py::test_addition --tb=no========================================= test session starts =========================================platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1rootdir: /home/qabrio/basic_calculator, inifile:collected 1 itemtest_calc.py F [100%]======================================= 1 failed in 0.01 seconds ======================================(env) qabrio@test:~/basic_calculator$
– short – ograniczenie do kilku linii, brak logów:
(env) qabrio@test:~/basic_calculator$ pytest test_calc.py::test_addition --tb=short========================================= test session starts =========================================platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1rootdir: /home/qabrio/basic_calculator, inifile:collected 1 itemtest_calc.py F [100%]============================================== FAILURES ===============================================____________________________________________ test_addition ____________________________________________test_calc.py:9: in test_additionassert object.show_result()[0] == 11E assert 15 == 11--------------------------------------- Captured stdout call ------------------------------------------10 + 5 = 15======================================= 1 failed in 0.01 seconds ======================================(env) qabrio@test:~/basic_calculator$
Dodatkowym parametrem, który może nam pomóc w analizowaniu przyczyn niezaliczenia testu jest —showlocals, lub -l. Dzięki temu w podsumowaniu na końcu dostaniemy informacje o stanie zmiennych użytych w teście. W naszym przypadku wykorzystujemy tylko i wyłącznie jedną, czyli zmienną object, co widać na poniższym wycinku z konsoli:
(env) qabrio@test:~/basic_calculator$ pytest calculation_test.py::test_subtraction -l================================================ test session starts ================================================platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1rootdir: /home/qabrio/basic_calculator, inifile:collected 1 itemcalculation_test.py F [100%]===================================================== FAILURES ======================================================_________________________________________________ test_subtraction __________________________________________________def test_subtraction():object = BasicCalculator()object.provide_number(13)object.provide_operand('-')object.provide_number(21)> assert object.show_result()[0] == 8E assert -8 == 8object =calculation_test.py:17: AssertionError----------------------------------------------- Captured stdout call ------------------------------------------------13 - 21 = -8============================================= 1 failed in 0.01 seconds ==============================================(env) qabrio@test:~/basic_calculator$
Przerywanie testów w przypadku błędów
Kolejny ciekawy parametr, który może się przydać, przerywa wykonywanie testów po pojawieniu się określonej liczby niezaliczonych testów. Chodzi o parametr —maxfail. Jeśli chcemy, aby testy zostały przerwane po pierwszym napotkanym fail‚u, należy użyć —maxfile=1 lub alternatywnie -x czy —exitfirst:
qabrio@test:~/basic_calculator$ pytest --tb=no -x========================================= test session starts =========================================platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1rootdir: /home/qabrio/basic_calculator, inifile:collected 6 itemscalculation_test.py .F================================= 1 failed, 1 passed in 0.01 seconds ==================================qabrio@test:~/basic_calculator$ pytest --tb=no --maxfail=2========================================= test session starts =========================================platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1.0rootdir: /home/qabrio/basic_calculator, inifile:collected 6 itemscalculation_test.py .F [ 33%]test_calc.py F================================ 2 failed, 1 passed in 0.02 seconds ===================================qabrio@test:~/basic_calculator$
Opcje cache'owania
PyTest wykorzystuje cache’owanie, co okazuje się bardzo użyteczne. Jedną z opcji, jest możliwość uruchomienia tylko tych testów, które w ostatnim uruchomieniu zakończyły się niepowodzeniem. Wykorzystujemy do tego flagę —lf (—last-failed):
(env) qabrio@test:~/basic_calculator$ pytest --tb=no========================================= test session starts =========================================platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1rootdir: /home/qabrio/basic_calculator, inifile:collected 6 itemscalculation_test.py .F [ 33%]test_calc.py F. [ 66%]subfolder/test_calculator.py .. [100%]================================= 2 failed, 4 passed in 0.02 seconds ==================================(env) qabrio@test:~/basic_calculator$ pytest --tb=no --lf========================================= test session starts =========================================platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1rootdir: /home/qabrio/basic_calculator, inifile:collected 6 itemsrun-last-failure: rerun previous 2 failurescalculation_test.py F [ 50%]test_calc.py F [100%]=========================================== 4 tests deselected ======================================================================= 2 failed, 4 deselected in 0.02 seconds ================================(env) qabrio@test:~/basic_calculator$
Podobne działanie do powyższego ma parametr -ff lub —first-failed, który określa, że wszystkie testy, które ostatnio nie przeszły, będą wykonane jako pierwsze, a po nich zostaną wykonane pozostałe testy.
(env) qabrio@test:~/basic_calculator$ pytest --tb=no========================================= test session starts =========================================platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1rootdir: /home/qabrio/basic_calculator, inifile:collected 6 itemscalculation_test.py .F [ 33%]test_calc.py F. [ 66%]subfolder/test_calculator.py .. [100%]================================= 2 failed, 4 passed in 0.02 seconds ==================================(env) qabrio@test:~/basic_calculator$ pytest --tb=no --ff========================================= test session starts =========================================platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1rootdir: /home/qabrio/basic_calculator, inifile:collected 6 itemsrun-last-failure: rerun previous 2 failures firstcalculation_test.py F [ 16%]test_calc.py F [ 33%]calculation_test.py . [ 50%]test_calc.py . [ 66%]subfolder/test_calculator.py .. [100%]================================= 2 failed, 4 passed in 0.02 seconds ==================================(env) qabrio@test:~/basic_calculator$
Poznaliśmy już większość najbardziej przydatnych parametrów uruchamiania testów w pyTest’cie, które wpływają na wybór testów, ich kolejność czy raportowanie. Nie trzeba ich oczywiście znać na pamięć, gdyż zawsze można skorzystać z parametru —help, dzięki któremu otrzymamy podstawy opis wszystkich parametrów.