pyTest Tutorial #2: Uruchamianie testów z parametrami

W części drugiej Tutorial’a pyTest’a skupimy się na sposobach uruchamianiu testów z wybranymi parametrami.

Pytest Tutorial

Pytest Tutorial


W poprzedniej serii pyTest Tutorial części poznaliśmy garść ogólnych informacji dotyczących pyTest‚a, a także jak go zainstalować. Dodatkowo stworzyliśmy dwa testy (test_calc.py). W tej części dowiemy się węcej, jak wygląda uruchamianie testów z różnymi parametrami:

  • test_addition
  • test_subtraction

Z tej części dowiemy się o:

  • wyświetleniu kolekcji testów bez uruchamiania,
  • uruchomieniu wszystkich testów,
  • uruchomieniu tylko wybranych testów,
  • przeszukiwaniu testów,
  • podstawowych opcjach raportowania.

Na potrzeby tej części skopiujmy plik z testami, wykorzystując poniższe komendy:

(env) qabrio@test:~/basic_calculator$ mkdir subfolder
(env) qabrio@test:~/basic_calculator$ mkdir other
(env) qabrio@test:~/basic_calculator$ cp test_calc.py calculation_test.py
(env) qabrio@test:~/basic_calculator$ cp test_calc.py subfolder/test_calculator.py
(env) qabrio@test:~/basic_calculator$ cp test_calc.py subfolder/calculator.py
(env) qabrio@test:~/basic_calculator$ cp test_calc.py other/test_calc

Powinniśmy otrzymać drzewo katalogów jak poniżej:

|___ base.py
|___ calculation_test.py
|___ test_calc.py
|___ other
      |__ test_calc
|___ subfolder
      |__ test_calculator.py
      |__ calculator.py

Wyświetlanie kolekcji testów

W tej odsłonie zapoznamy się z różnymi opcjami uruchamiania testów oraz przeanalizujemy otrzymane rezultaty. Na początek przyjrzyjmy się bliżej poleceniu pytest z flagą —collect-only. Powoduje ona, że testy nie będą wykonywane, lecz dostaniemy informacje o dostępnych testach:

(env) (env) qabrio@test:~/basic_calculator$ pytest --collect-only
======================================== test session starts =======================================
platform linux2 -- Python 2.7.17, pytest-3.3.2, py-1.5.2, pluggy-0.6.0
rootdir: /home/(env) qabrio/basic_calculator, inifile:
collected 6 items                                                                                
<Module 'calculation_test.py'>
  <Function 'test_addition'>
  <Function 'test_subtraction'>
<Module 'test_calc.py'>
  <Function 'test_addition'>
  <Function 'test_subtraction'>
<Module 'subfolder/test_calculator.py'>
  <Function 'test_addition'>
  <Function 'test_subtraction'>
 
=================================== no tests ran in 0.01 seconds ===================================

Jak widzimy pyTest przeszukał bieżący folder oraz wszystkie podfoldery, identyfikując trzy pliki z testami. Pliki takie jak subfolder/calculator.py, czy other/test_calc zostały pominięte. Wyjaśnieniem tej sytuacji jest fakt, że pyTest szukając testów, zawsze przyrównuje je do wzorców — zarówno pliki, jak i klasy czy funkcje. Poszczególne wzorce są wyszczególnione poniżej:

  • plików: test_*.py oraz *_test.py, np. test_calculator.py, regression_test.py
  • klas: Test* np. TestClass, TestRegression TestCalculation
  • funkcji: test_* np. test_addition test_subtraction

Ciekawą opcją jest możliwość wyłączenia danej ścieżki z całego zestawu testów. Poniżej możemy zobaczyć przykład, w którym wyłączymy z przeszukiwania ścieżkę, a właściwie plik test_calc.py, za pomocą parametru –ignore:

(env) cabrio@test:~/basic_calculator$ pytest --ignore=test_calc.py --collect-only
=========================================== 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 4 items                       
<Module 'calculation_test.py'>
  <Function 'test_addition'>
  <Function 'test_subtraction'>
