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

Ciąg dalszy poprzedniej części serii pyTest Tutorial. W tej części kolejny zestaw parametrów w odniesieniu do testów niezaliczonych.

Pytest Tutorial

Pytest Tutorial


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.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 =======================================

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 =======================================
  • – 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 =======================================
  • – 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 ======================================
  • – 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 ======================================

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 ==============================================

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 ===================================

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 ================================

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 ==================================

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.

close

Newsletter