Gruca Dariusz

Testy jednostkowe z Net Core (C#)

Szybki start

Korektor Krzysztof Bonk (boonkbook.pl)

Projektant okładki Dariusz Gruca

Podziękowania:

Tithi Luadthong Grafika na okładce

© Gruca Dariusz, 2020

© Dariusz Gruca, projekt okładki, 2020

Testy jednostkowe powoli stają się standardem w branży programistycznej. Wielotygodniowe kursy za setki złotych nie są już potrzebne. Książka zawiera wymaganą wiedzę do rozpoczęcia przygody z testowaniem aplikacji. Skierowana jest do osób początkujących, niezaznajomionych z tematyką.

ISBN 978-83-8221-538-0

Książka powstała w inteligentnym systemie wydawniczym Ridero

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.

Rys. 3. Przykładowa struktura projektu z testami.

Utrzymanie porządku jest naprawdę istotne. Szczególnie nabiera to znaczenia przy zwiększającej się ilości testów. Dzięki odpowiedniemu nazewnictwu zestawów przypadków testowych oraz umieszczaniu plików we właściwych katalogach w solucji jesteś w stanie bardzo szybko odnaleźć interesujący cię plik.

Bardzo dobrze do tego celu sprawdza się Search Solution Explorer. Wystarczy, że wpiszesz nazwę interesującego cię zestawu przypadków testowych, a Visual Studio go odnajdzie.

Rys. 4. Szybkie wyszukanie zestawu przypadków testowych.

Stosowanie konwencji nazewniczej znacząco uprości ci życie. Zawsze będziesz wiedział w jakim projekcie, katalogu, pliku szukać testów interesującej cię klasy.

XIV. Nazwa testu ma znaczenie

W przypadku gdy test nie przejdzie, to jego dobrze dobrana nazwa powinna spowodować pojawienie się u ciebie zrozumienia potencjalnego powodu wystąpienia usterki. Jeśli bez debugowania jesteś w stanie stwierdzić, co się zepsuło, to wtedy dobrze nazwałeś test. W przypadku, kiedy musisz najpierw zrozumieć, jak test działa, a potem i tak debugować kod, to coś poszło nie tak i nazwa nie spełniła swej funkcji, przez co na niewiele się zdała. Dobre nazewnictwo ułatwia proces refaktoryzacji, wiesz, jaką cześć funkcjonalności przez przypadek uszkodziłeś.

Inną niewątpliwą zaletą odpowiedniego doboru nazwy jest to, że pomoże ci ona w szybszym powrocie do kontekstu pracy. Gdy przychodzisz rano, wystarczy, że otworzysz plik zawierający zestaw przypadków testowych dla funkcjonalności, nad którą pracujesz. Przeglądasz testy i już wiesz, na czym skończyłeś i co zostało ci jeszcze do zrobienia.

Długie nazwy typu: Given_WarunkiWstepne_When_CoSprawdzamy_Then_OczekiwanyRezultat dobrze sprawdzają się przy testach integracyjnych. Krótkie nazewnictwo częściej stosuje się przy testach jednostkowych.

Spotkałem się z różnymi stylami nazewnictwa testów. Oto niektóre z nich:

— CoSprawdzamy_OczekiwanyRezultat

— NazwaMetody_CoSprawdzamy_OczekiwanyRezultat

— NazwaMetody_OczekiwanyRezultat_CoSprawdzamy

— Should_OczekiwanyRezultat_When_CoSprawdzamy FunkcjaDoPrzetestowania (np. IsNotAccesDeniedIfAgeOfUserIsLessThan18)

— When_CoSprawdzamy_Then_NazwaMetody_Should_OczekiwanyRezultat

— When_CoSprawdzamy_Expect_OczekiwanyRezultat

— Given_WarunkiWstepne_When_CoSprawdzamy_Then_OczekiwanyRezultat

Oczywiście nie musisz używać „_”:

— CoSprawdzamyOczekiwanyRezultat

— NazwaMetodyCoSprawdzamyOczekiwanyRezultat

— NazwaMetodyOczekiwanyRezultatCoSprawdzamy

— ShouldOczekiwanyRezultatWhenCoSprawdzamy

— WhenCoSprawdzamyThenNazwaMetodyShouldOczekiwanyRezultat

— WhenCoSprawdzamyExpectOczekiwanyRezultat

— GivenWarunkiWstepneWhenCoSprawdzamyThenOczekwianyRezultat

Jest w czym wybierać. Nie ograniczaj się tylko do wymienionych przeze mnie sposobów. Bez problemu możesz wymyślić coś swojego. Kreatywność to coś wspaniałego. Tylko pamiętaj, że nazwa testu ma ci sugerować zakres jego odpowiedzialności.

Więc jaki styl nazewnictwa wybrać?

Najlepiej omówić to z całym zespołem. Ustalcie wspólnie jakie nazewnictwo będzie obowiązywało w całym systemie. Jeżeli zespół nie jest jeszcze doświadczony, to polecam trochę poeksperymentować i po pewnym czasie określić, który styl lub style najbardziej wam odpowiadają.

XV. Wybór frameworka

Chce zaoszczędzić twój cenny czas, dlatego nie będę się rozpisywał nad wadami i zaletami dostępnych frameworków. Sytuacja może się też w każdej chwili zmienić, wystarczy, że wyjdzie nowa wersja. Najważniejsze dla ciebie jest nauczenie się tworzenia testów, narzędzie schodzi na drugi plan. Obecnie dla. Net Core polecany jest xUnit. Według mnie jest on też najprzyjemniejszy w użyciu. Dlatego z jego drobną pomocą pokażę ci jak pisać testy jednostkowe. Jego konkurenci to MSTest i NUnit.

Do automatycznego tworzenia atrap, zastosujemy Moq. W tej chwili ma on tylko jedną sensowną alternatywę Nsubstitute.

XVI. Tworzenie projektu

Stworzymy teraz projekt w. Net Core za pomocą Visual Studio 2019.

Rys. 1. Wybór rodzaju projektu

Z okna tworzenia nowego projektu w Visual Studio 2019 wybierz Class Library (.Net Core). W tym właśnie projekcie umieścimy kod, który będziemy testować.

Rys. 2. Wybór rodzaju projektu

Pierwsze testy jednostkowe napiszemy dla prostego kalkulatora. Więc w oknie Configure your new project, wpisz więc jako nazwę projektu SimpleCalculator.

W Localisation wybierz miejsce utworzenia projektu na dysku.

Solutuon name to nazwa naszej solucji, która jest zbiorem projektów. Dlatego jej nazwa powinna być związana z całym systemem. W naszym przypadku będzie się ona odnosiła do szybkiego startu z testami jednostkowymi. Więc nazwa UnitTestQuickStart wydaje się odpowiednia.

Rys. 3. Struktura projektu w oknie Solution Explorer

Projekt tworzony w tej książce jest niewielki, dlatego nie będziemy tworzyć struktury katalogów. Przejdziemy teraz do stworzenia projektu z testami.

XVII. Projekt z testami

Projekt z testami można stworzyć na kilka sposobów. Możesz dodać ClassLibrary (.Net Core) i do niego wgrać odpowiednie frameworki za pomocą Manage NuGet Packages lub wpisać odpowiednie komendy służące do instalacji frameworków w oknie Package Manager Console. Jednak niezaprzeczalnie najszybszym sposobem jest dodanie nowego dedykowanego dla testów projektu za pomocą Visual Studio 2019.

Twój czas się dla mnie liczy, więc wybierzmy najszybszą możliwość. Kliknij prawym przyciskiem myszy na nazwę solucji w Solution Explorer i z menu kontekstowego wybierz Add => New Project…

Rys. 1. Menu kontekstowe dla solucji.

Na ekranie pojawi się znajome okno dodawania projektu.

Rys. 2. Okno dodawania projektu w Visual Studio 2019

W wyszukiwarce ulokowanej w górnej części okna wpisz: xunit. Następnie wybierz xUnit Test Project(.Net Core) i kliknij Next.

Rys. 3. Okno ustawień projektu w Visual Studio 2019

W oknie ustawień dla projektu wpisz w pole Project name, nazwę projektu. Ze względu na to, że w tej książce skupiamy się na testach jednostkowych, dlatego odpowiednią nazwą będzie Tests. Unit

Rys. 4. Okno Solution Explorer. Struktura naszej Solucji

Proste. Visual Studio stworzył dla nas projekt z wymaganymi frameworkiami:

Microsoft.Net.Test.Sdk

Xunit

Xunit.runner.visualstudio

Już prawie mamy wszystkie wymagane narzędzia. Pozostało nam zainstalować tylko Moq i przejdziemy do tworzenia pierwszego testu. Zdaję sobie sprawę, że te rozdziały mogą być trochę nudne, ale są niezbędne. Musisz mieć wszystkie potrzebne narzędzia do pracy.

XVIII. Instalacja Moq

Moq wykona za ciebie ogrom pracy poprzez stworzenie obiektów atrap. Pozwoli ci je ustawić oraz weryfikować poprawność integracji między obiektami. Nie musisz już sam pisać klas wykonujących tę pracę, przez co zaoszczędzasz naprawdę dużo czasu i nerwów. Uwierz lub sam poeksperymentuj.

Początek nauki jest ekscytujący, zdobywasz nową wiedzę, chcesz ją jak najszybciej wykorzystać, wszystko widzisz w jasnych barwach. Jednak gdy pozytywne emocje opadną i przyjdzie codzienna praca, w której pisanie testów jednostkowych będzie dla ciebie normą, to docenisz każdą możliwą automatyzację powtarzającego się kodu. Tworzenie ręcznie kodu atrap nie pomaga ci bezpośrednio w osiągnięcie celu, jakim jest sprawdzenie logiki biznesowej lub integracji między obiektami. Bardzo dobrze, że powstały takie narzędzia, które wyręczają nas w tym niewątpliwie nużącym obowiązku.

Zdaje sobie sprawę z tego, że możesz czuć się jeszcze trochę zagubiony i nie do końca rozumieć, o czym piszę. Nic się nie martw, do wszystkiego dojdziemy w odpowiednim momencie. Skupmy się teraz na zainstalowaniu Moq.

Za pomocą Manage NuGet Packages, instalujemy Moq, tak jak by był zwykłym programem. Dlatego zdecydowałem się na tę opcję instalacji, wydaje się bardziej naturalna. Kliknij prawym przyciskiem myszy w projekcie Tests. Unit na Dependencies. Z menu kontekstowego wybierz Manage NuGet Packages…

Rys. 1. Menu kontekstowe dla Dependencies projektu Tests. Unit

Pojawi się okno NuGet Package Manager. W górnej części wybierz zakładkę Browse. Następnie poniżej w wyszukiwarce wpisz: moq. Kliknij lewym przyciskiem myszy na Moq by Daniel Cazzulino.

Rys. 2. Okno NuGet Package Manager

Po prawej stronie okna znajduje się wybór wersji narzędzia. Wybierz Last stable. Następnie kliknij przycisk Install.

Visual Studio 2019 wyświetli okno Preview Changes.

Koniec darmowego fragmentu książki.

Zachęcamy do zakupu pełnej wersji.