<Module 'subfolder/test_calculator.py'>
  <Function 'test_addition'>
  <Function 'test_subtraction'>
 
====================================== no tests ran in 0.00 seconds =======================================

Uruchamianie zestawu testów

Najbardziej podstawową metodą uruchamiania pyTest’a jest wpisanie nazwy narzędzia, czyli pytest w konsoli. Warunkiem jest, żeby znajdować się w lokalizacji testów, które chcemy wykonać. Jak wcześniej wspomniałem, jeśli nie użyjemy dodatkowych parametrów ograniczających zestaw testów, pyTest przeszuka folder bieżący oraz wszystkie podfoldery pod kątem testów. Przejdźmy do poniższego przykładu:

(env) qabrio@test:~/basic_calculator$ pytest
======================================== test session starts =========================================
platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1
rootdir: /home/(env) qabrio/basic_calculator, inifile:
collected 6 items                                       
 
calculation_test.py ..                                                                          [ 33%]
test_calc.py ..                                                                                 [ 66%]
subfolder/test_calculator.py ..                                                                 [100%]
 
====================================== 6 passed in 0.01 seconds ======================================

Jako rezultat polecenia, otrzymaliśmy informacje na temat wersji użytych narzędzi, lokalizacji testów, a także zostały wypisane pliki, z których testy zostały uruchomione. Obok każdego pliku znajdują się po dwie kropki. Oznaczają one, że zostały wykonane po dwa testy (w przypadku testów niezaliczonych zamiast kropki jest pokazane F). Na samym dole znajduje się podsumowanie z liczbą wykonanych testów.

Jeśli powyższe informacje są niewystarczające, zawsze można użyć flagi —verbose lub odpowiednio -v. Dzięki niej będziemy mieć dodatkowo wypisane wszystkie testy wraz z informacją czy przeszły, czy nie.

(env) qabrio@test:~/basic_calculator$ pytest -v
======================================== test session starts =========================================
platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 -- /home/qabrio/basic_calculator/env/bin/python3.6
cachedir: .cache
rootdir: /home/(env) qabrio/basic_calculator, inifile:
collected 6 items              
 
calculation_test.py::test_addition PASSED                                                       [ 16%]
calculation_test.py::test_subtraction PASSED                                                    [ 33%]
test_calc.py::test_addition PASSED                                                              [ 50%]
test_calc.py::test_subtraction PASSED                                                           [ 66%]
subfolder/test_calculator.py::test_addition PASSED                                              [ 83%]
subfolder/test_calculator.py::test_subtraction PASSED                                           [100%]
 
====================================== 6 passed in 0.01 seconds =======================================

Przeciwieństwem powyższego jest użycie flagi -q, czyli —quiet, która sprawia, że program staje się mniej ‚gadatliwy’ i jako rezultat dostaniemy tylko i wyłącznie ostatnią linię z podsumowanie liczby testów. Ciekawostką jest fakt, że flagę -q można użyć z flagą -v, które będą kasowały działanie drugiej — ‚wygra’ ta, która będzie więcej razy powtórzona. W poniższym przykładzie widać rezultat takiego podejścia. Oczywiście używanie takich flag jednocześnie jest bez sensu. Poniższa komenda jest równoznaczna z pytest -q:

(env) qabrio@test:~/basic_calculator$ pytest -vqq
......                                                                                                                                                                                                                                [100%]
6 passed in 0.01 seconds

Interakcje z testami

Jeśli testy wymagają jakiejkolwiek interakcji z testerem (np. tester jest proszony o wprowadzenie jakiejś danej), ich uruchomienie skończy się wyrzuceniem wyjątku IOError. Wynika to z tego, że domyślnie pyTest przejmuje cały strumień danych. Aby tego uniknąć, należy wykorzystać flagę -s, która jest równoznaczna z —capture=no. W rezultacie zostaną wypisane wszystkie informacje, które funkcja przesyła na standardowy strumień danych — chodzi tu szczególnie o funkcje print() oraz input():

