Opublikowano: 13-05-2016



W Pythonie są dostępne co najmniej dwa frameworki do testów - unittest i pytest (nose - kolejny framework - to testrunner). Niewątpliwą zaletą unittesta jest fakt, iż znajduje się w domyślnej dystrybucji pythona, a pytest, jako osobny pakiet, należy doinstalować za pomocą pip.

Odnoszę wrażenie, że pytest jest popularniejszy. Widziałem już go w użyciu przez różne osoby, czy firmy, natomiast unittest pozostaje w cieniu, ale to moje subiektywne odczucie.

Kilka słów za pytestem prosto z tego tematu:

  • easy support for distributed testing
  • good plugin architecture
  • easier assertions (just assert x == 42, no assertEqual())
  • funcargs (since 2.3 or 2.4 called fixtures, somewhat different to what other testing frameworks call fixtures)

Do pytesta dorzuciłbym jeszcze pakiet mock. Od Pythona 3 wchodzi w skład standardowej dystrybucji. Początkowo jego użycie może okazać się dość dziwne - wygląda prosto, ale jeśli nie wczytamy się w dokumentację to możemy się zdziwić, dlaczego to nie działa?

Testy domyślnie poszukiwane są w plikach o nazwach rozpoczynających się od test_, klasach od Test, funkcjach, metodach od test_. Dzieje się to automatycznie, nie musimy nic konfigurować.

Przykładowy test z użyciem pytest oraz mock:

W funkcji mock_socket tworzony jest mock, który będzie reprezentował obiekt gniazda z czterema funkcjami - connect, send, recv, close. Dzięki setup_method będzie tworzony przed każdym uruchomieniem metody testowej - dla każdego testu otrzymamy nowy, czysty obiekt. pytest pozwala oczywiście na uruchamianie metod przed startem, czy po zakończeniu metody testu, klasy, modułu. Więcej o tych możliwościach w dokumentacji.

Wkażdym teście wykorzystywany jest również dekorator patch, który pozwala na zamokowanie wybranej funkcji (obiektu, czy metody) w podanym pakiecie. W przykładzie mockowana jest funkcja socket z pakietu socket. I tutaj drobna uwaga, w zależności od tego, w jaki sposób importujemy funkcję socket w testowanej klasie, musimy przesłonić różne nazwy - może być to socket.socket - w przypadku użycia import socket, albo Network.socket - w przypadku użycia from socket import socket. Bardzo dobry opis znajduje się w tym wpisie.

Jeżeli oczekujemy, że testowana metoda rzuci wyjątek używamy konstrukcji with pytest.raises(). Pozostałe asercje są chyba dość zrozumiałe, część z nich pochodzi z pakietu mock.



Comments powered by Disqus