Krzysztof Pich

Developer thinking about using phpunit working on laptop

W jakich przypadkach testy jednostkowe natychmiast przyspieszą dostarczenie rozwiązania

Podczas dyskusji o wpływie testów jednostkowych na budżety projektów, powszechnie uważa się, że stanowią one inwestycję początkową, która przynosi długoterminowe korzyści. Choć osiągnięcie kompleksowego pokrycia testami całego projektu lub konkretnych modułów jest kluczowe dla realizacji tych korzyści, chciałbym przedstawić scenariusze, w których testy jednostkowe mogą faktycznie przyspieszyć rozwój, zamiast być jedynie inwestycją.

Dlaczego przydatność testów jednostkowych jest niejednoznaczna w PHP

Ekosystem PHP oferuje unikalne aspekty, jeśli chodzi o testy jednostkowe. Działamy w środowisku natychmiastowej widoczności zmian – bez potrzeby budowania czy kompilacji. Rodzi to ważne pytania:

  • Przy budowie MVP - dlaczego inwestować w testy, gdy rentowność produktu jest niepewna?
  • Jak zrównoważyć testowanie z potrzebami klientów dotyczącymi szybkiego wejścia na rynek?

Czy powinniśmy konsultować stosowanie testów jednostkowych z biznesem?

Odpowiedź nie jest prosta. Choć nie ma potrzeby omawiania konkretnych technicznych implementacji z nietechnicznymi klientami, którzy polegają na Twojej wiedzy eksperckiej, musimy zawsze dostosowywać nasze podejście do rozwoju do celów biznesowych. Czasami okoliczności mogą wymagać priorytetowego traktowania szybkości wejścia na rynek kosztem kompleksowego testowania, szczególnie w wyścigu z konkurencją lub przy walidacji koncepcji produktu. Chociaż istnieje bogata literatura na temat zarządzania długiem technicznym, kluczowe jest zapobieganie temu, by jego akumulacja stała się standardową praktyką dostarczania oprogramowania.

Jednak istnieją konkretne scenariusze, w których implementacja testów jednostkowych może faktycznie przyspieszyć dostarczanie rozwiązań w porównaniu z całkowitym ich pominięciem.

Scenariusze testowania strategicznego

Implementacja procesu checkout

Weźmy pod uwagę checkout, który zazwyczaj obejmuje wiele stron i złożonych interakcji użytkownika. Testowanie scenariuszy zarówno dla zalogowanych, jak i niezalogowanych użytkowników w różnych opcjach wysyłki oraz płatności może pochłonąć znaczną ilość czasu programisty.

Przyjrzyjmy się typowemu scenariuszowi: wysyłaniu danych zamówienia do systemu ERP. Payload musi zawierać informacje o produkcie, dane użytkownika, szczegóły wysyłki i informacje o płatności. Rozważmy te zmienne:

  • Trzy typy produktów: Wirtualny, Konfigurowalny i Prosty
  • Dwie opcje dostawy bazujące na zawartości koszyka (regularna wysyłka i dostawa elektroniczna)
  • Dwa scenariusze - zalogowany użytkownik i gość

To tworzy co najmniej sześć różnych scenariuszy do weryfikacji funkcjonalności kodu w różnych kombinacjach produktów, opcji dostawy i stanów uwierzytelnienia – nie licząc różnych metod płatności. Testy jednostkowe pozwalają na walidację niezawodności kodu bez konieczności wielokrotnego ręcznego przechodzenia przez cały proces checkout.

Praca z serwisami zewnętrznymi

Poprzedni przykład ERP rozciąga się na każdą integrację wymagającą złożonych zapytań API lub obsługi webhooków. Podczas pracy z systemami zewnętrznymi pojawia się kilka czasochłonnych wyzwań:

Niekompletne dane w systemach zewnętrznych

Często musisz rozpocząć integrację przy minimalnej konfiguracji systemu zewnętrznego. Działają tylko dostępy i masz szczęście, jeśli jest skonfigurowanych kilka elementów w systemie zewnętrznym. Możesz użyć PHPUnit do przygotowania swojego systemu do obsługi wszystkich potencjalnych typów produktów / typów płatności / typów klientów itp. To więcej niż pewne, że niektóre z Twoich założeń nie będą trafne, ale będziesz mieć większość kodu gotową i pokrytą testami jednostkowymi, co pozwoli na elastyczne dostosowanie się do nowych danych, gdy pojawią się podczas cyklu dostarczenia oprogramowania.

Przygotowanie danych do każdego testu

Integracje zewnętrzne często wymagają koordynacji z zespołami klienta lub stronami trzecimi w zakresie przygotowania przypadków testowych. Testy jednostkowe pozwalają zmaksymalizować każdą iterację testową poprzez pokrycie przypadków brzegowych bez czekania na środowiska testów integracyjnych.

W tym scenariuszu przypadki testowe pozwolą Ci wycisnąć więcej z każdej rundy poprzez dodanie przypadków brzegowych w testach jednostkowych i możliwość wielokrotnego wykonania zestawu testów bez potrzeby czekania na test integracyjny, dzięki czemu możesz osiągnąć więcej w jednej iteracji.

Praca z algorytmami opartymi na czasie

Systemy często wymagają działań zależnych od czasu, takich jak powiadomienia o porzuconym koszyku czy prośby o opinię po zakupie. Zazwyczaj zależą one od różnych warunków, jak status uwierzytelnienia użytkownika, zgody marketingowe czy atrybuty kampanii marketingowej. Aby wszystko przetestować, programiści najczęściej przygotowują skrypty SQL do mapowania i modyfikacji pól created_at, updated_at i wielu innych w bazie danych w celu dostosowania systemu do ręcznego testowania aplikacji. Głównym problemem tego rozwiązania jest to, że rzadko jest ono aktualizowane zgodnie z wymaganiami i każdy programista ma własny zestaw takich zapytań SQL.

Testy jednostkowe są nieocenionym narzędziem wspierającym w szybszym wykonaniu zadania z dodatkowym udokumentowanym zachowaniem systemu kontrolowanym w tym samym repozytorium, w którym istnieje kod. Będziesz musiał zaprojektować rozwiązanie, aby było czyste i testowalne, ale nie będzie to kosztować Cię znacznie więcej niż "zwykłe" programowanie.

  • Strukturyzuj swój kod, aby oddzielić logikę biznesową od frameworka i środowiska
  • Projektuj punkty wejścia używając obiektów z datami i flagami, które określają zachowanie systemu
  • Stosuj zasady SOLID – oddzielaj obsługę wiadomości od logiki decyzyjnej
  • Skup się na testowaniu logiki biznesowej zamiast systemów wykonywania kolejek

Kod opracowany zgodnie z tymi zasadami umożliwia kompleksowe testowanie logiki biznesowej poprzez wstrzykiwane scenariusze testowe. Testy manualne mogą wtedy skupić się na walidacji ogólnego przepływu danych i funkcjonalności systemu wiadomości, podczas gdy przypadki brzegowe pozostają pokryte testami jednostkowymi.

Podsumowanie

Testowanie jednostkowe wykracza poza osiąganie wysokich wskaźników pokrycia czy umożliwianie praktyk CI/CD. Gdy stosowane strategicznie, staje się potężnym narzędziem do przyspieszania rozwoju przy jednoczesnym utrzymaniu jakości. Upewnij się, że Twoje projekty mają możliwości testowania jednostkowego i właściwą integrację z pipeline'em od samego początku – ta podstawa pozwoli Ci zwiększyć szybkość rozwoju przy jednoczesnej poprawie jakości kodu.