(env) qabrio@test:~/basic_calculator$ pytest -sv
======================================== test session starts =========================================
platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 -- /home/qabrio/basic_calculator/env/bin/python3.6
cachedir: .cache
rootdir: /home/(env) qabrio/basic_calculator, inifile:
collected 6 items                                       
 
calculation_test.py::test_addition 10 + 5 = 15
PASSED                                                                                          [ 16%]
calculation_test.py::test_subtraction 13 - 21 = -8
PASSED                                                                                          [ 33%]
test_calc.py::test_addition 10 + 5 = 15
PASSED                                                                                          [ 50%]
test_calc.py::test_subtraction 13 - 21 = -8
PASSED                                                                                          [ 66%]
subfolder/test_calculator.py::test_addition 10 + 5 = 15
PASSED                                                                                          [ 83%]
subfolder/test_calculator.py::test_subtraction 13 - 21 = -8
PASSED                                                                                          [100%]
 
======================================= 6 passed in 0.01 seconds =====================================

Uruchamianie wybranych testów

Nic nie stoi na przeszkodzie, aby uruchomić przy użyciu pyTest’a tylko wybrane testy. W tym celu, po nazwie pytest oraz argumentach, należy wpisać nazwę pliku, lub nazwę testu, poprzedzoną nazwą pliku oraz podwójnym dwukropkiem:

(env) qabrio@test:~/basic_calculator$ pytest -v calculation_test.py 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 -- /home/qabrio/basic_calculator/env/bin/python3.6
cachedir: .cache
rootdir: /home/(env) qabrio/basic_calculator, inifile:
collected 3 items               
 
calculation_test.py::test_addition PASSED                                               [ 33%]
calculation_test.py::test_subtraction PASSED                                            [ 66%]
test_calc.py::test_addition PASSED                                                      [100%]
 
================================== 3 passed in 0.01 seconds ==================================

Jak widać na powyższym, zostały uruchomione wszystkie testy z pliku calculation_test.py oraz tylko jeden wybrany test z pliku test_calc.py

Przeszukiwanie testów

Kolejną wartą wspomnienia flagą jest -k, która sprawia, że pliki są przeszukiwane pod kątem pasujących do wzorca testów (podanego po fladze -k). Dla przykładu spróbujmy uruchomić wszystkie testy zawierające w nazwie część addition:

(env) qabrio@test:~/basic_calculator$ pytest -vk 'addition'
========================================= test session starts =========================================
platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 -- /home/qabrio/basic_calculator/env/bin/python3.6
cachedir: .cache
rootdir: /home/(env) qabrio/basic_calculator, inifile:
collected 6 items                                                                                                                                                                                                                           
 
calculation_test.py::test_addition PASSED                                                        [ 33%]
test_calc.py::test_addition PASSED                                                               [ 66%]
subfolder/test_calculator.py::test_addition PASSED                                               [100%]
 
========================================= 3 tests deselected ==========================================
=============================== 3 passed, 3 deselected in 0.01 seconds ================================

Analizując rezultat, możemy zauważyć, że pyTest znalazł 6 testów, z czego trzy pasowały do wzorca, a trzy zostały odrzucone. Ciekawostką jest fakt, że jako argument można podać wyrażenie logiczne. Czyli na przykład dodając not w argumencie przed frazą, która poszukujemy, spowoduje to odrzucenie wszystkich testów zawierających daną frazę:

(env) qabrio@test:~/basic_calculator$ pytest -vk 'not addition'
========================================= test session starts =========================================
platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 -- /home/qabrio/basic_calculator/env/bin/python3.6
cachedir: .cache
rootdir: /home/(env) qabrio/basic_calculator, inifile:
collected 6 items                                            
 
