pyTest Tutorial #3: Uruchamianie testów z parametrami – ciąg dalszy

pyTest Tutorial #3: Parametry uruchamiania testów - ciąg dalszy

Poziom trudności
2/5

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:

  1. test_calc.py
  2. def test_addition():
  3. (...)
  4. assert object.show_result()[0] == 11
  5. calculation_test.py
  6. def test_subtraction():
  7. (...)
  8. 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.1
rootdir: /home/qabrio/basic_calculator, inifile:
collected 1 item
test_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] == 11
E assert 15 == 11
test_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.1
rootdir: /home/qabrio/basic_calculator, inifile:
collected 1 item
test_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.1
rootdir: /home/qabrio/basic_calculator, inifile:
collected 1 item
test_calc.py F [100%]
============================================== FAILURES ===============================================
____________________________________________ test_addition ____________________________________________
Traceback (most recent call last):
File "/home/qabrio/basic_calculator/test_calc.py", line 9, in test_addition
assert object.show_result()[0] == 11
AssertionError: 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.1
rootdir: /home/qabrio/basic_calculator, inifile:
collected 1 item
test_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.1
rootdir: /home/qabrio/basic_calculator, inifile:
collected 1 item
test_calc.py F [100%]
============================================== FAILURES ===============================================
____________________________________________ test_addition ____________________________________________
test_calc.py:9: in test_addition
assert object.show_result()[0] == 11
E 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.1
rootdir: /home/qabrio/basic_calculator, inifile:
collected 1 item
calculation_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] == 8
E assert -8 == 8
object =
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.1
rootdir: /home/qabrio/basic_calculator, inifile:
collected 6 items
calculation_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.0
rootdir: /home/qabrio/basic_calculator, inifile:
collected 6 items
calculation_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.1
rootdir: /home/qabrio/basic_calculator, inifile:
collected 6 items
calculation_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.1
rootdir: /home/qabrio/basic_calculator, inifile:
collected 6 items
run-last-failure: rerun previous 2 failures
calculation_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.1
rootdir: /home/qabrio/basic_calculator, inifile:
collected 6 items
calculation_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.1
rootdir: /home/qabrio/basic_calculator, inifile:
collected 6 items
run-last-failure: rerun previous 2 failures first
calculation_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.

Dodaj komentarz