E-book
6.83
drukowana A5
26.16
drukowana A5
Kolorowa
49.63
Testy jednostkowe z Net Core (C#)

Bezpłatny fragment - Testy jednostkowe z Net Core (C#)

Szybki start


4
Objętość:
102 str.
ISBN:
978-83-8221-538-0
E-book
za 6.83
drukowana A5
za 26.16
drukowana A5
Kolorowa
za 49.63

I. Uwaga

Nazywam się Dariusz Gruca, jestem starszym programistą pracującym w sektorze medycznym. Zachęcam cię do odwiedzenia mojej strony internetowej www.DariuszGruca.pl

Znajdziesz tam bloga ze wpisami technologicznymi oraz recenzje wręcz obowiązkowych książek dla każdego programisty. W przyszłości planuję też tworzyć kursy w wersji wideo.

Kod zawarty w tej książce jest w formie zdjęcia. To kompromis, na który musiałem się zdecydować po testowaniu różnych rozwiązań na urządzeniach mobilnych.

Poświęć te parę chwil i naucz się pisać testy jednostkowe. Zapraszam.

II. Wstęp

Programy są dzisiaj wszędzie. Aplikacje potrafią wykonywać za nas żmudne nudne operacje, przyśpieszając naszą pracę. Uczą nasze dzieci, dostarczają nam rozrywki. Prawdopodobnie nie istnieje już żaden aspekt życia człowieka, który nie byłby wspierany przez oprogramowanie. Komputer wykonuje instrukcja po instrukcji, wszystko to, co zostało mu polecone przez programistę. Więc to na naszych barkach spoczywa odpowiedzialność za jakość dostarczonego kodu. Błędy mogą być błahe, ale mogą również spowodować utratę milionów złotych lub co gorsza, przyczynić się do śmierci ludzi.

Pracuję nad systemem wspierającym laboratoria patomorfologiczne. W tego typu placówkach ocenia się czy badana osoba ma raka. Nie muszę więc chyba wspominać, jak ważna jest jakość takiego systemu. Błąd może zagrozić zdrowiu, a nawet życiu pacjenta.

Jednak każdy program powinien być odpowiednio przetestowany. Nie tylko te, które wpływają na ludzkie życie, czy finanse. Nawet proste oprogramowanie codziennego użytku powinno być wolne od błędów.

Moim zdaniem każdy programista, przed przekazaniem kodu do repozytorium, zobowiązany jest dobrze go sprawdzić. Ręczne wykonywanie tej czynności jest bardzo czasochłonne, a w niektórych przypadkach wręcz niemożliwe. Rozwiązaniem tego problemu są testy automatyczne, których fundament stanowią testy jednostkowe. W tej książce pokażę ci, jak szybko rozpocząć swoją przygodę z testami jednostkowymi. Ekspresowo nauczysz się pisać kod, który testuje kod.

III. Standard

Testy automatyczne stają się standardem. Coraz więcej firm wymaga tej wiedzy od swoich pracowników. Nie pozostań w tyle. Wiedza oraz umiejętności związane z tą tematyką z pewnością powinny być integralną częścią warsztatu każdego profesjonalnego programisty.

Coraz częściej w ogłoszeniach o pracę widnieje zapis o doświadczeniu komercyjnym, związanym z pisaniem testów automatycznych. Sięgając po tę książkę, zakładam, że ta tematyka jest dla ciebie nowa.

Jeżeli pracujesz jako programista, masz szczęście, możesz jeszcze dziś zacząć zdobywać doświadczenie komercyjne, pisząc testy jednostkowe w swoim obecnym projekcie. Teoria jest potrzebna, ale doświadczenie jest cenniejsze. Dlatego jak najszybciej wykorzystaj przekazaną przeze mnie wiedzę. Twoje pierwsze testy z pewnością nie będą idealne, nie martw się tym, z czasem będziesz w tym coraz lepszy. Ważne jest, abyś rozpoczął tworzenie u siebie nowego nawyku.

W przypadku, gdy dopiero poszukujesz swojej pierwszej pracy, możesz zabłysnąć dodatkową umiejętnością. Stwórz popisowy projekt, w którym pochwalisz się swoją wiedzą. Koniecznie napisz do niego testy. Zamieść projekt na https://github.com/ lub innym portalu, znajdź seniora (np. na https://www.linkedin.com/), daj mu swój projekt do code review, zastosuj się do jego sugestii i popraw swój kod. Pamiętaj, że projekt nie musi być kompletny. Chodzi o to, byś zaprezentował swoje umiejętności związane z tym, jak piszesz, jakiego używasz nazewnictwa, jak tworzysz architekturę rozwiązania. Wpisz link do swojego CV. Popisowy projekt z testami znacząco zwiększy twoją szansę na przejście do kolejnego etapu rekrutacji. Uwierz, niewiele osób ma takie projekty, a programista najlepiej ocenia innego programistę po jego kodzie. Tylko bądź uczciwy, code review to nie to samo co zlecenie komuś takiego projektu. Oszustwo bardzo szybko wyjdzie podczas rozmowy rekrutacyjnej, naprawdę nie warto kombinować. Świat jest mały i swoim nieczystym zagraniem możesz znacząco utrudnić sobie znalezienie pracy w tym zawodzie.

IV. Praca bez testów automatycznych

Wyobraź sobie następującą sytuację. Janusz uważa się za profesjonalnego programistę, przez co testuje swoje rozwiązanie przed wrzuceniem kodu do repozytorium, jednak testy wykonuje manualnie. Dostał on nowe zadanie do wykonania. Z uśmiechem na twarzy napisał piękny i czysty kod. Teraz chce sprawdzić, jak on działa. Uruchamia więc system, loguje się, wybiera z menu interesujący go moduł, następnie wprowadza dane, po czym okazuje się, że pojawił się błąd. Janusz poprawia więc kod i ponawia próbę. Tym razem problemem są dane, których nie może wykorzystać ponownie. Na twarzy Janusza pojawia się grymas, ponieważ musi teraz poświęcić czas, aby je wygenerować. Po kilku minutach klikania po różnych modułach zaczyna pojawiać się u niego frustracja. Kawa, na którą Janusz miał się udać po wykonaniu zadania będzie zbędna. Gdy w końcu udało mu się przygotować wszystko, co potrzeba, sprawdza swoją funkcjonalność. Na ekranie widzi błąd. Poprawia kod i proces zaczyna się na nowo. Horror. Czas nieubłaganie brnie do przodu. Nerwy przebijają się przez tamę, jego stoickiego spokoju zalewając go negatywnymi emocjami. Po siódmej porażce siarczyście klnie pod nosem. Musi wyjść na papierosa, by się uspokoić. Pali od niedawna, biedak nie potrafił w inny sposób poradzić sobie z szarpiącymi go nerwami. W pięknym ogrodzie jego umysłu niczym chwasty zaczynają pojawiać się myśli o zrzuceniu odpowiedzialności za jakość swojej pracy na testera manualnego.

Mija miesiąc, Janusz ma już dość i postanawia porzucić sprawdzanie jakości własnej pracy. Bez testowania, wrzuca zmiany do repozytorium. Z uśmiechem na twarzy przechodzi do tworzenia kolejnych zadań. Czuje złudną ulgę. Wydaje mu się, że niesamowicie przyśpieszył.

Niestety jego pozorne szczęście trwało tylko chwilę. Gdy pewny siebie był w połowie tworzenia nowego modułu, przyszedł czas zapłaty za dług, który niewątpliwie zaciągnął. Tester zaczął zgłaszać błędy do kodu, od którego rozpoczął swoje radosne kodowanie bez sprawdzania jakości. Janusz wrócił do poprzedniego zadania. Poprawa błędu okazała się prosta. Jednak przez to, że pętla zwrotna informacji o problemie występującym w kodzie wydłużyła się, poświęcił on dużo czasu na przypomnienie sobie, o co chodziło w danej funkcjonalności. Z dnia na dzień coraz więcej czasu poświęcał na analizę i poprawę błędów niż na tworzenie nowych funkcji systemu.

Tempo pracy zwolniło, było jeszcze gorzej niż podczas ręcznego sprawdzania kodu. Powrót do kontekstu poprzednich zadań zabierał Januszowi dużo czasu, co go frustrowało. Każdy zgłoszony błąd wpływał negatywnie na jego samopoczucie. Kiedyś czuł się profesjonalistą, teraz za każdym razem, gdy widział, zbliżającego się do jego biurka testera klął pod nosem. Stracił ten błysk w oku i zapał do pracy. Do pokonania negatywnych emocji nie wystarczały mu już papierosy. Co następnie, alkohol?

A mógł tego wszystkiego uniknąć, wystarczyło, żeby nauczył się pisać testy jednostkowe.

V. Poziomy pętli informacji zwrotnej

Człowiek popełnia błędy. Dlatego w pracę programisty wpleciona jest pętla informacji zwrotnej — im jest krótsza, tym lepiej. Szybka informacja o występującym błędzie w algorytmie pozwala zaoszczędzić dużo czasu.


Pętle informacji zwrotnej można podzielić na następujące poziomy:


Poziom 0 — Testy jednostkowe

Poziom 1 — Testy automatyczne serwer buildów

Poziom 2 — Testy manualne, wykonywane przez programistę

Poziom 3 — Testy manualne, wykonywane przez testera

Poziom 4 — Produkcja

Rys. 1. Pętla informacji zwrotnej w stosunku do czasu.

Im więcej błędów zostanie wyeliminowanych, przez testy jednostkowe tym lepiej. Produkcja nie powinna zgłaszać żadnych problemów, jedynie sugestie zmian funkcjonalności. Zdaję sobie sprawę, że tak nie będzie, ponieważ w każdym systemie zdarzają się bugi. Twoim celem jest, by było ich jak najmniej.

Jeśli posiadasz zestawy przypadków testowych dla całego systemu i używasz ich w procesie Continuous Integration, to jako programista możesz zrezygnować z testów manualnych, zostawiając tę czynność testerowi. Jednak zawsze mile widziane jest choć podstawowe „przeklikanie” funkcjonalności

Niektóre z firm tak bardzo ufają testom automatycznym, że pomijają pracę testera i każdy commit po przejściu testów wbudowanych w build serwer, od razu jest wgrywany na produkcję. Ten proces nazywa się Continuous Delivery

VI. Jakość kodu

System pokryty testami automatycznymi pozwala na częstszą i prostszą refaktoryzacje. Posiadając testy, możesz bez obaw ulepszać swój kod. Po zmianach uruchamiasz tylko zestawy przypadków testowych, czyli pliki zawierające klasy z testami. Jeśli nie zobaczysz czerwonego koloru, to nowa wersja może zostać wprowadzona do repozytorium.

Kod produkcyjny musi mieć odpowiednią strukturę, by dało się do niego napisać testy jednostkowe. Przez to w niezamierzony sposób wymuszają one na programiście pisanie lepszego jakościowo kodu.

Zasady SOLID staną się twoimi najlepszymi przyjaciółmi. Pomijając je, szybko odkryjesz problemy podczas budowania zestawów przypadków testowych. W najgorszym razie możesz nawet stwierdzić, że do napisanego kodu nie da się stworzyć testów. Czasem tak się dzieje. Nic się nie martw, wystarczy zdobyta w tej książce wiedza oraz trochę doświadczenia i ten problem przestanie istnieć.

VII. Mniejsza ilość błędów

Pisząc testy, układasz scenariusze warte sprawdzenia. Skupiasz się nie tylko nad optymistycznymi ścieżkami, ale też nad prawdopodobnymi problemami z kodem. Na początku swojej przygody czas poświęcony na tę czynność może wydawać ci się zbyt długi. Jednak z rosnącym doświadczeniem wyrobisz w sobie szósty zmysł do wyszukiwania i natychmiastowego eliminowania słabych punktów kodu. Jest to niezwykle cenna umiejętność. Możesz ją wykorzystać nie tylko dla swojej pracy, ale również podczas code review.

Warto wyrobić w sobie nawyk krytycznego spoglądania na kod, dzięki temu zminimalizujesz ilość zgłaszanych bugów.

W przypadku gdy tester zgłosi błąd, piszesz test, który nie przechodzi, potem poprawiasz kod. Następnie uruchamiasz wszystkie testy. Zielony kolor, powinien oznaczać, że poprawka nie wpłynęła negatywnie na system, co pozwoli ci w nocy zasnąć spokojnym snem. Napisany test jest gwarancją, że ten sam błąd już nigdy się nie pojawi w systemie.

Z własnego doświadczenia wiem, że testy jednostkowe pozwalają wyeliminować bardzo dużą część błędów. Dlatego naprawdę warto je pisać.

VIII. MIT: Pisząc testy, twoje tempo pracy zwolni

Uważaj, w tę pułapkę wpada bardzo wielu programistów. Zwolnienie tempa pracy oczywiście jest zauważalne. Nie wynika ono jednak bezpośrednio z pisania testów.

Utrata szybkości spowodowana jest tym, że najpierw uczysz się dostarczać lepszej jakości kod. Szlifujesz umiejętność szukania słabych stron swojego rozwiązania. No i oczywiście nabierasz dopiero doświadczenia w pisaniu testów.

Gdy to wszystko opanujesz, niewątpliwie przyśpieszysz. Z czasem tworzenie zestawów przypadków testowych stanie się dla ciebie tak naturalne, że nie będziesz wyobrażał sobie pracy bez tego przydatnego narzędzia.

Pamiętaj, że testy same w sobie nie dają gwarancji jakości. To ty jako profesjonalny programista jesteś jej gwarantem. Ucz się i rozwijaj, każdego dnia a zobaczysz jak szybko, będziesz pisał lepszy kod.

IX. Rodzaje testów automatycznych

Testy automatyczne przez pewien okres cieszyły się złą sławą. Wynikała ona ze skupienia się na testach e2e (end-to-end). Przechodzą one przez wszystkie komponenty systemu, począwszy od interfejsu użytkownika, poprzez logikę aplikacyjną a na zapisie w bazie danych kończąc. Ich największym problemem jest kruchość oraz koszt.

Dopiero gdy Mike Cohn w swojej książce Succeeding with Agile zaczął promować piramidę testów automatycznych, wróciły one do łask, stając się teraz wręcz standardem.


Piramida została podzielona na trzy typy.

Rys. 1. Piramida automatyzacji testów

Testy rozłożone w takich proporcjach minimalizują koszt związany z ich wytworzeniem oraz utrzymaniem. Podział ten nie jest uzależniony od architektury systemu czy metodyki jego projektowania, przez co jest uniwersalny. Przyjrzyjmy się każdemu z poziomów:

UI

Testów e2e powinno być jak najmniej, najlepiej kilka na moduł. Ich zadaniem jest sprawdzenie głównej i najważniejszej ścieżki procesu. Są one bardzo kruche oraz wykonują się długo. Chronią przede wszystkim przed regresją kodu.

Service

Testy integracyjne wykonują się nieco szybciej od testów e2e. Jednak nie dostatecznie szybko by stanowiły podstawę piramidy. Ich głównym celem jest testowanie aplikacji w oderwaniu od interfejsu użytkownika. Wykorzystują one jednak rzeczywiste zależności infrastrukturalne, na przykład bazę danych.

Istnieje możliwość wymiany „prawdziwej” bazy danych na tworzoną w pamięci. To rozwiązanie jest znacznie szybsze, ale nie jest pozbawione wad, jedną z nich są różnice między tymi typami baz, przez co nie zawsze da się wprowadzić takie rozwiązanie.

Innym problemem jest to, że te testy i tak wykonują się wolniej niż testy jednostkowe. Przez to w dużych systemach informatycznych opieranie się na testach integracyjnych może spowodować wydłużenie się czasu budowania paczki przez serwer buildów do nieakceptowalnych wartości.

Unit

Testy jednostkowe to podstawa piramidy. Są niezaprzeczalnie najszybsze, jest je też najprościej napisać i wdrożyć do procesu budowania paczki. Wynika to z faktu, że działają w całkowitym oderwaniu od interfejsu użytkownika i od infrastruktury.


Testy jednostkowe będą głównym tematem tej książki. Za ich pomocą sprawdzisz poprawność logiki domenowej oraz aplikacyjnej. W twoim systemie będzie ich najwięcej, więc musisz się skupić na tym, by były one napisane jak najlepiej. Dodatkowo wiedzę oraz doświadczenie zdobyte podczas ich tworzenia możesz przenieść na kolejne poziomy piramidy.

X. Zasada 80/20

Zasada Pareto jest również znana pod nazwą 80/20. Cieszy się największą popularnością w biznesie i ekonomii, ale świetnie sprawdza się praktycznie w każdej dziedzinie życia. Mówi ona o tym, że 20% twoich nakładów i wysiłków odpowiada za 80% osiągniętych efektów.

Idealnie do tej zasady pasują testy jednostkowe. Najniższym kosztem, wykonują najwięcej pracy. Oprócz tego, że najłatwiej się je pisze i są proste w utrzymaniu, to sprawdzają poprawność logiki domenowej oraz aplikacyjnej.

Oderwanie testów jednostkowych od infrastruktury gwarantuje ich uniwersalność i niezależność. W przypadku, gdy z jakiegoś powodu zmienisz dostawcę bazy danych lub API, z którym się integrujesz, nie będziesz musiał poprawiać swoich zestawów przypadków testowych. Dlatego kluczowe jest, abyś to właśnie na tych testach skupił swoją uwagę i opanował ich pisanie na poziomie mistrzowskim.

Pamiętaj, że testy infrastrukturalne i e2e są znacznie droższe i bardziej kłopotliwe w utrzymaniu. Traktuj je jako dodatek.

XI. Nazwa klasy oraz pliku z testami

Testy to metody znajdujące się w klasie. Jest ona najczęściej nazywana zestawem przypadków testowych (Test Suite).

Są dwa bardzo popularne sposoby nazewnictwa klas oraz plików z testami. Aby stworzyć nazwę dla zestawu przypadków testowych, do nazwy klasy, którą chcemy przetestować, dopisujemy Tests lub TestSuite.

Przykładowo chcesz napisać testy dla serwisu o nazwie OrderService. W takim przypadku klasę zawierającą testy możesz nazwać OrderServiceTests bądź OrderServiceTestSuite a plik oczywiście OrderServiceTests. cs lub OrderServiceTestSuite. cs

Rys. 1. Zestaw przypadków testowych.

Dobre nazewnictwo klas z testami jest bardzo istotne. Dzięki niemu zachowasz porządek w swoim systemie i o wiele prościej będzie Ci odnaleźć interesujący cię zestaw przypadków testowych.

XII. Budowa testu

Bardzo popularną koncepcją budowy testu jest AAA, czyli Arrange-Act-Assert znana również jako Given-When-Then. Opracował tę koncepcję Bill Wake.

Zakłada ona podział struktury testu w następujący sposób:


Arrange w tej części tworzymy założenia wstępne naszego testu. Inicjalizujemy niezbędne obiekty. Obiekt klasy, którą testujemy, nazywamy sut lub cut od (system under test lub class under test). Taki styl nazewnictwa pomaga odróżnić obiekt testowanej klasy, od obiektów, które tylko biorą udział w teście.


Act uruchamia testowaną funkcjonalność. Jeżeli jest taka potrzeba, to przekazujemy wymagane parametry do testowanej przez nas metody.


Assert odpowiada za sprawdzenie warunków określających powodzenie testu.

Rys. 1. Podział testu na części Arrange-Act-Assert.

Sekcje testu polecam oddzielać od siebie enterem. W przypadku testów zawierających dużą ilość kodu dobrze jest napisać komentarz z nazwą sekcji. Znacząco poprawi to czytelność metody testowej.

Rys. 2. Zastosowanie komentarzy do zwiększenia czytelność metody testowej.

Rozdzielenie testu na te trzy sekcje sprawi, że zrozumienie i utrzymanie metod testowych stanie się o wiele prostsze.

XIII. Testy a architektura systemu

Wiesz już jak tworzyć i nazywać zestawy przypadków testowych. Pokażę ci teraz, w jakim miejscu w solucji powinny się one znaleźć.

Zestawy przypadków testowych umieszczamy w osobnym projekcie. W zależności od potrzeb możemy mieć kilka projektów z testami. Najczęściej nazwy projektów zawierają typy testów automatycznych.

Rys. 2. Przykładowa struktura solucji.

Na rysunku powyżej widzisz przykładową strukturę aplikacji podzieloną na komponenty, które znajdują się w osobnych folderach.

W projekcie zawierającym testy stwórz katalogi według struktury solucji. W ten sposób szybko odnajdziesz interesujące cię pliki z testami.

Przeczytałeś bezpłatny fragment.
Kup książkę, aby przeczytać do końca.
E-book
za 6.83
drukowana A5
za 26.16
drukowana A5
Kolorowa
za 49.63