calculation_test.py::test_subtraction PASSED                                                     [ 33%]
test_calc.py::test_subtraction PASSED                                                            [ 66%]
subfolder/test_calculator.py::test_subtraction PASSED                                            [100%]
 
========================================= 3 tests deselected ==========================================
================================ 3 passed, 3 deselected in 0.01 seconds ===============================

Znajdowanie najwolniejszych testów

PyTest umożliwia również weryfikowanie czasu trwania testów oraz czynności przygotowawczych/zamykających testy. Można to wykonać za pomocą opcji —durations=N, gdzie N=0 jest wykorzystane dla wszystkich testów, a inna liczba określa pokazanie N najwolniejszych działań. Jest to szczególnie przydatne, kiedy pracujemy nad wydajnością w naszych testach. Na przykład:

(env) qabrio@test:~/basic_calculator$ pytest --durations=4
========================================= test session starts =========================================
platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 -- /home/qabrio/basic_calculator/env/bin/python3.6
rootdir: /home/(env) qabrio/basic_calculator, inifile:
collected 6 items                              
 
calculation_test.py ..                                                                           [ 33%]
test_calc.py ..                                                                                  [ 66%]
subfolder/test_calculator.py ..                                                                  [100%]
 
======================================= slowest 4 test durations ======================================
0.00s setup    calculation_test.py::test_addition
0.00s call     calculation_test.py::test_addition
0.00s call     subfolder/test_calculator.py::test_addition
0.00s call     test_calc.py::test_addition
======================================= 6 passed in 0.01 seconds ======================================

Raportowanie

Kolejną istotną rzeczą, którą należy znać przy uruchamianiu testów, są opcje raportowania. Dostępne opcje raportowania są umieszczane jako argumenty dla flagi -r. Jednymi z bardziej przydatnych są :

  • f – krótkie podsumowanie wszystkich testów, które nie przeszły,
  • p – krótkie podsumowanie wszystkich testów, które przeszły,
  • s – krótkie podsumowanie wszystkich testów, które pominięto,
  • P – informacje ze standardowego wyjścia testów, które przeszły.
(env) qabrio@test:~/basic_calculator$ pytest -vk 'addition' -r pP
========================================= test session starts =========================================
platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 -- /home/qabrio/basic_calculator/env/bin/python3.6
cachedir: .cache
rootdir: /home/(env) qabrio/basic_calculator, inifile:
collected 6 items                  
 
calculation_test.py::test_addition PASSED                                                        [ 33%]
test_calc.py::test_addition PASSED                                                               [ 66%]
subfolder/test_calculator.py::test_addition PASSED                                               [100%]
======================================= short test summary info =======================================
PASSED calculation_test.py::test_addition
PASSED test_calc.py::test_addition
PASSED subfolder/test_calculator.py::test_addition
 
=============================================== PASSES ================================================
____________________________________________ test_addition ____________________________________________
---------------------------------------- Captured stdout call -----------------------------------------
10 + 5 = 15
____________________________________________ test_addition ____________________________________________
---------------------------------------- Captured stdout call -----------------------------------------
10 + 5 = 15
____________________________________________ test_addition ____________________________________________
---------------------------------------- Captured stdout call -----------------------------------------
10 + 5 = 15
========================================== 3 tests deselected =========================================
================================ 3 passed, 3 deselected in 0.01 seconds ===============================

Podsumowując tę część serii pyTest Tutorial Uruchamianie testów z parametrami, warto wspomnieć, że dobrą praktyką w tworzeniu komend uruchamiających testy, jest przy pierwszym uruchomieniu użyć flagi —collect-only. Używamy jej do sprawdzenia, czy zapytanie wybrało takie testy, jakie oczekiwaliśmy. Jeśli coś pójdzie nie tak, mamy możliwość dokonania poprawek bez żadnych konsekwencji. W kolejnej części nauczymy się jak obsługiwać i sterować uruchamianiem testów pod kątem testów, które kończą się niepowodzeniem.

close

Newsletter