Skip to content

TECH TALK 1 WPROWADZENIE DO TESTÓW

dybi edited this page Apr 9, 2018 · 5 revisions

PO CO W OGÓLE TESTY?

"Mój kod działa, sprawdziłem ręcznie" - Anonimowy Programista

źródło: https://android.jlelse.eu/basics-of-unit-testing-affdd2273310

Testy zapewniają nam, m. in.:

  • powtarzalność wyników (podczas ręcznego wykonywania testu, człowiek może łatwo popełnić błąd)
  • oszczędność czasu - raz napisane testy będą służyć wciąż i wciąż
  • dobrze napisane testy mogą być doskonałą dokumentacją dla kodu, która zawsze będzie aktualna (jeśli nie - testy nie będą przechodzić)

// Dyskusja

RODZAJE TESTÓW (bardzo z grubsza)

  1. Testy jednostkowe (ang. unit tests) - u nas: praktycznie brak :( WIĘCEJ: Wprowadzenie Jeffa Knuppa

  2. Testy komponentowe (ang. component unit tests)(w Pythonie ciężko o dobry przykład)

  3. Testy kontraktowe (ang. contract tests), np. pact WIĘCEJ: Pact, Consumer Driven Contracts

  4. Testy integracyjne (ang. integration tests) - u nas: wiekszość (django testy z odpaleniem DB i stawianiem lokalnie serwera)

  5. Testy systemowe- (ang. End To End Test lub E2E tests) u nas: kilka testow do odpalania na klastrze (api-integration*.py)

Piramida: ~70/20/10

Podstawą piramidy powinny być testy jednostkowe - ze względu na szybkość, precyzję, łatwość przygotowania/napisania. Następne powinny być testy integracyjne, które sprawdzą kooperację pomiędzy komponentami, np. przepływ (ang. flow) lub zgodność interfejsów. Na samym szczycie powinny być testy E2E. Są one "najcięższe" i najbardziej kosztowne w napisaniu/utrzymaniu. Można ich używać jako testów akceptacyjnych (testów mających na celu potwierdzenie, że w kodzie "nie ma już błędów", np. demo dla klienta).

WIĘCEJ: Gradacja i rodzaje testów wg inżynierów Google

TESTY JEDNOSTKOWE - CZYM SĄ?

Powinny mieć właściwości FIRST

  • Fast - szybkie: kilkaset / kilka tysięcy testów na sekundę
  • Isolates - izolacja: przyczyna nieprzechodzenia testu jest oczywista
  • Repeatable - powtarzalność: dają ten sam rezultat, niezależnie od kolejności, czasu (pory), faktu puszczania w izolacji bądź w zestawie (tzw. test suit - "garnitur", zestaw, klasa testów)
  • Self-validating - samosprawdzające: nie potrzeba eksperta z domeną wiedzą, żeby określić czy test przeszedł czy nie; dają jednoznaczną odpowiedź - tak/nie
  • Timely - o czasie: są dostępne (mogą być użyte do sprawdzenia kodu) wystarczająco wcześnie (w idealnym świecie - przed powstaniem kodu produkcyjnego)

WIĘCEJ: FIRST - właściwości testów jednostkowych

DEMO

TESTY INTEGRACYJNE A TESTY JEDNOSTKOWE - przykład

funkcja: validate_report_computed_task_time_window (w concent_api/core/validation.py)

test: test_core_views.test_send_should_return_http_400_if_task_to_compute_younger_than_report_computed

Co zyskujemy preferując testy jednostkowe (nad testy integracyjne) do testowania małych kawałków kodu (unit-ów)?

  • szybkość
  • łatwiejszy przygotowanie (setup)
  • dokładność (w przypadku nieprzechodzia testu łatwiej zidentyfikować przyczynę - błąd w kodzie)

WNIOSKI

Piszmy test jednostkowe! :)

źródło: https://ardalis.com


ZADANIE "DOMOWE":

Napisać test jednostkowy dla funkcji i porównać czas trwania z testem integracyjnym django (python manage.py test core.tests.test_core_views.CoreViewSendTest.test_send_should_return_http_400_if_task_to_compute_younger_than_report_computed):

def validate_report_computed_task_time_window(report_computed_task):
    assert isinstance(report_computed_task, message.ReportComputedTask)

    if report_computed_task.timestamp < report_computed_task.task_to_compute.timestamp:
        raise Http400("ReportComputedTask timestamp is older then nested TaskToCompute.")

PODPOWIEDŹ: Można użyć self.assertRaises() z unittest albo pytest.raises()