Implementacja testów jednostkowych pozwala zacząć od celu funkcjonalności i przejść przez kompozycję obiektu aż do szczegółów. Pracując nad projektem bez testów jednostkowych, naturalnie zaczynasz od obecnej bazy kodu i budujesz w kierunku rozwiązania. To podejście jest początkowo proste, ale może prowadzić do pozostawienia najtrudniejszych decyzji na koniec zadania, gdy większość kodu jest już "gotowa". Może to znacząco wpłynąć na utrzymanie zadania w ramach budżetu i harmonogramu.
Gdy zaczniesz od testów jednostkowych, zyskujesz potężne nowe narzędzie. Możesz wykonywać kod bez uruchamiania całej aplikacji lub bez potrzeby posiadania punktu wyjścia w obecnej bazie kodu.
Przykład
Wyobraź sobie, że musisz wysłać payload po wykonaniu zamówienia do systemu ERP, co jest typową funkcją w systemach e-commerce. Oto kilka wymagań dla naszego przykładowego systemu ERP:
- JSON wykorzystywany w komunikacji
- Autoryzacja opiera się na tokenie bearer.
- Każde żądanie wykorzystuje kilka pól z zawartości JSON oraz secret key do generowania hashu – algorytm jest opisany w dokumentacji.
- W requeście należy wysłać dane klienta, order items i kod metody wysyłki
Standardowe podejście bez testów jednostkowych
Programując w PHP, naturalnie zaczą byś od wyszukiwania wymaganych danych do requestu w obecnym systemie. Po zakończeniu, przeszedłbyś do implementacji parsera do serializacji JSON, a następnie zbudowałbyś klasę, która przyjmuje payload i tworzy żądanie z autoryzacją. Jakie są konsekwencje tego podejścia?
- Jeśli nie rozważyłeś, jak błędy autoryzacji i requestu są obsługiwane przez klasę nadawczą, będziesz musiał dostosować już utworzony kod do wybranego podejścia – zazwyczaj gdy zadanie jest prawie skończone.
- Pytania o twój system, takie jak "Jak uzyskać przedmiot zamówienia z ceną regularną i ceną po rabacie?" są łatwe do rozwiązania – masz kod do zbadania i jesteś ekspertem w swoim systemie. Jednak pytania takie jak "Czy 'liczba' rabatu w dokumentacji to procent czy kwota?" mogą być czasochłonne ze względu na opóźnienia w komunikacji między tobą a zespołem ERP.
- You’re unable to test the solution without having almost everything implemented Nie możesz przetestować rozwiązania bez zaimplementowania prawie wszystkiego – jeśli okaże się, że dokumentacja jest nieaktualna dla kilku elementów, właśnie spędziłeś tydzień nad rozwiązaniem, sprint ma się ku końcowi, a ty potrzebujesz odpowiedzi od klienta lub zespołu ERP.
Jak Ci pomoże rozpoczęcie od testów jednostkowych
Rozpoczniesz od interfejsu klasy ErpSender i zależności. Czas rozważyć następujące pytania:
- Potrzebuję metody send() , która przyjmie ciąg znaków i zbuduje autoryzację dla zapytania.
- Mogę zweryfikować poprawność JSON za pomocą metody json_validate.
- Gdzie powinienem wyliczyć hash dla zapytania. Powinienem to rozważyć przy budowaniu zawartości requestu.
- Token powinien być dostarczony przez klasę ErpConfiguration
- W przypadku obsługi błędów powinienem rzucić wyjątek. Będę musiał zatrzymać przetwarzanie zamówienia lub przechować je do ponownego wysłania, lub oznaczyć zamówienie. Zastanów się, gdzie logować błędy i kogo powiadomić – jeśli cokolwiek z tego nie jest określone na początku zadania, masz doskonałe pytania do zespołu biznesowego. you have excellent questions for the business team.
Załóżmy, że mamy gotową klasę ErpSender, wiedząc, że będzie ona rzucać wyjątek w przypadku błędu, zwracać void i potrzebować JSONa z klasy wywołującej – wszystko inne jest obsługiwane przez wstrzykiwanie zależności. To, co musimy zbudować, to klasa PayloadBuilder. Teraz powinniśmy rozważyć:
- Jak zbudować hash? Haszowanie nie jest częścią budowania requestu, ale będzie potrzebować określonej listy pól dla każdego payloadu. Hash będzie potrzebował klasy ErpConfiguration jako zależności, aby uzyskać secret key i dane z requestu. ErpConfiguration class as a dependency to get the secret and payload data.
- To najlepszy czas, aby zadać pytania związane z architekturą:
- Czy ERP będzie używany tylko do przetwarzania zamówień, czy inne dane będą wysyłane z e-commerce, takie jak klienci, przedmioty itp.? W tym momencie możesz chcieć skontaktować się z PM, Solution architektem lub bezpośrednio z biznesem.
- Jeśli tak – może być korzystne zaimplementowanie wzorca projektowego, takiego jak kompozyt, budowniczy lub metoda fabrykująca co również może rozwiązać problem z hashem.
- Czy potrzebuję zapisać pełny request i czy potrzebuję funkcjonalności powtarzania zapytania przy błędzie?
- Może potrzebuję klasy OrderProcessor, a PayloadBuilder będzie używany w tej klasie, aby spełnić zasadę pojedynczej odpowiedzialności?
- Jak powinienem budować payload – wykorzystując klasy i interfejsy systemu e-commerce, czy potrzebuję stworzyć obiekty typu Data Access dla ERP ze względu na różnice lub złożoność danych w systemie?
Po tym procesie i stworzeniu niezbędnych testów i implementacji, możesz zagłębić się w szczegóły swojego systemu e-commerce. To powinien być trzeci lub czwarty dzień pracy, a ty odpowiedziałeś na wszystkie pytania architektoniczne i większość funkcjonalnych. Możesz skupić się na poziomie, w którym masz najwięcej doświadczenia, odpowiadając na pytania takie jak:
- Jakie powinno być miejsce do pobierania danych zamówienia?
- Jak zebrać wszystkie dane?
- Jak obsłużyć różne typy produktów?
Tego rodzaju pytania rzadko polegają na zespołach biznesowych lub zewnętrznych – możesz je rozwiązać, sprawdzając dokumentację platformy e-commerce lub po prostu czytając kod. Rozsądne jest zostawienie tego na koniec zamiast skupiania się na tym na początku pracy.
Podsumowanie
Pracując z testami jednostkowymi i zaczynając od końca, będziesz w stanie myśleć o brakujących szczegółach technicznych i projekcie architektonicznym wcześniej i z mniejszą bazą kodu, która będzie wymagała dostosowania do decyzji. To może zapewnić ci niezbędny czas na komunikację i pokazać cię jako godnego zaufania profesjonalistę.