{"id":68,"date":"2024-10-15T17:04:57","date_gmt":"2024-10-15T15:04:57","guid":{"rendered":"https:\/\/pich.pl\/?p=68"},"modified":"2024-10-15T17:04:58","modified_gmt":"2024-10-15T15:04:58","slug":"unit-tests-start-with-architecture-instead-of-detail","status":"publish","type":"post","link":"https:\/\/pich.pl\/pl\/2024\/10\/15\/unit-tests-start-with-architecture-instead-of-detail\/","title":{"rendered":"Testy jednostkowe - Zacznij od architektury zamiast od szczeg\u00f3\u0142\u00f3w"},"content":{"rendered":"<p>Implementacja test\u00f3w jednostkowych pozwala zacz\u0105\u0107 od celu funkcjonalno\u015bci i przej\u015b\u0107 przez kompozycj\u0119 obiektu a\u017c do szczeg\u00f3\u0142\u00f3w. Pracuj\u0105c nad projektem bez test\u00f3w jednostkowych, naturalnie zaczynasz od obecnej bazy kodu i budujesz w kierunku rozwi\u0105zania. To podej\u015bcie jest pocz\u0105tkowo proste, ale mo\u017ce prowadzi\u0107 do pozostawienia najtrudniejszych decyzji na koniec zadania, gdy wi\u0119kszo\u015b\u0107 kodu jest ju\u017c \"gotowa\". Mo\u017ce to znacz\u0105co wp\u0142yn\u0105\u0107 na utrzymanie zadania w ramach bud\u017cetu i harmonogramu.<\/p>\n\n\n\n<p>Gdy zaczniesz od test\u00f3w jednostkowych, zyskujesz pot\u0119\u017cne nowe narz\u0119dzie. Mo\u017cesz wykonywa\u0107 kod bez uruchamiania ca\u0142ej aplikacji lub bez potrzeby posiadania punktu wyj\u015bcia w obecnej bazie kodu.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Przyk\u0142ad <\/h2>\n\n\n\n<p>Wyobra\u017a sobie, \u017ce musisz wys\u0142a\u0107 payload po wykonaniu zam\u00f3wienia do systemu ERP, co jest typow\u0105 funkcj\u0105 w systemach e-commerce. Oto kilka wymaga\u0144 dla naszego przyk\u0142adowego systemu ERP:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>JSON wykorzystywany w komunikacji<\/li>\n\n\n\n<li>Autoryzacja opiera si\u0119 na tokenie bearer.<\/li>\n\n\n\n<li>Ka\u017cde \u017c\u0105danie wykorzystuje kilka p\u00f3l z zawarto\u015bci JSON oraz secret key do generowania hashu \u2013 algorytm jest opisany w dokumentacji.<\/li>\n\n\n\n<li>W reque\u015bcie nale\u017cy wys\u0142a\u0107 dane klienta, order items i kod metody wysy\u0142ki<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Standardowe podej\u015bcie bez test\u00f3w jednostkowych<\/h3>\n\n\n\n<p>Programuj\u0105c w PHP, naturalnie zacz\u0105 by\u015b od wyszukiwania wymaganych danych do requestu w obecnym systemie. Po zako\u0144czeniu, przeszed\u0142by\u015b do implementacji parsera do serializacji JSON, a nast\u0119pnie zbudowa\u0142by\u015b klas\u0119, kt\u00f3ra przyjmuje payload i tworzy \u017c\u0105danie z autoryzacj\u0105. Jakie s\u0105 konsekwencje tego podej\u015bcia?<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li class=\"translation-block\">Je\u015bli nie rozwa\u017cy\u0142e\u015b, jak b\u0142\u0119dy autoryzacji i requestu s\u0105 obs\u0142ugiwane przez klas\u0119 nadawcz\u0105, b\u0119dziesz musia\u0142 dostosowa\u0107 ju\u017c utworzony kod do wybranego podej\u015bcia \u2013 zazwyczaj gdy zadanie jest prawie sko\u0144czone.<\/li>\n\n\n\n<li class=\"translation-block\">Pytania o tw\u00f3j system, takie jak \"Jak uzyska\u0107 przedmiot zam\u00f3wienia z cen\u0105 regularn\u0105 i cen\u0105 po rabacie?\" s\u0105 \u0142atwe do rozwi\u0105zania \u2013 masz kod do zbadania i jeste\u015b ekspertem w swoim systemie. Jednak pytania takie jak \"Czy 'liczba' rabatu w dokumentacji to procent czy kwota?\" mog\u0105 by\u0107 czasoch\u0142onne ze wzgl\u0119du na op\u00f3\u017anienia w komunikacji mi\u0119dzy tob\u0105 a zespo\u0142em ERP.<\/li>\n\n\n\n<li>You&#8217;re <strong>unable to test the solution without having almost everything implemented<\/strong> Nie mo\u017cesz przetestowa\u0107 rozwi\u0105zania bez zaimplementowania prawie wszystkiego \u2013 je\u015bli oka\u017ce si\u0119, \u017ce dokumentacja jest nieaktualna dla kilku element\u00f3w, w\u0142a\u015bnie sp\u0119dzi\u0142e\u015b tydzie\u0144 nad rozwi\u0105zaniem, sprint ma si\u0119 ku ko\u0144cowi, a ty potrzebujesz odpowiedzi od klienta lub zespo\u0142u ERP.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Jak Ci pomo\u017ce rozpocz\u0119cie od test\u00f3w jednostkowych<\/h3>\n\n\n\n<p class=\"translation-block\">Rozpoczniesz od interfejsu klasy ErpSender i zale\u017cno\u015bci. Czas rozwa\u017cy\u0107 nast\u0119puj\u0105ce pytania:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Potrzebuj\u0119 metody <strong>send()<\/strong> , kt\u00f3ra przyjmie ci\u0105g znak\u00f3w i zbuduje autoryzacj\u0119 dla zapytania.\n<ul class=\"wp-block-list\">\n<li>Mog\u0119 zweryfikowa\u0107 poprawno\u015b\u0107 JSON za pomoc\u0105 metody json_validate.<\/li>\n\n\n\n<li>Gdzie powinienem wyliczy\u0107 hash dla zapytania. Powinienem to rozwa\u017cy\u0107 przy budowaniu zawarto\u015bci requestu.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li class=\"translation-block\">Token powinien by\u0107 dostarczony przez klas\u0119 ErpConfiguration<\/li>\n\n\n\n<li>W przypadku obs\u0142ugi b\u0142\u0119d\u00f3w powinienem rzuci\u0107 wyj\u0105tek. B\u0119d\u0119 musia\u0142 zatrzyma\u0107 przetwarzanie zam\u00f3wienia lub przechowa\u0107 je do ponownego wys\u0142ania, lub oznaczy\u0107 zam\u00f3wienie. Zastan\u00f3w si\u0119, gdzie logowa\u0107 b\u0142\u0119dy i kogo powiadomi\u0107 \u2013 je\u015bli cokolwiek z tego nie jest okre\u015blone na pocz\u0105tku zadania, masz doskona\u0142e pytania do zespo\u0142u biznesowego. <strong>you have excellent questions for the business team<\/strong>.<\/li>\n<\/ul>\n\n\n\n<p class=\"translation-block\">Za\u0142\u00f3\u017cmy, \u017ce mamy gotow\u0105 klas\u0119 ErpSender, wiedz\u0105c, \u017ce b\u0119dzie ona rzuca\u0107 wyj\u0105tek w przypadku b\u0142\u0119du, zwraca\u0107 void i potrzebowa\u0107 JSONa z klasy wywo\u0142uj\u0105cej \u2013 wszystko inne jest obs\u0142ugiwane przez wstrzykiwanie zale\u017cno\u015bci. To, co musimy zbudowa\u0107, to klasa PayloadBuilder. Teraz powinni\u015bmy rozwa\u017cy\u0107:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Jak zbudowa\u0107 hash? Haszowanie nie jest cz\u0119\u015bci\u0105 budowania requestu, ale b\u0119dzie potrzebowa\u0107 okre\u015blonej listy p\u00f3l dla ka\u017cdego payloadu. Hash b\u0119dzie potrzebowa\u0142 klasy ErpConfiguration jako zale\u017cno\u015bci, aby uzyska\u0107 secret key i dane z requestu. <strong>ErpConfiguration<\/strong> class as a dependency to get the secret and payload data.<\/li>\n\n\n\n<li>To najlepszy czas, aby zada\u0107 pytania zwi\u0105zane z architektur\u0105:\n<ul class=\"wp-block-list\">\n<li>Czy ERP b\u0119dzie u\u017cywany tylko do przetwarzania zam\u00f3wie\u0144, czy inne dane b\u0119d\u0105 wysy\u0142ane z e-commerce, takie jak klienci, przedmioty itp.? W tym momencie mo\u017cesz chcie\u0107 skontaktowa\u0107 si\u0119 z PM, Solution architektem lub bezpo\u015brednio z biznesem.<\/li>\n\n\n\n<li>Je\u015bli tak \u2013 mo\u017ce by\u0107 korzystne zaimplementowanie wzorca projektowego, takiego jak kompozyt, budowniczy lub metoda fabrykuj\u0105ca co r\u00f3wnie\u017c mo\u017ce rozwi\u0105za\u0107 problem z hashem.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Czy potrzebuj\u0119 zapisa\u0107 pe\u0142ny request i czy potrzebuj\u0119 funkcjonalno\u015bci powtarzania zapytania przy b\u0142\u0119dzie?<\/li>\n\n\n\n<li class=\"translation-block\">Mo\u017ce potrzebuj\u0119 klasy OrderProcessor, a PayloadBuilder b\u0119dzie u\u017cywany w tej klasie, aby spe\u0142ni\u0107 zasad\u0119 pojedynczej odpowiedzialno\u015bci?<\/li>\n\n\n\n<li>Jak powinienem budowa\u0107 payload \u2013 wykorzystuj\u0105c klasy i interfejsy systemu e-commerce, czy potrzebuj\u0119 stworzy\u0107 obiekty typu Data Access dla ERP ze wzgl\u0119du na r\u00f3\u017cnice lub z\u0142o\u017cono\u015b\u0107 danych w systemie?<\/li>\n<\/ul>\n\n\n\n<p>Po tym procesie i stworzeniu niezb\u0119dnych test\u00f3w i implementacji, mo\u017cesz zag\u0142\u0119bi\u0107 si\u0119 w szczeg\u00f3\u0142y swojego systemu e-commerce. To powinien by\u0107 trzeci lub czwarty dzie\u0144 pracy, a ty odpowiedzia\u0142e\u015b na wszystkie pytania architektoniczne i wi\u0119kszo\u015b\u0107 funkcjonalnych. Mo\u017cesz skupi\u0107 si\u0119 na poziomie, w kt\u00f3rym masz najwi\u0119cej do\u015bwiadczenia, odpowiadaj\u0105c na pytania takie jak:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Jakie powinno by\u0107 miejsce do pobierania danych zam\u00f3wienia?<\/li>\n\n\n\n<li>Jak zebra\u0107 wszystkie dane?<\/li>\n\n\n\n<li>Jak obs\u0142u\u017cy\u0107 r\u00f3\u017cne typy produkt\u00f3w?<\/li>\n<\/ul>\n\n\n\n<p>Tego rodzaju pytania rzadko polegaj\u0105 na zespo\u0142ach biznesowych lub zewn\u0119trznych \u2013 mo\u017cesz je rozwi\u0105za\u0107, sprawdzaj\u0105c dokumentacj\u0119 platformy e-commerce lub po prostu czytaj\u0105c kod. Rozs\u0105dne jest zostawienie tego na koniec zamiast skupiania si\u0119 na tym na pocz\u0105tku pracy.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Podsumowanie<\/h2>\n\n\n\n<p>Pracuj\u0105c z testami jednostkowymi i zaczynaj\u0105c od ko\u0144ca, b\u0119dziesz w stanie my\u015ble\u0107 o brakuj\u0105cych szczeg\u00f3\u0142ach technicznych i projekcie architektonicznym wcze\u015bniej i z mniejsz\u0105 baz\u0105 kodu, kt\u00f3ra b\u0119dzie wymaga\u0142a dostosowania do decyzji. To mo\u017ce zapewni\u0107 ci niezb\u0119dny czas na komunikacj\u0119 i pokaza\u0107 ci\u0119 jako godnego zaufania profesjonalist\u0119.<\/p>","protected":false},"excerpt":{"rendered":"<p>Implementing unit tests allows you to begin with the solution goal and work your way through an object&#8217;s composition down to the details. When working on a project without unit tests, you naturally start from the current codebase and build towards the solution. This approach is initially straightforward but can lead to leaving the most [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":103,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"slim_seo":{"title":"Unit Tests - start with architecture instead of detail","description":"Implementing unit tests allows you to begin with the solution goal and work your way through an object's composition down to the details."},"footnotes":""},"categories":[16],"tags":[],"class_list":["post-68","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-programming"],"_links":{"self":[{"href":"https:\/\/pich.pl\/pl\/wp-json\/wp\/v2\/posts\/68","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pich.pl\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pich.pl\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pich.pl\/pl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pich.pl\/pl\/wp-json\/wp\/v2\/comments?post=68"}],"version-history":[{"count":6,"href":"https:\/\/pich.pl\/pl\/wp-json\/wp\/v2\/posts\/68\/revisions"}],"predecessor-version":[{"id":106,"href":"https:\/\/pich.pl\/pl\/wp-json\/wp\/v2\/posts\/68\/revisions\/106"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/pich.pl\/pl\/wp-json\/wp\/v2\/media\/103"}],"wp:attachment":[{"href":"https:\/\/pich.pl\/pl\/wp-json\/wp\/v2\/media?parent=68"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pich.pl\/pl\/wp-json\/wp\/v2\/categories?post=68"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pich.pl\/pl\/wp-json\/wp\/v2\/tags?post=68"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}