Cyfroteka.pl

klikaj i czytaj online

Cyfro
Czytomierz
00749 010214 10704503 na godz. na dobę w sumie
Testy jednostkowe. Świat niezawodnych aplikacji. Wydanie II - książka
Testy jednostkowe. Świat niezawodnych aplikacji. Wydanie II - książka
Autor: Liczba stron: 320
Wydawca: Helion Język publikacji: polski
ISBN: 978-83-246-8774-9 Data wydania:
Lektor:
Kategoria: ebooki >> komputery i informatyka >> programowanie >> inne - programowanie
Porównaj ceny (książka, ebook, audiobook).

Poznaj możliwości testów jednostkowych!

System informatyczny to inteligentne połączenie modułów i zależności, otoczone setkami tysięcy, a nawet milionami linii kodu źródłowego. Zmiana w jednym obszarze może mieć fatalny wpływ na działanie systemu w zupełnie innym miejscu. Ta zależność prowadzi do ogromnych kosztów wprowadzenia nawet najdrobniejszej zmiany w oprogramowaniu. Czy istnieje rozwiązanie tego problemu? Jak stworzyć system, w którym błyskawiczna weryfikacja lub wprowadzona zmiana nie spowodują nowych błędów w innej części? Oczywiście, że można to zrobić! Odpowiedzią na te i wiele innych problemów są testy automatyczne.

Ten przewodnik to doskonała okazja, by głębiej poznać temat testów jednostkowych. Jeżeli uważasz, że ich pisanie jest uciążliwe, czasochłonne, trudne lub po prostu nie wiesz, jak je tworzyć, ta książka rozwiąże wszystkie Twoje problemy! W trakcie lektury dowiesz się, jak pisać testy, tworzyć zestawy testowe oraz przygotowywać makiety i namiastki. Poznasz narzędzia Moq, FakeItEasy oraz Typemock Isolator. Ponadto zdobędziesz wiedzę na temat organizacji testów oraz strategii testowania kodu odziedziczonego. Książka ta jest obowiązkową lekturą dla wszystkich programistów C# szukających świetnego przewodnika po świecie testów jednostkowych!

Dzięki tej książce:

Niezawodny kod jest w Twoim zasięgu!

Znajdź podobne książki Ostatnio czytane w tej kategorii

Darmowy fragment publikacji:

Tytuł oryginału: The Art of Unit Testing: With Examples in .NET, 2nd Edition Tłumaczenie: Radosław Meryk ISBN: 978-83-246-8774-9 Original edition copyright © 2014 by Manning Publications Co. All rights reserved. Polish edition copyright © 2014 by HELION SA. All rights reserved. All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording or by any information storage retrieval system, without permission from the Publisher. Wszelkie prawa zastrzeżone. Nieautoryzowane rozpowszechnianie całości lub fragmentu niniejszej publikacji w jakiejkolwiek postaci jest zabronione. Wykonywanie kopii metodą kserograficzną, fotograficzną, a także kopiowanie książki na nośniku filmowym, magnetycznym lub innym powoduje naruszenie praw autorskich niniejszej publikacji. Wszystkie znaki występujące w tekście są zastrzeżonymi znakami firmowymi bądź towarowymi ich właścicieli. Autor oraz Wydawnictwo HELION dołożyli wszelkich starań, by zawarte w tej książce informacje były kompletne i rzetelne. Nie biorą jednak żadnej odpowiedzialności ani za ich wykorzystanie, ani za związane z tym ewentualne naruszenie praw patentowych lub autorskich. Autor oraz Wydawnictwo HELION nie ponoszą również żadnej odpowiedzialności za ewentualne szkody wynikłe z wykorzystania informacji zawartych w książce. Projekt okładki: Studio Gravite / Olsztyn Obarek, Pokoński, Pazdrijowski, Zaprucki Materiały graficzne na okładce zostały wykorzystane za zgodą Shutterstock Images LLC. Wydawnictwo HELION ul. Kościuszki 1c, 44-100 GLIWICE tel. 32 231 22 19, 32 230 98 63 e-mail: helion@helion.pl WWW: http://helion.pl (księgarnia internetowa, katalog książek) Drogi Czytelniku! Jeżeli chcesz ocenić tę książkę, zajrzyj pod adres http://helion.pl/user/opinie/tesjed Możesz tam wpisać swoje uwagi, spostrzeżenia, recenzję. Printed in Poland. • Kup książkę • Poleć książkę • Oceń książkę • Księgarnia internetowa • Lubię to! » Nasza społeczność Spis tre(cid:258)ci S(cid:239)owo wst(cid:218)pne do drugiego wydania 11 S(cid:239)owo wst(cid:218)pne do pierwszego wydania 13 Przedmowa 15 Podzi(cid:218)kowania 17 O tej ksi(cid:200)(cid:285)ce 19 O ilustracji na ok(cid:239)adce 24 CZ(cid:125)(cid:165)(cid:109) I. ZACZYNAMY 25 Rozdzia(cid:239) 1. Podstawowe informacje o testach jednostkowych 27 1.1. Definicja testu jednostkowego krok po kroku 28 1.1.1. Dlaczego wa(cid:285)ne jest pisanie „dobrych” testów jednostkowych 29 1.1.2. Wszyscy piszemy testy jednostkowe (w pewnym sensie) 30 1.2. W(cid:239)a(cid:258)ciwo(cid:258)ci dobrego testu jednostkowego 31 1.3. Testy integracyjne 31 1.3.1. Wady niezautomatyzowanych testów integracyjnych w porównaniu z automatycznymi testami jednostkowymi 33 1.4. Co sprawia, (cid:285)e test jednostkowy jest dobry 36 1.5. Prosty przyk(cid:239)ad testu jednostkowego 37 1.6. Wytwarzanie oprogramowania sterowane testami 40 1.7. Trzy zasadnicze umiej(cid:218)tno(cid:258)ci potrzebne do skutecznego stosowania technik TDD 43 1.8. Podsumowanie 44 Rozdzia(cid:239) 2. Pierwszy test jednostkowy 45 2.1. Frameworki testów jednostkowych 46 2.1.1. 2.1.2. Co oferuj(cid:200) frameworki testów jednostkowych 46 Frameworki xUnit 49 2.2. Wprowadzenie w tematyk(cid:218) projektu LogAn 49 2.3. Pierwsze kroki z NUnit 49 2.3.1. 2.3.2. 2.3.3. Wykorzystanie atrybutów NUnit w kodzie 54 Instalacja frameworka NUnit 50 (cid:146)adowanie rozwi(cid:200)zania 51 2.4. Piszemy pierwszy test 55 Klasa Assert 55 Uruchomienie pierwszego testu za pomoc(cid:200) frameworka NUnit 56 2.4.1. 2.4.2. 2.4.3. Dodanie testów pozytywnych 58 2.4.4. Od czerwonego do zielonego: d(cid:200)(cid:285)enie do spe(cid:239)nienia testów 59 2.4.5. Styl kodu testów 59 Poleć książkęKup książkę 6 Spis tre(cid:258)ci 2.5. Refaktoryzacja w kierunku testów z parametrami 59 2.6. Wi(cid:218)cej atrybutów NUnit 62 2.6.1. 2.6.2. 2.6.3. 2.6.4. 2.6.5. Atrybuty Setup i TearDown 62 Testowanie wyst(cid:218)powania oczekiwanych wyj(cid:200)tków 65 Ignorowanie testów 67 Sk(cid:239)adnia fluent frameworka NUnit 68 Ustawianie kategorii testowych 69 2.7. Testowanie wyników metod, które nie zwracaj(cid:200) warto(cid:258)ci, tylko zmieniaj(cid:200) stan systemu 70 2.8. Podsumowanie 74 CZ(cid:125)(cid:165)(cid:109) II. PODSTAWOWE TECHNIKI 75 Rozdzia(cid:239) 3. Wykorzystanie namiastek do rozwi(cid:200)zywania zale(cid:285)no(cid:258)ci 77 Identyfikacja zale(cid:285)no(cid:258)ci od systemu plików w klasie LogAnalyzer 78 3.1. Wprowadzenie w tematyk(cid:218) namiastek 77 3.2. 3.3. Okre(cid:258)lenie sposobu (cid:239)atwego testowania klasy LogAnalyzer 79 3.4. Refaktoryzacja projektu w celu u(cid:239)atwienia testowania 82 3.4.1. Wyodr(cid:218)bnienie interfejsu umo(cid:285)liwiaj(cid:200)cego zast(cid:200)pienie istniej(cid:200)cej implementacji 84 3.4.2. Wstrzykiwanie zale(cid:285)no(cid:258)ci: wstrzykni(cid:218)cie sztucznej implementacji do testowanej jednostki 86 3.4.3. Wstrzykni(cid:218)cie sztucznego obiektu na poziomie konstruktora 86 3.4.4. 3.4.5. Wstrzykni(cid:218)cie sztucznego obiektu Symulowanie wyj(cid:200)tków z poziomu sztucznych obiektów 90 za pomoc(cid:200) gettera lub settera w(cid:239)a(cid:258)ciwo(cid:258)ci 91 3.4.6. Wstrzykni(cid:218)cie sztucznego obiektu bezpo(cid:258)rednio przed wywo(cid:239)aniem metody 93 3.5. Odmiany technik refaktoryzacji 100 3.5.1. Wykorzystanie techniki „wyodr(cid:218)bnij i przes(cid:239)o(cid:241)” do tworzenia sztucznych wyników 100 3.6. Pokonanie problemu hermetyzacji 102 Korzystanie ze sk(cid:239)adowych internal oraz atrybutu [InternalsVisibleTo] 103 3.6.1. 3.6.2. Wykorzystanie atrybutu [Conditional] 103 3.6.3. Korzystanie z dyrektyw #if i #endif do warunkowej kompilacji 104 3.7. Podsumowanie 104 Rozdzia(cid:239) 4. Testowanie interakcji z wykorzystaniem obiektów-makiet 107 4.1. Testy bazuj(cid:200)ce na warto(cid:258)ci, testy bazuj(cid:200)ce na stanach a testy integracyjne 108 4.2. Ró(cid:285)nica pomi(cid:218)dzy obiektami-makietami a namiastkami 110 4.3. Napisany r(cid:218)cznie prosty przyk(cid:239)ad obiektu-makiety 111 4.4. Wykorzystywanie obiektów-makiet razem z namiastkami 114 4.5. 4.6. (cid:146)a(cid:241)cuch sztucznych obiektów: namiastki, Jedna makieta na test 118 które generuj(cid:200) makiety lub inne namiastki 119 4.7. Problemy z pisanymi r(cid:218)cznie makietami i namiastkami 120 4.8. Podsumowanie 121 Poleć książkęKup książkę Spis tre(cid:258)ci 7 Rozdzia(cid:239) 5. Frameworki izolacji 123 5.1. Dlaczego stosujemy frameworki izolacji? 124 5.2. Dynamiczne tworzenie sztucznych obiektów 126 5.2.1. Wykorzystanie frameworka NSubstitute w testach 126 5.2.2. Zast(cid:200)pienie sztucznego obiektu napisanego r(cid:218)cznie obiektem dynamicznym 127 5.3. Symulacja sztucznych warto(cid:258)ci 130 5.3.1. Wprowadzamy do testu makiet(cid:218) razem z namiastk(cid:200) 131 5.4. Testowanie dzia(cid:239)a(cid:241) zwi(cid:200)zanych ze zdarzeniami 136 5.4.1. 5.4.2. Testowanie obiektu nas(cid:239)uchuj(cid:200)cego zdarzenia 136 Testowanie, czy zosta(cid:239)o wyzwolone zdarzenie 138 5.5. Wspó(cid:239)czesne frameworki izolacji dla (cid:258)rodowiska .NET 138 5.6. Zalety i pu(cid:239)apki frameworków izolacji 140 5.6.1. Pu(cid:239)apki, których nale(cid:285)y unika(cid:202) w przypadku korzystania z frameworków izolacji 140 Nieczytelny kod testu 141 5.6.2. 5.6.3. Weryfikacja niew(cid:239)a(cid:258)ciwych rzeczy 141 5.6.4. Wi(cid:218)cej ni(cid:285) jedna makieta w te(cid:258)cie 141 5.6.5. Nadspecyfikacja testów 141 5.7. Podsumowanie 142 Rozdzia(cid:239) 6. Bardziej zaawansowane zagadnienia zwi(cid:200)zane z frameworkami izolacji 145 6.1. Frameworki ograniczone i nieograniczone 146 6.1.1. 6.1.2. 6.1.3. Frameworki ograniczone 146 Frameworki nieograniczone 146 Jak dzia(cid:239)aj(cid:200) nieograniczone frameworki bazuj(cid:200)ce na profilerze 148 6.2. Warto(cid:258)(cid:202) dobrych frameworków izolacji 151 6.3. W(cid:239)asno(cid:258)ci wspieraj(cid:200)ce d(cid:239)ugowieczno(cid:258)(cid:202) i u(cid:285)yteczno(cid:258)(cid:202) 152 Imitacje rekurencyjne 152 6.3.1. 6.3.2. Domy(cid:258)lne ignorowanie argumentów 153 6.3.3. 6.3.4. 6.3.5. Rozleg(cid:239)e imitacje 153 Nie(cid:258)cis(cid:239)e zachowania sztucznych obiektów 154 Nie(cid:258)cis(cid:239)e makiety 154 6.4. Antywzorce projektowe frameworków izolacji 155 6.4.1. Myl(cid:200)ce poj(cid:218)cia 155 6.4.2. 6.4.3. 6.4.4. Zarejestruj i odtwórz 156 Lepkie zachowania 158 Z(cid:239)o(cid:285)ona sk(cid:239)adnia 158 6.5. Podsumowanie 159 CZ(cid:125)(cid:165)(cid:109) III. KOD TESTU 161 Rozdzia(cid:239) 7. Hierarchie testów i ich organizacja 163 7.1. Testy uruchamiane w ramach automatycznych kompilacji 164 7.1.1. 7.1.2. Anatomia skryptu kompilacji 165 Inicjowanie kompilacji i integracji 167 Poleć książkęKup książkę 8 Spis tre(cid:258)ci 7.2. Klasyfikacja testów na podstawie szybko(cid:258)ci i typu 168 7.2.1. 7.2.2. Czynnik ludzki oddzielenia testów jednostkowych od testów integracyjnych 169 Bezpieczna zielona strefa 170 7.3. Zadbanie o umieszczenie testów w repozytorium z kodem (cid:283)ród(cid:239)owym 171 7.4. Odwzorowanie klas testowych na testowany kod 171 7.4.1. Odwzorowanie testów na projekty 171 7.4.2. Odwzorowanie testów na klasy 172 7.4.3. Odwzorowanie testów na punkty wej(cid:258)cia metod konkretnych jednostek pracy 173 7.5. Wstrzykiwanie zale(cid:285)no(cid:258)ci cross-cutting 173 7.6. Budowanie API obs(cid:239)ugi testów dla aplikacji 176 7.6.1. Wykorzystanie wzorców dziedziczenia w klasach testowych 176 7.6.2. 7.6.3. Tworzenie narz(cid:218)dziowych klas i metod obs(cid:239)ugi testów 189 Zapoznanie deweloperów ze stworzonym API 190 7.7. Podsumowanie 191 Rozdzia(cid:239) 8. Filary dobrych testów jednostkowych 193 8.1. Pisanie wiarygodnych testów 194 8.1.1. Decydowanie o tym, kiedy nale(cid:285)y usun(cid:200)(cid:202) lub zmodyfikowa(cid:202) testy 194 8.1.2. 8.1.3. 8.1.4. Oddzielenie testów jednostkowych od integracyjnych 202 8.1.5. Unikanie logiki w testach 199 Testowanie tylko jednego aspektu 201 Zapewnienie przegl(cid:200)dów kodu 203 8.2. Pisanie testów (cid:239)atwych w utrzymaniu 205 8.2.1. 8.2.2. 8.2.3. Testowanie metod prywatnych lub chronionych 205 Usuwanie duplikatów 207 Korzystanie z metod konfiguracyjnych w sposób u(cid:239)atwiaj(cid:200)cy utrzymanie 210 8.2.4. Wymuszanie izolacji testu 213 8.2.5. 8.2.6. 8.2.7. Unikanie wielu asercji dotycz(cid:200)cych ró(cid:285)nych aspektów 220 Porównywanie obiektów 222 Unikanie nadmiernej specyfikacji 225 8.3. Pisanie czytelnych testów 227 Nazwy testów jednostkowych 227 Nazwy zmiennych 228 8.3.1. 8.3.2. 8.3.3. Dobre komunikaty asercji 229 8.3.4. Oddzielenie asercji od akcji 230 8.3.5. Konfigurowanie i rozbiórka 231 8.4. Podsumowanie 231 CZ(cid:125)(cid:165)(cid:109) IV. PROJEKTOWANIE I PROCES 233 Rozdzia(cid:239) 9. Wdra(cid:285)anie testów jednostkowych w organizacji 235 9.1. Jak zosta(cid:202) agentem zmian? 236 9.1.1. 9.1.2. 9.1.3. Okre(cid:258)lenie mo(cid:285)liwych punktów wej(cid:258)cia 237 B(cid:200)d(cid:283) przygotowany na trudne pytania 236 Przekonaj inne osoby z organizacji: mistrzów i oponentów 236 Poleć książkęKup książkę Spis tre(cid:258)ci 9 9.2. Sposoby na odniesienie sukcesu 239 9.2.1. Wdro(cid:285)enie po partyzancku (dó(cid:239)-góra) 239 9.2.2. Przekonanie kierownictwa (góra-dó(cid:239)) 240 9.2.3. Mistrz z zewn(cid:200)trz 240 9.2.4. 9.2.5. D(cid:200)(cid:285)enie do konkretnych celów 242 9.2.6. Zadbanie o widoczno(cid:258)(cid:202) post(cid:218)pów 241 U(cid:258)wiadomienie sobie istnienia przeszkód 244 9.3. Czynniki wp(cid:239)ywaj(cid:200)ce na pora(cid:285)k(cid:218) 244 9.3.1. 9.3.2. 9.3.3. 9.3.4. Brak si(cid:239)y nap(cid:218)dowej 245 Brak politycznego wsparcia 245 Z(cid:239)e implementacje i pierwsze wra(cid:285)enia 245 Brak wsparcia ze strony zespo(cid:239)u 246 9.4. Czynniki wp(cid:239)ywaj(cid:200)ce na zachowania cz(cid:239)onków zespo(cid:239)u 246 9.5. Trudne pytania i odpowiedzi 248 9.5.1. 9.5.2. Ile dodatkowego czasu b(cid:218)dzie trzeba po(cid:258)wi(cid:218)ci(cid:202)? 248 Czy ze wzgl(cid:218)du na wprowadzenie testów jednostkowych b(cid:218)dzie zagro(cid:285)one moje stanowisko in(cid:285)yniera jako(cid:258)ci? 250 Sk(cid:200)d wiemy, (cid:285)e testy jednostkowe si(cid:218) sprawdzaj(cid:200)? 250 Czy istnieje dowód, (cid:285)e testy jednostkowe pomagaj(cid:200)? 251 9.5.3. 9.5.4. 9.5.5. Dlaczego dzia(cid:239) kontroli jako(cid:258)ci ci(cid:200)gle znajduje b(cid:239)(cid:218)dy? 251 9.5.6. 9.5.7. 9.5.8. 9.5.9. 9.5.10. Debuger pokazuje, (cid:285)e mój kod dzia(cid:239)a (cid:127) do czego s(cid:200) mi potrzebne testy? 253 9.5.11. Czy trzeba stosowa(cid:202) kodowanie w stylu TDD? 253 Istnieje mnóstwo kodu, dla którego nie ma testów. Od czego zacz(cid:200)(cid:202)? 252 Kodujemy w kilku j(cid:218)zykach (cid:127) czy testy jednostkowe s(cid:200) wykonalne? 252 Co zrobi(cid:202), je(cid:258)li produkt obejmuje kombinacj(cid:218) oprogramowania i sprz(cid:218)tu? 253 Sk(cid:200)d mo(cid:285)emy wiedzie(cid:202), (cid:285)e nie ma b(cid:239)(cid:218)dów w testach? 253 9.6. Podsumowanie 254 Rozdzia(cid:239) 10. Praca z kodem odziedziczonym 255 10.1. Od czego nale(cid:285)y zacz(cid:200)(cid:202) przy dodawaniu testów? 256 10.2. Wybór strategii selekcji 258 10.2.1. Plusy i minusy strategii „najpierw (cid:239)atwe” 258 10.2.2. Plusy i minusy strategii „najpierw trudne” 259 10.3. Pisanie testów integracyjnych przed refaktoryzacj(cid:200) 259 10.4. Wa(cid:285)ne narz(cid:218)dzia do testów jednostkowych odziedziczonego kodu 261 10.4.1. (cid:146)atwe izolowanie zale(cid:285)no(cid:258)ci za pomoc(cid:200) frameworków izolacji bez ogranicze(cid:241) 261 10.4.2. Wykorzystanie programu JMockit do pracy z kodem odziedziczonym w Javie 262 10.4.3. Wykorzystanie programu Vise do refaktoryzacji kodu w Javie 264 10.4.4. Przeprowadzenie testów akceptacyjnych przed refaktoryzacj(cid:200) 265 10.4.5. Przeczytaj ksi(cid:200)(cid:285)k(cid:218) Michaela Feathersa na temat pracy z kodem odziedziczonym 266 10.4.6. Wykorzystanie programu NDepend do analizy kodu produkcyjnego 266 10.4.7. Wykorzystanie programu ReSharper do refaktoryzacji i poruszania si(cid:218) po kodzie produkcyjnym 267 10.4.8. Wykrywanie powielonego kodu (oraz b(cid:239)(cid:218)dów) za pomoc(cid:200) narz(cid:218)dzi Simian i TeamCity 267 10.5. Podsumowanie 268 Poleć książkęKup książkę 10 Spis tre(cid:258)ci Rozdzia(cid:239) 11. Projekt a sprawdzalno(cid:258)(cid:202) 269 11.1. Dlaczego nale(cid:285)y dba(cid:202) o sprawdzalno(cid:258)(cid:202) podczas projektowania? 269 11.2. Sprawdzalno(cid:258)(cid:202) jako cel projektowy 270 11.2.1. Domy(cid:258)lne stosowanie metod wirtualnych 271 11.2.2. Projekt bazuj(cid:200)cy na interfejsach 272 11.2.3. Domy(cid:258)lne stosowanie klas niezapiecz(cid:218)towanych 272 11.2.4. Unikanie tworzenia egzemplarzy klas skonkretyzowanych wewn(cid:200)trz metod zawieraj(cid:200)cych logik(cid:218) 272 11.2.5. Unikanie bezpo(cid:258)rednich wywo(cid:239)a(cid:241) do metod statycznych 273 11.2.6. Unikanie konstruktorów lub konstruktorów statycznych zawieraj(cid:200)cych logik(cid:218) 273 11.2.7. Oddzielenie logiki singletona od posiadaczy singletona 274 11.3. Plusy i minusy projektowania z my(cid:258)l(cid:200) o sprawdzalno(cid:258)ci 275 11.3.1. Ilo(cid:258)(cid:202) pracy 276 11.3.2. Z(cid:239)o(cid:285)ono(cid:258)(cid:202) 276 11.3.3. Eksponowanie wra(cid:285)liwych IP 277 11.3.4. Czasami nie mo(cid:285)na 277 11.4. Alternatywy dla projektowania z my(cid:258)l(cid:200) o sprawdzalno(cid:258)ci 277 11.4.1. Dyskusje o projektach i j(cid:218)zyki o dynamicznych typach 277 11.5. Przyk(cid:239)ad projektu trudnego do testowania 279 11.6. Podsumowanie 283 11.7. Dodatkowe materia(cid:239)y 284 Dodatek A. Narz(cid:218)dzia i frameworki 287 A.1. Frameworki izolacji 288 A.2. Frameworki testów 292 A.3. API testów 296 A.4. Kontenery IoC 299 A.5. Testowanie baz danych 302 A.6. Testowanie stron WWW 303 A.7. Testowanie interfejsu u(cid:285)ytkownika (w aplikacjach desktop) 305 A.8. Testowanie aplikacji wielow(cid:200)tkowych 306 A.9. Testy akceptacyjne 306 A.10. Frameworki API w stylu BDD 308 Skorowidz 309 Poleć książkęKup książkę Pierwszy test jednostkowy W tym rozdziale: (cid:81) Przegl(cid:261)d frameworków testów jednostkowych w .NET (cid:81) Piszemy pierwszy test za pomoc(cid:261) frameworka NUnit (cid:81) Korzystanie z atrybutów NUnit (cid:81) Trzy typy wyj(cid:286)cia jednostki pracy Kiedy po raz pierwszy zacz(cid:200)(cid:239)em pisa(cid:202) testy jednostkowe z wykorzystaniem praw- dziwego frameworka do testów jednostkowych, nie by(cid:239)o zbyt obszernej dokumen- tacji, a we frameworkach, z którymi pracowa(cid:239)em, nie by(cid:239)o odpowiednich przyk(cid:239)a- dów (w tamtych czasach kodowa(cid:239)em g(cid:239)ównie z wykorzystaniem j(cid:218)zyków VB 5 i 6). Nauka pos(cid:239)ugiwania si(cid:218) nimi by(cid:239)a wyzwaniem, dlatego zacz(cid:200)(cid:239)em od pisania raczej s(cid:239)abych testów. Na szcz(cid:218)(cid:258)cie czasy si(cid:218) zmieni(cid:239)y. Ten rozdzia(cid:239) pomo(cid:285)e czytelnikom rozpocz(cid:200)(cid:202) pisanie testów, nawet je(cid:258)li nie maj(cid:200) poj(cid:218)cia, od czego zacz(cid:200)(cid:202). Pomo(cid:285)e on znale(cid:283)(cid:202) si(cid:218) na dobrej drodze do pisania rzeczywistych testów jednostkowych za pomoc(cid:200) frameworka NUnit — (cid:258)rodowiska do tworzenia testów jednostkowych w .NET. Jest to mój ulubiony framework do tworzenia testów jednostkowych w .NET, poniewa(cid:285) jest (cid:239)atwy do pos(cid:239)ugiwania si(cid:218), (cid:239)atwy do zapami(cid:218)tania i zawiera mnóstwo doskona(cid:239)ych w(cid:239)asno(cid:258)ci. Istniej(cid:200) inne frameworki dla .NET, w tym takie, które maj(cid:200) wi(cid:218)cej funkcji, ale zaczynam zawsze od frameworka NUnit. Je(cid:258)li jest taka potrzeba, to czasami po- s(cid:239)uguj(cid:218) si(cid:218) innymi frameworkami. Przyjrzymy si(cid:218), jak dzia(cid:239)a (cid:258)rodowisko NUnit, jakiej u(cid:285)ywa sk(cid:239)adni, jak je uruchomi(cid:202) i uzyska(cid:202) informacje o tym, (cid:285)e test si(cid:218) po- wiód(cid:239) b(cid:200)d(cid:283) nie. Aby to osi(cid:200)gn(cid:200)(cid:202), zaprezentuj(cid:218) niewielki projekt oprogramowania, Poleć książkęKup książkę 46 ROZDZIA(cid:224) 2. Pierwszy test jednostkowy którego b(cid:218)dziemy u(cid:285)ywa(cid:202) w ca(cid:239)ej ksi(cid:200)(cid:285)ce do odkrywania technik testowania i naj- lepszych praktyk. Czytelnik mo(cid:285)e odczuwa(cid:202), (cid:285)e zmuszam go do u(cid:285)ywania frameworka NUnit w tej ksi(cid:200)(cid:285)ce. Dlaczego nie u(cid:285)ywa(cid:202) wbudowanego w (cid:258)rodowisku Visual Studio frameworka MSTest? Odpowied(cid:283) sk(cid:239)ada si(cid:218) z dwóch cz(cid:218)(cid:258)ci: (cid:81) NUnit zawiera lepsze funkcje od MSTest w zakresie pisania testów jednostkowych i atrybutów testów. Dzi(cid:218)ki temu mo(cid:285)emy pisa(cid:202) testy bardziej czytelne i (cid:239)atwiejsze w utrzymaniu. (cid:81) W Visual Studio 2012 wbudowany mechanizm uruchamiania testów pozwala na uruchamianie testów napisanych w innych frameworkach, w tym we frameworku NUnit. Aby to umo(cid:285)liwi(cid:202), wystarczy zainstalowa(cid:202) adapter testów NUnit dla Visual Studio — NuGet ((cid:258)rodowisko NuGet omówiono w dalszej cz(cid:218)(cid:258)ci tego rozdzia(cid:239)u). 2.1. To sprawia, (cid:285)e wybór frameworka testów jednostkowych staje si(cid:218) dla mnie stosun- kowo (cid:239)atwy. Po pierwsze, musimy przyjrze(cid:202) si(cid:218) temu, czym jest framework testów jednost- kowych i co pozwala nam zrobi(cid:202), czego nie mogliby(cid:258)my zrobi(cid:202), gdyby(cid:258)my go nie stosowali. Frameworki testów jednostkowych Testy r(cid:218)czne s(cid:200) k(cid:239)opotliwe. Piszemy kod, uruchamiamy go w debugerze, wciska- my w aplikacji wszystkie potrzebne klawisze, aby uruchomi(cid:202) kod, który w(cid:239)a(cid:258)nie napisali(cid:258)my, a nast(cid:218)pnie powtarzamy wszystko to po napisaniu nowego kodu. A do tego musimy pami(cid:218)ta(cid:202), (cid:285)eby sprawdzi(cid:202) pozosta(cid:239)y kod, na który móg(cid:239) mie(cid:202) wp(cid:239)yw nowy kod. To dodatkowa r(cid:218)czna praca. Doskonale. Wykonywanie testów i testowanie regresyjne ca(cid:239)kowicie r(cid:218)cznie, powtarzanie tych samych czynno(cid:258)ci w kó(cid:239)ko jak ma(cid:239)pa jest podatne na b(cid:239)(cid:218)dy i czasoch(cid:239)onne, a ludzie nie lubi(cid:200) tego robi(cid:202) — jest to najbardziej znienawidzona czynno(cid:258)(cid:202) w roz- woju oprogramowania. Problemy te mo(cid:285)na z(cid:239)agodzi(cid:202) dzi(cid:218)ki zastosowaniu odpo- wiednich narz(cid:218)dzi. Frameworki do testów jednostkowych pozwalaj(cid:200) pisa(cid:202) testy szybciej przy u(cid:285)yciu zestawu znanych API, wykonywa(cid:202) testy automatycznie i (cid:239)atwo przegl(cid:200)da(cid:202) wyniki tych testów. A do tego niczego nigdy nie zapominaj(cid:200)! Spróbuj- my przyjrze(cid:202) si(cid:218) bli(cid:285)ej, co mog(cid:200) nam zaoferowa(cid:202). 2.1.1. Co oferuj(cid:261) frameworki testów jednostkowych Do tej pory wielu czytelników tej ksi(cid:200)(cid:285)ki wykonywa(cid:239)o testy o ograniczonych mo(cid:285)- liwo(cid:258)ciach: (cid:81) Nie by(cid:239)y strukturalne. Za ka(cid:285)dym razem, gdy chcieli(cid:258)my przetestowa(cid:202) jak(cid:200)(cid:258) w(cid:239)asno(cid:258)(cid:202), musieli(cid:258)my „odkrywa(cid:202)” ko(cid:239)o na nowo. Jeden test móg(cid:239) wygl(cid:200)da(cid:202) jak aplikacja konsolowa, inny u(cid:285)ywa(cid:239) graficznego interfejsu u(cid:285)ytkownika, a jeszcze Poleć książkęKup książkę 2.1. Frameworki testów jednostkowych 47 inny formularza webowego. Nie mieli(cid:258)my czasu na testowanie, a testy nie spe(cid:239)nia(cid:239)y wymagania „(cid:239)atwe w implementacji”. (cid:81) Nie by(cid:239)y powtarzalne. Ani autor testu, ani cz(cid:239)onkowie jego zespo(cid:239)u nie mogli uruchomi(cid:202) testów, które by(cid:239)y napisane w przesz(cid:239)o(cid:258)ci. To (cid:239)amie zasad(cid:218) „powtarzalno(cid:258)ci” i utrudnia znajdowanie b(cid:239)(cid:218)dów regresji. Dzi(cid:218)ki stosowaniu frameworka mo(cid:285)na (cid:239)atwiej i w zautomatyzowany sposób napisa(cid:202) testy, które s(cid:200) powtarzalne. (cid:81) Nie pokrywa(cid:239)y wszystkich wa(cid:285)nych cz(cid:218)(cid:258)ci kodu. Testy nie sprawdza(cid:239)y wszystkich istotnych cz(cid:218)(cid:258)ci kodu. Oznacza to ca(cid:239)y kod zawieraj(cid:200)cy logik(cid:218), poniewa(cid:285) ka(cid:285)dy taki fragment mo(cid:285)e zawiera(cid:202) potencjalny b(cid:239)(cid:200)d (gettery i settery w(cid:239)a(cid:258)ciwo(cid:258)ci nie licz(cid:200) si(cid:218) jako logika, ale ostatecznie b(cid:218)d(cid:200) u(cid:285)ywane jako cz(cid:218)(cid:258)(cid:202) pewnej jednostki pracy). Gdyby pisanie testów by(cid:239)o (cid:239)atwiejsze, byliby(cid:258)my bardziej sk(cid:239)onni pisa(cid:202) ich wi(cid:218)cej. Dzi(cid:218)ki temu uzyskaliby(cid:258)my lepsze pokrycie. Krótko mówi(cid:200)c: to, czego nam brakowa(cid:239)o, to framework do pisania, uruchamiania i przegl(cid:200)dania testów jednostkowych oraz ich wyników. Na rysunku 2.1 pokazano obszary wytwarzania oprogramowania, na które ma wp(cid:239)yw framework testów jed- nostkowych. Rysunek 2.1. Testy jednostkowe pisze si(cid:266) jako kod korzystaj(cid:261)cy z bibliotek frameworka testów jednostkowych. Nast(cid:266)pnie testy s(cid:261) uruchamiane za pomoc(cid:261) osobnego narz(cid:266)dzia do testów jednostkowych lub z poziomu IDE, a nast(cid:266)pnie przegl(cid:261)dane (w postaci tekstu wyj(cid:286)ciowego, interfejsu IDE lub aplikacji frameworka testowania) przez programist(cid:266) b(cid:261)d(cid:296) zautomatyzowany proces kompilacji Poleć książkęKup książkę 48 ROZDZIA(cid:224) 2. Pierwszy test jednostkowy Frameworki testów jednostkowych s(cid:200) bibliotekami kodu i modu(cid:239)ami, które poma- gaj(cid:200) programistom uruchamia(cid:202) testy jednostkowe dla swojego kodu zgodnie z tym, co przedstawiono w tabeli 2.1. Maj(cid:200) te(cid:285) drug(cid:200) stron(cid:218) — pozwalaj(cid:200) na uruchomie- nie testów w ramach zautomatyzowanej kompilacji. Zagadnienie to opisz(cid:218) w ko- lejnych rozdzia(cid:239)ach. Tabela 2.1. W jaki sposób frameworki testów jednostkowych pomagaj(cid:261) programistom pisa(cid:252) i uruchamia(cid:252) testy i przegl(cid:261)da(cid:252) ich wyniki Praktyka dotycz(cid:261)ca testów jednostkowych (cid:224)atwe pisanie testów w usystematyzowany sposób. Uruchamianie jednego lub wszystkich testów jednostkowych. Przegl(cid:261)d wyników wykonanych testów. W jaki sposób framework pomaga? Framework zapewnia programi(cid:286)cie bibliotek(cid:266) klas zawieraj(cid:261)c(cid:261) nast(cid:266)puj(cid:261)ce elementy: (cid:237) klasy bazowe lub interfejsy do dziedziczenia; (cid:237) atrybuty do umieszczenia w kodzie w celu oznaczenia testów; (cid:237) klasy ASERCJI zawieraj(cid:261)ce specjalne metody asercji, które wywo(cid:225)ujemy w celu weryfikacji kodu. identyfikuje testy w kodzie; Framework dostarcza narz(cid:266)dzia do uruchamiania testów (programu konsolowego lub z interfejsem GUI), które: (cid:237) (cid:237) uruchamia testy automatycznie; (cid:237) pokazuje status w czasie dzia(cid:225)ania; (cid:237) mo(cid:298)e by(cid:252) zautomatyzowane za po(cid:286)rednictwem wiersza polecenia. Narz(cid:266)dzie do uruchamiania testów zazwyczaj dostarcza nast(cid:266)puj(cid:261)ce informacje: (cid:237) ile testów uruchomiono; (cid:237) ile testów nie uruchomi(cid:225)o si(cid:266); (cid:237) ile testów si(cid:266) nie powiod(cid:225)o; (cid:237) które testy si(cid:266) nie powiod(cid:225)y; (cid:237) powody niepowodzenia testów; (cid:237) komunikat ASSERT, który napisali(cid:286)my; (cid:237) miejsce w kodzie, dla którego test si(cid:266) nie powiód(cid:225); (cid:237) je(cid:286)li to mo(cid:298)liwe, pe(cid:225)ny (cid:286)lad stosu wyj(cid:261)tków, które spowodowa(cid:225)y niepowodzenie testu; dzi(cid:266)ki niemu dotrzemy do wywo(cid:225)a(cid:276) metod wewn(cid:261)trz stosu wywo(cid:225)a(cid:276). W chwili pisania tej ksi(cid:200)(cid:285)ki istnia(cid:239)o ponad 150 frameworków testów jednostkowych — praktycznie jeden dla ka(cid:285)dego j(cid:218)zyka programowania b(cid:218)d(cid:200)cego w publicznym u(cid:285)ytku. Obszern(cid:200) list(cid:218) mo(cid:285)na znale(cid:283)(cid:202) pod adresem http://en.wikipedia.org/wiki/ List_of_unit_testing_frameworks. We(cid:283)my pod uwag(cid:218), (cid:285)e dla samego tylko (cid:258)rodo- wiska .NET dost(cid:218)pne s(cid:200) co najmniej trzy ró(cid:285)ne frameworki testów jednostkowych: MS Test (firmy Microsoft), xUnit.NET oraz NUnit. Spo(cid:258)ród nich framework NUnit by(cid:239) w przesz(cid:239)o(cid:258)ci de facto standardem. Obecnie mo(cid:285)na zauwa(cid:285)y(cid:202) rywalizacj(cid:218) po- mi(cid:218)dzy zwolennikami MS Test i NUnit, wyst(cid:218)puj(cid:200)c(cid:200) po prostu dlatego, (cid:285)e (cid:258)rodo- wisko MS Test jest wbudowane w Visual Studio. Jednak(cid:285)e gdybym mia(cid:239) wybór, wy- bra(cid:239)bym NUnit ze wzgl(cid:218)du na niektóre funkcje, o których napisz(cid:218) w dalszej cz(cid:218)(cid:258)ci tego rozdzia(cid:239)u, a tak(cid:285)e w dodatku po(cid:258)wi(cid:218)conym narz(cid:218)dziom i frameworkom. Poleć książkęKup książkę 2.2. Wprowadzenie w tematyk(cid:218) projektu LogAn 49 UWAGA. Korzystanie z frameworka testów jednostkowych nie daje gwaran- cji, (cid:285)e testy, które piszemy, b(cid:218)d(cid:200) czytelne, (cid:239)atwe w utrzymaniu lub wiary- godne albo (cid:285)e obejm(cid:200) ca(cid:239)o(cid:258)(cid:202) logiki, któr(cid:200) chcieliby(cid:258)my przetestowa(cid:202). W roz- dziale 7. oraz w ró(cid:285)nych innych miejscach w tej ksi(cid:200)(cid:285)ce przyjrzymy si(cid:218), jak zapewni(cid:202), aby nasze testy jednostkowe mia(cid:239)y takie w(cid:239)a(cid:258)ciwo(cid:258)ci. 2.1.2. Frameworki xUnit (cid:146)(cid:200)cznie frameworki do testów jednostkowych okre(cid:258)lane s(cid:200) nazw(cid:200) frameworków xUnit, poniewa(cid:285) ich nazwy zazwyczaj zaczynaj(cid:200) si(cid:218) od pierwszych liter j(cid:218)zyka, dla którego zosta(cid:239)y zbudowane. Istnieje framework CppUnit dla j(cid:218)zyka C++, JUnit dla Javy, NUnit dla .NET oraz HUnit dla j(cid:218)zyka Haskell. Nie dla wszystkich z nich przestrzega si(cid:218) tych zasad nazewnictwa, ale przewa(cid:285)nie si(cid:218) to robi. W tej ksi(cid:200)(cid:285)ce b(cid:218)dziemy u(cid:285)ywa(cid:202) NUnit — frameworka testów jednostkowych dla (cid:258)rodowiska .NET, które u(cid:239)atwia pisanie testów, uruchamianie ich i analiz(cid:218) wy- ników. NUnit pocz(cid:200)tkowo pojawi(cid:239) si(cid:218) jako bezpo(cid:258)redni port wszechobecnego JUnit dla Javy. Od tego czasu poczyniono ogromny post(cid:218)p w jego konstrukcji i funkcjo- nalno(cid:258)ci. W efekcie NUnit oddzieli(cid:239) si(cid:218) od swojego rodzica i zacz(cid:200)(cid:239) (cid:285)y(cid:202) w(cid:239)asnym (cid:285)yciem w stale zmieniaj(cid:200)cym si(cid:218) ekosystemie frameworków do testów. Poj(cid:218)cia, które b(cid:218)dziemy omawia(cid:202), powinny by(cid:202) zrozumia(cid:239)e dla programistów Javy i C++. 2.2. Wprowadzenie w tematyk(cid:266) projektu LogAn Projekt, który wykorzystamy do testów w tej ksi(cid:200)(cid:285)ce, pocz(cid:200)tkowo b(cid:218)dzie prosty. B(cid:218)dzie zawiera(cid:239) tylko jedn(cid:200) klas(cid:218). W kolejnych rozdzia(cid:239)ach b(cid:218)dziemy rozszerza(cid:202) ten projekt o nowe klasy i funkcje. Projekt nazwiemy LogAn (skrót od log and notification — dos(cid:239). dzienniki i powiadamianie). Oto scenariusz. Twoja firma ma wiele wewn(cid:218)trznych produktów, których u(cid:285)ywa do monitorowania swoich aplikacji w siedzibie klientów. Wszystkie te produkty za- pisuj(cid:200) pliki dzienników i umieszczaj(cid:200) je w specjalnym katalogu. Pliki dzienników s(cid:200) zapisywane we w(cid:239)asnym formacie opracowanym przez Twoj(cid:200) firm(cid:218). Format ten nie mo(cid:285)e by(cid:202) parsowany za pomoc(cid:200) (cid:285)adnych istniej(cid:200)cych narz(cid:218)dzi zewn(cid:218)trznych. Otrzyma(cid:239)e(cid:258) zadanie stworzenia produktu LogAn, który b(cid:218)dzie analizowa(cid:202) te pliki dziennika w celu wyszukania w nich szczególnych przypadków i zdarze(cid:241). Gdy znaj- dzie takie przypadki i zdarzenia, powinien zawiadomi(cid:202) zainteresowane strony. W tej ksi(cid:200)(cid:285)ce napiszemy testy weryfikuj(cid:200)ce mo(cid:285)liwo(cid:258)ci systemu LogAn w za- kresie parsowania, rozpoznawania zdarze(cid:241) i powiadamiania. Zanim jednak zacznie- my testowanie naszego projektu, przyjrzymy si(cid:218), jak pisze si(cid:218) testy jednostkowe za pomoc(cid:200) frameworka NUnit. W pierwszym kroku nale(cid:285)y go zainstalowa(cid:202). 2.3. Pierwsze kroki z NUnit Tak jak w przypadku ka(cid:285)dego nowego narz(cid:218)dzia najpierw trzeba framework zain- stalowa(cid:202). Poniewa(cid:285) NUnit jest programem typu open source, który mo(cid:285)na pobra(cid:202) za darmo, to zadanie b(cid:218)dzie raczej proste. Nast(cid:218)pnie przyjrzymy si(cid:218), jak zacz(cid:200)(cid:202) Poleć książkęKup książkę 50 ROZDZIA(cid:224) 2. Pierwszy test jednostkowy pisanie testów z wykorzystaniem frameworka NUnit, u(cid:285)ywa(cid:202) ró(cid:285)nych wbudowa- nych atrybutów dostarczanych przez NUnit oraz uruchamia(cid:202) testy i uzyskiwa(cid:202) rze- czywiste wyniki. 2.3.1. Instalacja frameworka NUnit Najlepszym i najprostszym sposobem, aby zainstalowa(cid:202) NUnit, jest skorzystanie z NuGet — darmowego rozszerzenia do Visual Studio, które pozwala na wyszuki- wanie, pobieranie i instalacj(cid:218) referencji do popularnych bibliotek z poziomu Visual Studio za pomoc(cid:200) kilku klikni(cid:218)(cid:202) mysz(cid:200) i prostego tekstu polecenia. Zalecam zainstalowanie rozszerzenia NuGet poprzez przej(cid:258)cie do nast(cid:218)puj(cid:200)- cego menu w Visual Studio: Tools/Extension Manager, klikni(cid:218)cie Online Gallery i zainstalowanie pierwszego na li(cid:258)cie rozszerzenia NuGet Package Manager. Po instalacji nale(cid:285)y zrestartowa(cid:202) Visual Studio i voilà — mamy pot(cid:218)(cid:285)ne i (cid:239)atwe w ob- s(cid:239)udze narz(cid:218)dzie do dodawania referencji i zarz(cid:200)dzania nimi w projektach (progra- mistom, którzy migruj(cid:200) ze (cid:258)rodowiska Ruby, rozszerzenie NuGet mo(cid:285)e przypomi- na(cid:202) narz(cid:218)dzia Ruby Gems i GemFile, cho(cid:202) w dalszym ci(cid:200)gu b(cid:218)dzie ono nowe, je(cid:258)li chodzi o kontrol(cid:218) wersji oraz wdra(cid:285)anie). Po zainstalowaniu rozszerzenia NuGet mo(cid:285)emy otworzy(cid:202) nast(cid:218)puj(cid:200)ce menu: Tools/Library Package Manager/Package Manager Console, a nast(cid:218)pnie w oknie tekstowym, które si(cid:218) wy(cid:258)wietli, wpisa(cid:202) polecenie: Install-Package NUnit (mo(cid:285)na równie(cid:285) skorzysta(cid:202) z klawisza Tab w celu automatycznego uzupe(cid:239)nienia dost(cid:218)p- nych polece(cid:241) oraz nazw pakietów bibliotek). Po wykonaniu tych dzia(cid:239)a(cid:241) powinni(cid:258)my zobaczy(cid:202) przyjemny komunikat Nunit Installed Successfully. Rozszerzenie NuGet pobra(cid:239)o archiwum zip zawieraj(cid:200)ce pliki frameworka NUnit, doda(cid:239)o referencj(cid:218) do domy(cid:258)lnego projektu ustawionego w polu kombi okna konsoli mened(cid:285)era pakietów oraz zako(cid:241)czy(cid:239)o prac(cid:218), wy(cid:258)wietla- j(cid:200)c komunikat informuj(cid:200)cy o tym, (cid:285)e wykona(cid:239)o te wszystkie dzia(cid:239)ania. W naszym projekcie powinni(cid:258)my teraz zobaczy(cid:202) referencj(cid:218) do biblioteki NUnit.Framework.dll. Krótka uwaga na temat interfejsu GUI frameworka NUnit: to podstawowe na- rz(cid:218)dzie uruchamiania testów frameworka NUnit. Narz(cid:218)dzie to omówi(cid:218) w dalszej cz(cid:218)(cid:258)ci tego rozdzia(cid:239)u, ale zazwyczaj go nie u(cid:285)ywam. Powinni(cid:258)my uzna(cid:202) je raczej za narz(cid:218)dzie edukacyjne pozwalaj(cid:200)ce zrozumie(cid:202), jak dzia(cid:239)a NUnit jako osobne na- rz(cid:218)dzie, bez dodatków do Visual Studio. Narz(cid:218)dzie z interfejsem GUI nie jest rów- nie(cid:285) do(cid:239)(cid:200)czone do wersji frameworka NUnit zainstalowanej za pomoc(cid:200) rozszerze- nia NuGet. Rozszerzenie NuGet instaluje tylko potrzebne biblioteki DLL — bez interfejsu u(cid:285)ytkownika (to ma pewien sens, poniewa(cid:285) mo(cid:285)emy mie(cid:202) wiele projektów korzystaj(cid:200)cych z NUnit, ale nie potrzebujemy wielu wersji interfejsu u(cid:285)ytkownika frameworka, (cid:285)eby je uruchomi(cid:202)). Aby pobra(cid:202) interfejs u(cid:285)ytkownika frameworka NUnit, który tak(cid:285)e poka(cid:285)(cid:218) nieco dok(cid:239)adniej w dalszej cz(cid:218)(cid:258)ci tego rozdzia(cid:239)u, mo(cid:285)na zainstalowa(cid:202) pakiet NUnit.Runners za pomoc(cid:200) rozszerzenia NuGet albo mo(cid:285)na odwiedzi(cid:202) witryn(cid:218) Nunit.com i zainstalowa(cid:202) stamt(cid:200)d pe(cid:239)n(cid:200) wersj(cid:218). Ta pe(cid:239)na wer- sja jest tak(cid:285)e wbudowana w pakiet NUnit Console Runner, z którego korzystamy podczas uruchamiania testów na serwerze kompilacji. Poleć książkęKup książkę 2.3. Pierwsze kroki z NUnit 51 Je(cid:258)li kto(cid:258) nie mo(cid:285)e pobra(cid:202) rozszerzenia NuGet b(cid:200)d(cid:283) nie ma do niego dost(cid:218)pu, mo(cid:285)e pobra(cid:202) framework NUnit z witryny www.NUnit.com i r(cid:218)cznie doda(cid:202) do pro- jektu referencje do bibliotek NUnit. Jako bonus mo(cid:285)na wykorzysta(cid:202) fakt, (cid:285)e NUnit jest produktem open source. Mo(cid:285)na zatem pobra(cid:202) kod (cid:283)ród(cid:239)owy NUnit, samodzielnie go skompilowa(cid:202) i swobodnie ko- rzysta(cid:202) z kodu (cid:283)ród(cid:239)owego w ramach licencji open source (ze szczegó(cid:239)ami licencji mo(cid:285)na si(cid:218) zapozna(cid:202) w pliku license.txt w katalogu z programem). UWAGA. Gdy powstawa(cid:239)a ta ksi(cid:200)(cid:285)ka, najnowsz(cid:200) wersj(cid:200) NUnit by(cid:239)a wersja 2.6.0. Przyk(cid:239)ady w tej ksi(cid:200)(cid:285)ce powinny by(cid:202) zgodne z wi(cid:218)kszo(cid:258)ci(cid:200) przysz(cid:239)ych wersji frameworka. Je(cid:258)li wybrali(cid:258)my r(cid:218)czny sposób instalacji NUnit, mo(cid:285)emy uruchomi(cid:202) pobrany pro- gram Setup. Program instalacyjny umie(cid:258)ci skrót do narz(cid:218)dzia z interfejsem GUI na pulpicie, ale g(cid:239)ówne pliki programu powinny by(cid:202) zapisane w katalogu o nazwie C:Program FilesNUnit-Net-2.6.0. Dwukrotne klikni(cid:218)cie ikony NUnit na pulpicie spowoduje uruchomienie narz(cid:218)dzia do wykonywania testów. Zrzut ekranu tego narz(cid:218)dzia pokazano na rysunku 2.2. Rysunek 2.2. Interfejs GUI frameworka NUnit jest podzielony na trzy g(cid:225)ówne cz(cid:266)(cid:286)ci: drzewo wy(cid:286)wietlaj(cid:261)ce testy po lewej stronie, komunikaty i b(cid:225)(cid:266)dy w górnej prawej cz(cid:266)(cid:286)ci oraz informacje (cid:286)ladu stosu w dolnej prawej cz(cid:266)(cid:286)ci 2.3.2. (cid:224)adowanie rozwi(cid:261)zania Je(cid:258)li pobra(cid:239)e(cid:258) kod (cid:283)ród(cid:239)owy przyk(cid:239)adów tej ksi(cid:200)(cid:285)ki, za(cid:239)aduj w (cid:258)rodowisku Visual Studio 2010 lub nowszym rozwi(cid:200)zanie ArtOfUnitTesting2ndEd.Samples.sln znaj- duj(cid:200)ce si(cid:218) w folderze Code. Poleć książkęKup książkę 52 ROZDZIA(cid:224) 2. Pierwszy test jednostkowy UWAGA. Do uruchamiania przyk(cid:239)adów zamieszczonych w tej ksi(cid:200)(cid:285)ce mo(cid:285)na korzysta(cid:202) z wersji Microsoft Visual C# 2010 Express (lub wersji nowszej). Zaczniemy od przetestowania poni(cid:285)szej prostej klasy z jedn(cid:200) metod(cid:200) (jednostk(cid:200), któr(cid:200) testujemy): public class LogAnalyzer { public bool IsValidLogFileName(string fileName) { if(fileName.EndsWith( .SLF )) { return false; } return true; } } Zwró(cid:202)my uwag(cid:218), (cid:285)e celowo pomin(cid:200)(cid:239)em znak ! przed warunkiem instrukcji if. Z tego powodu metoda ta ma b(cid:239)(cid:200)d — zwraca false zamiast true, gdy plik ma roz- szerzenie SLF. Zrobi(cid:239)em to po to, aby(cid:258)my mogli zobaczy(cid:202), jak w programie do uru- chamiania testów wygl(cid:200)da sytuacja, gdy test si(cid:218) nie powiedzie. Powy(cid:285)sza metoda nie wydaje si(cid:218) skomplikowana; przetestujemy j(cid:200), aby upewni(cid:202) si(cid:218), (cid:285)e dzia(cid:239)a, ale g(cid:239)ównie po to, by prze(cid:258)ledzi(cid:202) procedur(cid:218) testowania. W rzeczy- wistym (cid:258)wiecie powinni(cid:258)my przetestowa(cid:202) wszystkie metody, które zawieraj(cid:200) logi- k(cid:218) — nawet je(cid:258)li wydaje si(cid:218) ona by(cid:202) prosta. Logika mo(cid:285)e si(cid:218) nie powie(cid:258)(cid:202). Chcemy wiedzie(cid:202), kiedy tak si(cid:218) stanie. W kolejnych rozdzia(cid:239)ach b(cid:218)dziemy testowa(cid:202) bardziej skomplikowane scenariusze i logiki. Metoda sprawdza rozszerzenie pliku, aby ustali(cid:202), czy plik jest poprawnym pli- kiem dziennika, czy nie. Nasz pierwszy test b(cid:218)dzie polega(cid:239) na wys(cid:239)aniu prawid(cid:239)o- wej nazwy pliku i sprawdzeniu, czy metoda zwraca true. Oto pierwsze kroki potrzebne do napisania automatycznego testu dla metody IsValidLogFileName: 1. Dodaj nowy projekt biblioteki klas do rozwi(cid:200)zania. B(cid:218)dzie ona zawiera(cid:202) nasze klasy testowe. Nadaj mu nazw(cid:218) LogAn.UnitTests (przy za(cid:239)o(cid:285)eniu, (cid:285)e testowany projekt ma nazw(cid:218) LogAn.csproj). 2. Do tej biblioteki dodaj now(cid:200) klas(cid:218), która b(cid:218)dzie zawiera(cid:239)a metody testowe. Nazwij j(cid:200) LogAnalyzerTests (zak(cid:239)adaj(cid:200)c, (cid:285)e testowana klasa ma nazw(cid:218) LogAnalyzer). 3. Dodaj now(cid:200) metod(cid:218) do powy(cid:285)szego przypadku testowego o nazwie IsValidLogFileName_BadExtension_ReturnsFalse(). Wi(cid:218)cej informacji na temat standardów nazewnictwa i uk(cid:239)adu testów podamy w dal- szej cz(cid:218)(cid:258)ci tej ksi(cid:200)(cid:285)ki. Podstawowe zasady wymieniono w tabeli 2.2. Na przyk(cid:239)ad dla naszego projektu LogAn projekt testowy b(cid:218)dzie mia(cid:239) nazw(cid:218) LogAn.UnitTests. Klasa testowa dla klasy LogAnalyzer b(cid:218)dzie nosi(cid:239)a nazw(cid:218) LogAna- lyzerTests. Poleć książkęKup książkę 2.3. Pierwsze kroki z NUnit 53 Tabela 2.2. Podstawowe regu(cid:225)y umieszczania testów i nadawania im nazw Obiekt do przetestowania Projekt Klasa Jednostka pracy (metoda lub logiczna grupa kilku metod albo kilku klas) Obiekt do stworzenia po stronie testuj(cid:261)cej Utwórz projekt testu o nazwie [Testowany_ projekt].UnitTests. Dla klasy b(cid:266)d(cid:261)cej cz(cid:266)(cid:286)ci(cid:261) projektu Testowany_projekt stwórz klas(cid:266) o nazwie [NazwaKlasy]Tests. Dla ka(cid:298)dej jednostki pracy stwórz metod(cid:266) testu o nast(cid:266)puj(cid:261)cej nazwie: [NazwaJednostkiPracy]_[TestowanyScenariusz]_[OczekiwaneZachowanie]. Nazwa jednostki pracy powinna odpowiada(cid:252) nazwie metody (je(cid:286)li to jest ca(cid:225)a jednostka pracy) lub by(cid:252) bardziej abstrakcyjna, je(cid:286)li jest to przypadek u(cid:298)ycia obejmuj(cid:261)cy wiele metod lub klas, na przyk(cid:225)ad LogowanieU(cid:285)ytkownika lub Usu(cid:241)U(cid:285)ytkownika albo Inicjalizacja. Bardziej komfortowe mo(cid:298)e by(cid:252) zacz(cid:266)cie od nazwy metody i przej(cid:286)cie pó(cid:296)niej na nazwy bardziej abstrakcyjne. Je(cid:286)li s(cid:261) to nazwy metod, upewnij si(cid:266), (cid:298)e s(cid:261) to nazwy publiczne oraz (cid:298)e nie reprezentuj(cid:261) pocz(cid:261)tku jednostki pracy. Oto trzy cz(cid:218)(cid:258)ci nazwy metody testowej: (cid:81) NazwaJednostkiPracy — nazwa metody, grupy metod b(cid:200)d(cid:283) klas, które testujemy. (cid:81) Scenariusz — warunki, w jakich jednostka jest testowana, na przyk(cid:239)ad „z(cid:239)y login”, „nieprawid(cid:239)owy u(cid:285)ytkownik” albo „dobre has(cid:239)o”. Na przyk(cid:239)ad mo(cid:285)emy opisa(cid:202) parametry wysy(cid:239)ane do metody publicznej albo pocz(cid:200)tkowy stan systemu, gdy jest wywo(cid:239)ywana jednostka pracy, na przyk(cid:239)ad „brak pami(cid:218)ci w systemie”, „brak u(cid:285)ytkowników” lub „u(cid:285)ytkownik ju(cid:285) istnieje”. (cid:81) OczekiwaneZachowanie — jakiego dzia(cid:239)ania oczekujemy od testowanej metody w okre(cid:258)lonych warunkach. Mo(cid:285)e to by(cid:202) jedna z trzech mo(cid:285)liwo(cid:258)ci: wynik jako zwracana warto(cid:258)(cid:202) (rzeczywista warto(cid:258)(cid:202) lub wyj(cid:200)tek), wynik jako zmiana stanu systemu (na przyk(cid:239)ad dodanie nowego u(cid:285)ytkownika do systemu, dzi(cid:218)ki czemu system b(cid:218)dzie si(cid:218) zachowywa(cid:239) inaczej przy nast(cid:218)pnym logowaniu) lub wynik w postaci wywo(cid:239)ania systemu zewn(cid:218)trznego (na przyk(cid:239)ad zewn(cid:218)trznej us(cid:239)ugi sieciowej). W naszym te(cid:258)cie metody IsValidLogFileName scenariusz polega na tym, (cid:285)e wysy- (cid:239)amy do metody prawid(cid:239)ow(cid:200) nazw(cid:218) pliku, a oczekiwanym dzia(cid:239)aniem jest zwró- cenie przez metod(cid:218) warto(cid:258)ci true. Metodzie testu mo(cid:285)emy zatem nada(cid:202) nazw(cid:218) IsValidFileName_BadExtension_ReturnsFalse(). Czy testy powinni(cid:258)my pisa(cid:202) w projekcie kodu produkcyjnego? A mo(cid:285)e powin- ni(cid:258)my je wydzieli(cid:202) do innego projektu — specjalnie stworzonego dla testów? Za- zwyczaj wol(cid:218) oddzieli(cid:202) projekt testowy od kodu produkcyjnego, poniewa(cid:285) to spra- wia, (cid:285)e reszta prac zwi(cid:200)zanych z testowaniem staje si(cid:218) (cid:239)atwiejsza. Ponadto wiele osób nie chce do(cid:239)(cid:200)cza(cid:202) testów do kodu produkcyjnego, co prowadzi do ró(cid:285)nych brzydkich schematów kompilacji warunkowej lub innych z(cid:239)ych pomys(cid:239)ów, które powoduj(cid:200), (cid:285)e kod staje si(cid:218) mniej czytelny. Z drugiej strony, nie mam pod tym wzgl(cid:218)dem bardzo (cid:258)cis(cid:239)ych wymaga(cid:241). Po- doba mi si(cid:218) równie(cid:285) pomys(cid:239) wykorzystywania testów obok dzia(cid:239)aj(cid:200)cej aplikacji Poleć książkęKup książkę 54 ROZDZIA(cid:224) 2. Pierwszy test jednostkowy produkcyjnej, aby mo(cid:285)na by(cid:239)o testowa(cid:202) jej prawid(cid:239)owe dzia(cid:239)anie ju(cid:285) po zainsta- lowaniu. To wymaga uwa(cid:285)nych przemy(cid:258)le(cid:241), ale nie jest konieczne, aby testy i kod produkcyjny wyst(cid:218)powa(cid:239)y w tym samym projekcie. Mo(cid:285)emy mie(cid:202) ciastko i jedno- cze(cid:258)nie mo(cid:285)emy je zje(cid:258)(cid:202). Jeszcze nie u(cid:285)ywali(cid:258)my frameworka NUnit, ale ju(cid:285) jeste(cid:258)my blisko. Musimy jeszcze doda(cid:202) referencj(cid:218) do projektu testuj(cid:200)cego w projekcie testowanym. Aby to zrobi(cid:202), nale(cid:285)y klikn(cid:200)(cid:202) prawym przyciskiem myszy w projekcie testowanym i wy- bra(cid:202) polecenie Add Reference. Nast(cid:218)pnie nale(cid:285)y wybra(cid:202) zak(cid:239)adk(cid:218) Projects, po czym wybra(cid:202) projekt LogAn. Nast(cid:218)pn(cid:200) rzecz(cid:200), jakiej powinni(cid:258)my si(cid:218) nauczy(cid:202), jest sposób oznaczenia meto- dy, która ma by(cid:202) za(cid:239)adowana i uruchomiona przez framework NUnit automatycz- nie. Najpierw powinni(cid:258)my si(cid:218) upewni(cid:202), czy zosta(cid:239)a dodana referencja do frame- worka NUnit albo za pomoc(cid:200) rozszerzenia NuGet, albo r(cid:218)cznie, zgodnie z opisem w punkcie 2.3.1. 2.3.3. Wykorzystanie atrybutów NUnit w kodzie Framework NUnit korzysta z systemu atrybutów w celu rozpoznawania i (cid:239)adowa- nia testów. Podobnie jak zak(cid:239)adki w ksi(cid:200)(cid:285)ce, te atrybuty pomagaj(cid:200) frameworkowi zidentyfikowa(cid:202) wa(cid:285)ne cz(cid:218)(cid:258)ci w zestawie, który go (cid:239)aduje, oraz cz(cid:218)(cid:258)ci b(cid:218)d(cid:200)ce te- stami do wywo(cid:239)ania. Framework NUnit dysponuje zestawem, który zawiera te specjalne atrybuty. Wystarczy tylko doda(cid:202) referencj(cid:218) do projektu testowego (nie w kodzie produkcyj- nym!) do zestawu NUnit.Framework. Mo(cid:285)na go znale(cid:283)(cid:202) w zak(cid:239)adce .NET w oknie dialogowym Add Reference (nie trzeba tego robi(cid:202), je(cid:258)li u(cid:285)yli(cid:258)my rozszerzenia Nu- Get do zainstalowania frameworka NUnit). Je(cid:258)li wpiszemy NUnit, wy(cid:258)wietli si(cid:218) kilka zestawów o nazwie zaczynaj(cid:200)cej si(cid:218) od tej cz(cid:218)(cid:258)ci. Nale(cid:285)y doda(cid:202) nunit.framework.dll jako referencj(cid:218) do projektu testowego (je(cid:258)li zainstalowali(cid:258)my framework r(cid:218)cznie, a nie za po(cid:258)rednictwem rozszerzenia NuGet). Narz(cid:218)dzie do uruchamiania testów NUnit potrzebuje co najmniej dwóch atry- butów do tego, aby wiedzie(cid:202), co nale(cid:285)y uruchomi(cid:202): (cid:81) [TestFixture] — atrybut [TestFixture] oznacza klas(cid:218), która zawiera zautomatyzowane testy NUnit (gdyby(cid:258)my zast(cid:200)pili s(cid:239)owo „Fixture” s(cid:239)owem „Class”, atrybut ten mia(cid:239)by znacznie wi(cid:218)cej sensu. Ale taka zamiana jest dobra tylko jako (cid:202)wiczenie wykonywane w celu zapami(cid:218)tania znaczenia atrybutu. Gdyby(cid:258)my dos(cid:239)ownie zmienili atrybut w ten sposób, kod si(cid:218) nie skompiluje). Atrybut [TestFixture] nale(cid:285)y umie(cid:258)ci(cid:202) na pocz(cid:200)tku nowej klasy LogAnalyzerTests. (cid:81) [Test] — atrybut [Test] mo(cid:285)na umie(cid:258)ci(cid:202) w metodzie w celu oznaczenia jej jako zautomatyzowanego testu do wywo(cid:239)ania. Ten atrybut nale(cid:285)y umie(cid:258)ci(cid:202) w nowej metodzie testowej. Po zako(cid:241)czeniu pracy kod testu powinien wygl(cid:200)da(cid:202) nast(cid:218)puj(cid:200)co: Poleć książkęKup książkę 2.4. Piszemy pierwszy test 55 [TestFixture] public class LogAnalyzerTests { [Test] public void IsValidFileName_BadExtension_ReturnsFalse() { } } WSKAZÓWKA. Framework NUnit w najbardziej podstawowej konfigura- cji wymaga, aby metody testów by(cid:239)y publiczne, zwraca(cid:239)y void i nie przyj- mowa(cid:239)y (cid:285)adnych parametrów, ale jak si(cid:218) przekonamy, czasami testy mog(cid:200) równie(cid:285) pobiera(cid:202) parametry! W tym momencie oznaczyli(cid:258)my klas(cid:218) i metod(cid:218) do uruchomienia. Teraz framework NUnit wywo(cid:239)a ka(cid:285)dy kod, który umie(cid:258)cimy wewn(cid:200)trz metody testowej, kiedy tyl- ko tego za(cid:285)(cid:200)damy. 2.4. Piszemy pierwszy test W jaki sposób testujemy kod? Test jednostkowy zazwyczaj obejmuje trzy g(cid:239)ówne dzia(cid:239)ania: 1. Konfiguracj(cid:218) obiektów — utworzenie ich i ustawienie wed(cid:239)ug potrzeb. 2. Wykonanie operacji na obiektach. 3. Asercj(cid:218) oczekiwanego rezultatu. Oto prosty fragment kodu, który wykonuje te wszystkie trzy dzia(cid:239)ania. Za asercj(cid:218) jest odpowiedzialna klasa Assert frameworka NUnit: [Test] public void IsValidFileName_BadExtension_ReturnsFalse() { LogAnalyzer analyzer = new LogAnalyzer(); bool result = analyzer.IsValidLogFileName( plikoz(cid:239)ymrozszerzeniu.foo ); Assert.False(result); } Zanim przejdziemy dalej, nale(cid:285)y napisa(cid:202) troch(cid:218) wi(cid:218)cej o klasie Assert, poniewa(cid:285) spe(cid:239)nia ona wa(cid:285)n(cid:200) rol(cid:218) podczas pisania testów jednostkowych. 2.4.1. Klasa Assert Klasa Assert zawiera metody statyczne i znajduje si(cid:218) w przestrzeni nazw NUnit.Fra- mework. Jest mostem pomi(cid:218)dzy testowanym kodem a frameworkiem NUnit, a jej celem jest deklaracja, (cid:285)e okre(cid:258)lone za(cid:239)o(cid:285)enie jest prawdziwe. Je(cid:258)li oka(cid:285)e si(cid:218), (cid:285)e argumenty przekazane do klasy Assert b(cid:218)d(cid:200) inne ni(cid:285) za(cid:239)o(cid:285)one, framework NUnit rozpozna, (cid:285)e test si(cid:218) nie powiód(cid:239), i powiadomi nas o tym. Opcjonalnie mo(cid:285)na Poleć książkęKup książkę 56 ROZDZIA(cid:224) 2. Pierwszy test jednostkowy poinformowa(cid:202) klas(cid:218) Assert, jaki komunikat ostrzegawczy powinien si(cid:218) wy(cid:258)wietli(cid:202), je(cid:258)li asercja si(cid:218) nie powiedzie. Klasa Assert zawiera wiele metod. Najwa(cid:285)niejsza z nich to Assert.True(jakie(cid:258)_ wyra(cid:285)enie_logiczne), która sprawdza warunek Boolean. Ale istnieje wiele innych metod, które mo(cid:285)na uzna(cid:202) za cukier sk(cid:239)adniowy, a które sprawiaj(cid:200), (cid:285)e asercje pew- nych elementów staj(cid:200) si(cid:218) bardziej czytelne (jedn(cid:200) z nich jest metoda Assert.False, której u(cid:285)yli(cid:258)my). Oto metoda, która sprawdza, czy oczekiwany obiekt b(cid:200)d(cid:283) warto(cid:258)(cid:202) jest taka sa- ma jak warto(cid:258)(cid:202) rzeczywista: Assert.AreEqual(oczekiwany_obiekt, rzeczywisty_obiekt, komunikat); Oto przyk(cid:239)ad: Assert.AreEqual(2, 1+1, Nieprawid(cid:239)owe dzia(cid:239)anie arytmetyczne ); Poni(cid:285)sza metoda sprawdza, czy dwa argumenty odwo(cid:239)uj(cid:200) si(cid:218) do tego samego obiektu: Assert.AreSame(oczekiwany_obiekt, rzeczywisty_obiekt, komunikat); Oto przyk(cid:239)ad: Assert.AreSame(int.Parse( 1 ),int.Parse( 1 ), ten test nie powinien si(cid:218) powie(cid:258)(cid:202) ). Klasa Assert jest prosta do nauki, pos(cid:239)ugiwania si(cid:218) i zapami(cid:218)tania. Nale(cid:285)y równie(cid:285) zwróci(cid:202) uwag(cid:218), (cid:285)e wszystkie metody klasy Assert przyjmuj(cid:200) ostatni parametr typu string, który zostanie wy(cid:258)wietlony obok wyj(cid:258)cia generowa- nego przez framework w przypadku, gdy test si(cid:218) nie powiedzie. Nigdy nie nale(cid:285)y u(cid:285)ywa(cid:202) tego parametru (jego u(cid:285)ycie zawsze jest opcjonalne). Nale(cid:285)y zadba(cid:202) o to, by nazwa testu wyja(cid:258)nia(cid:239)a, co ma si(cid:218) zdarzy(cid:202). Cz(cid:218)sto programi(cid:258)ci pisz(cid:200) trywialnie oczywiste rzeczy typu „test nie powiód(cid:239) si(cid:218)” lub „oczekiwano x zamiast y”, co fra- mework sam dostarcza. Podobnie jak w przypadku komentarzy w kodzie (cid:127) je(cid:258)li ju(cid:285) musimy u(cid:285)ywa(cid:202) tego parametru, to nazwa metody powinna by(cid:202) czytelniejsza. Po omówieniu podstaw interfejsu API spróbujmy uruchomi(cid:202) test. 2.4.2. Uruchomienie pierwszego testu za pomoc(cid:261) frameworka NUnit Nadszed(cid:239) czas, aby uruchomi(cid:202) pierwszy test i sprawdzi(cid:202), czy powiedzie si(cid:218), czy nie. Istniej(cid:200) co najmniej cztery ró(cid:285)ne sposoby uruchomienia testu: (cid:81) Za pomoc(cid:200) interfejsu GUI frameworka NUnit. (cid:81) Za pomoc(cid:200) narz(cid:218)dzia do uruchamiania testów (cid:258)rodowiska Visual Studio 2012 z zainstalowanym rozszerzeniem do uruchamiania testów NUnit (w galerii NuGet wyst(cid:218)puje ono pod nazw(cid:200) NUnit Test Adapter). (cid:81) Za pomoc(cid:200) narz(cid:218)dzia do uruchamiania testów programu ReSharper (dobrze znanej komercyjnej wtyczki do (cid:258)rodowiska VS). (cid:81) Za pomoc(cid:200) narz(cid:218)dzia TestDriven.NET (innej znanej wtyczki do (cid:258)rodowiska VS). Poleć książkęKup książkę 2.4. Piszemy pierwszy test 57 Chocia(cid:285) w tej ksi(cid:200)(cid:285)ce opisano tylko interfejs GUI frameworka NUnit, osobi(cid:258)cie korzystam z narz(cid:218)dzia NCrunch, które jest szybkie, dzia(cid:239)a automatycznie, ale trze- ba za nie zap(cid:239)aci(cid:202) (to narz(cid:218)dzie razem z innymi opisano w dodatku po(cid:258)wi(cid:218)conym narz(cid:218)dziom). NCrunch dostarcza prostych, szybkich informacji wewn(cid:200)trz okna edytora w (cid:258)rodowisku Visual Studio. Uwa(cid:285)am, (cid:285)e to narz(cid:218)dzie do uruchamiania testów tworzy idealn(cid:200) par(cid:218) z technikami TDD. Wi(cid:218)cej informacji na jego temat mo(cid:285)na znale(cid:283)(cid:202) pod adresem http://www.ncrunch.net/. Aby uruchomi(cid:202) test za pomoc(cid:200) interfejsu GUI frameworka NUnit, trzeba mie(cid:202) skompilowany zestaw (w tym przypadku plik .dll), który mo(cid:285)na przekaza(cid:202) frame- workowi NUnit do sprawdzenia. Po skompilowaniu projektu nale(cid:285)y znale(cid:283)(cid:202) (cid:258)cie(cid:285)k(cid:218) do pliku zestawu, który powsta(cid:239) po kompilacji. Nast(cid:218)pnie nale(cid:285)y za(cid:239)adowa(cid:202) GUI frameworka NUnit (je(cid:258)li zainstalowali(cid:258)my framework NUnit r(cid:218)cznie, wystarczy znale(cid:283)(cid:202) ikon(cid:218) na pulpicie. Je(cid:258)li zainstalowa- li(cid:258)my (cid:258)rodowisko NUnit.Runners za pomoc(cid:200) rozszerzenia NuGet, nale(cid:285)y odszuka(cid:202) plik wykonywalny (cid:258)rodowiska GUI frameworka NUnit w folderze packages w g(cid:239)ów- nym folderze rozwi(cid:200)zania, a nast(cid:218)pnie wybra(cid:202) polecenie File/Open. Nast(cid:218)pnie wprowadzamy nazw(cid:218) zestawu do testowania. Po lewej stronie okna wy(cid:258)wietli si(cid:218) pojedynczy test oraz hierarchia klas i przestrzeni nazw projektu (rysunek 2.3). Aby uruchomi(cid:202) testy, nale(cid:285)y klikn(cid:200)(cid:202) przycisk Run. Testy s(cid:200) automatycznie pogrupo- wane wed(cid:239)ug nazw (nazwy zestawu, typu), wi(cid:218)c mo(cid:285)na wybra(cid:202) i uruchomi(cid:202) tylko okre(cid:258)lone typy b(cid:200)d(cid:283) przestrzenie nazw (zwykle uruchamiamy wszystkie testy, aby uzyska(cid:202) pe(cid:239)niejsze informacje na temat awarii). Rysunek 2.3. Niepowodzenie testów NUnit mo(cid:298)na zaobserwowa(cid:252) w trzech miejscach: hierarchia testów po lewej stronie i pasek post(cid:266)pu u góry maj(cid:261) czerwony kolor, a po prawej stronie wy(cid:286)wietlaj(cid:261) si(cid:266) komunikaty o b(cid:225)(cid:266)dach Jak mo(cid:285)na zobaczy(cid:202), test nie wychodzi, co mo(cid:285)e sugerowa(cid:202), (cid:285)e jest b(cid:239)(cid:200)d w kodzie. Nadszed(cid:239) czas, (cid:285)eby naprawi(cid:202) kod i przekona(cid:202) si(cid:218), (cid:285)e test wyjdzie. Modyfikujemy kod poprzez dodanie brakuj(cid:200)cego znaku ! w instrukcji if, tak aby przyj(cid:218)(cid:239)a nast(cid:218)- puj(cid:200)c(cid:200) posta(cid:202): if(!fileName.EndsWith( .SLF )) { return false; } Poleć książkęKup książkę 58 ROZDZIA(cid:224) 2. Pierwszy test jednostkowy 2.4.3. Dodanie testów pozytywnych Pokazali(cid:258)my, (cid:285)e z(cid:239)e rozszerzenia spowoduj(cid:200) takie oznaczenia, ale kto powiedzia(cid:239), (cid:285)e dobre rozszerzenie zostanie „zatwierdzone” przez nasz(cid:200) niewielk(cid:200) metod(cid:218)? Gdyby(cid:258)my stosowali technik(cid:218) TDD, brakuj(cid:200)ce testy by(cid:239)yby oczywiste, ale ponie- wa(cid:285) piszemy testy po kodzie, musimy wymy(cid:258)li(cid:202) dobre przypadki testowe, które pokryj(cid:200) wszystkie (cid:258)cie(cid:285)ki. Na listingu 2.1 dodano kilka nowych testów, aby zoba- czy(cid:202), co si(cid:218) b(cid:218)dzie dzia(cid:239)o, gdy przeka(cid:285)emy plik z dobrym rozszerzeniem. Jeden z testów sprawdza rozszerzenie z(cid:239)o(cid:285)one z wielkich liter, natomiast drugi z ma(cid:239)ych. Listing 2.1. Logika walidacji nazw plików programu LogAnalyzer, któr(cid:261) chcemy przetestowa(cid:252) [Test] public void IsValidLogFileName_GoodExtensionLowercase_ReturnsTrue() { LogAnalyzer analyzer = new LogAnalyzer(); bool result = analyzer .IsValidLogFileName( filewithgoodextension.slf ); Assert.True(result); } [Test]public void IsValidLogFileName_GoodExtensionUppercase_ReturnsTrue() { LogAnalyzer analyzer = new LogAnalyzer(); bool result = analyzer .IsValidLogFileName( filewithgoodextension.SLF ); Assert.True(result); } Je(cid:258)li teraz skompilujemy rozwi(cid:200)zanie, zauwa(cid:285)ymy, (cid:285)e (cid:258)rodowisko GUI frameworka NUnit potrafi wykry(cid:202), (cid:285)e zestaw si(cid:218) zmieni(cid:239), i automatycznie ponownie za(cid:239)aduje zestaw w GUI. Kiedy ponownie uruchomimy testy, zauwa(cid:285)ymy, (cid:285)e test z rozsze- rzeniem z(cid:239)o(cid:285)onym z ma(cid:239)ych liter nie wychodzi. Aby test wyszed(cid:239), musimy zmo- dyfikowa(cid:202) kod produkcyjny — zastosowa(cid:202) dopasowywanie ci(cid:200)gów bez rozró(cid:285)nia- nia wielko(cid:258)ci liter: public bool IsValidLogFileName(string fileName) { if (!fileName.EndsWith( .SLF , StringComparison.CurrentCultureIgnoreCase)) { return false; } return true; } Je(cid:258)li ponownie uruchomimy testy, wszystkie powinny wyj(cid:258)(cid:202). W (cid:258)rodowisku GUI frameworka NUnit powinien ponownie wy(cid:258)wietli(cid:202) si(cid:218) pi(cid:218)kny zielony pasek. Poleć książkęKup książkę 2.5. Refaktoryzacja w kierunku testów z parametrami 59 2.4.4. Od czerwonego do zielonego: d(cid:261)(cid:298)enie do spe(cid:225)nienia testów (cid:165)rodowisko GUI frameworka NUnit zosta(cid:239)o zbudowane zgodnie z prost(cid:200) zasad(cid:200): aby uzyska(cid:202) „zielone” (cid:258)wiat(cid:239)o pozwalaj(cid:200)ce przej(cid:258)(cid:202) dalej, wszystkie testy musz(cid:200) by(cid:202) spe(cid:239)nione. Je(cid:258)li chocia(cid:285) jeden z testów nie powiedzie si(cid:218), zobaczymy czerwo- ne (cid:258)wiat(cid:239)o na górnym pasku post(cid:218)pu. Informuje nas ono, (cid:285)e co(cid:258) niedobrego dzieje si(cid:218) z systemem (lub z testami). Zasada przechodzenia od czerwonego do zielonego jest powszechna w ca(cid:239)ym (cid:258)wiecie testów jednostkowych, a zw(cid:239)aszcza w metodyce wytwarzania oprogramo- wania bazuj(cid:200)cej na testach (TDD). Jej mantra to czerwone-zielone-refaktoryzacja, co oznacza, (cid:285)e zaczynamy od testu, który nie wychodzi, nast(cid:218)pnie d(cid:200)(cid:285)ymy do jego spe(cid:239)nienia, a w dalszej kolejno(cid:258)ci staramy si(cid:218), by kod sta(cid:239) si(cid:218) bardziej czytelny i (cid:239)a- twiejszy w utrzymaniu. Testy mog(cid:200) równie(cid:285) nie powie(cid:258)(cid:202) si(cid:218), je(cid:258)li nagle zostanie zg(cid:239)oszony nieoczeki- wany wyj(cid:200)tek. Test, który zatrzyma si(cid:218) z powodu nieoczekiwanego wyj(cid:200)tku, jest uznawany za nieudany w wi(cid:218)kszo(cid:258)ci (je(cid:258)li nie we wszystkich) frameworków testo- wych. Jest to cz(cid:218)(cid:258)(cid:202) podej(cid:258)cia — czasami w programie s(cid:200) b(cid:239)(cid:218)dy w postaci wyj(cid:200)t- ków, których si(cid:218) nie spodziewali(cid:258)my. Je(cid:258)li chodzi o wyj(cid:200)tki, w dalszej cz(cid:218)(cid:258)ci tego rozdzia(cid:239)u poka(cid:285)emy rodzaj testu, który jako specyficznego wyniku lub zachowania oczekuje zg(cid:239)oszenia wyj(cid:200)tku z okre(cid:258)lo- nego kodu. Tego rodzaju test nie wychodzi, je(cid:258)li wyj(cid:200)tek nie zostanie zg(cid:239)oszony. 2.4.5. Styl kodu testów Zwró(cid:202)my uwag(cid:218), (cid:285)e testy, które napisa(cid:239)em, maj(cid:200) kilka cech dotycz(cid:200)cych stylu i czy- telno(cid:258)ci, które wyró(cid:285)niaj(cid:200) kod testów od „standardowego” kodu. Nazwy testów mog(cid:200) by(cid:202) bardzo d(cid:239)ugie, ale znaki podkre(cid:258)lenia pomagaj(cid:200) zadba(cid:202) o to, aby(cid:258)my nie zapomnieli umie(cid:258)ci(cid:202) wszystkich wa(cid:285)nych informacji. Dodatkowo w ka(cid:285)dym te(cid:258)cie umie(cid:258)ci(cid:239)em pusty wiersz pomi(cid:218)dzy etapami konfiguracji, dzia(cid:239)ania i asercji. Uwa- (cid:285)am, (cid:285)e to pomaga mi znacznie szybciej czyta(cid:202) testy i u(cid:239)atwia znajdowanie w nich problemów. Stara(cid:239)em si(cid:218) równie(cid:285) jak najbardziej oddzieli(cid:202) kod asercji od kodu dzia(cid:239)ania. Preferuj(cid:218) asercj(cid:218) na warto(cid:258)ci, a nie bezpo(cid:258)rednio na wywo(cid:239)aniu funkcji. Dzi(cid:218)ki temu kod staje si(cid:218) znacznie bardziej czytelny. Czytelno(cid:258)(cid:202) jest jednym z najwa(cid:285)niejszych aspektów pisania testu. Test powinien czyta(cid:202) bez wysi(cid:239)ku nawet kto(cid:258), kto nigdy nie widzia(cid:239) testu wcze(cid:258)niej, bez potrzeby zadawania zbyt wielu pyta(cid:241), lub w ogóle (cid:285)adnych pyta(cid:241). Wi(cid:218)cej na ten temat na- pisz(cid:218) w rozdziale 7. Teraz zobaczmy, czy mo(cid:285)emy wyeliminowa(cid:202) troch(cid:218) powtórze(cid:241) i poprawi(cid:202) spójno(cid:258)(cid:202) testów bez szkody dla ich czytelno(cid:258)ci. 2.5. Refaktoryzacja w kierunku testów z parametrami Wszystkie testy, które napisali(cid:258)my do tej pory, maj(cid:200) pewien problem zwi(cid:200)zany z (cid:239)a- two(cid:258)ci(cid:200) utrzymania. Wyobra(cid:283)my sobie, (cid:285)e teraz chcemy doda(cid:202) parametr do kon- struktora klasy LogAnalyzer. B(cid:218)dziemy wi(cid:218)c mieli trzy testy, które si(cid:218) nie skompiluj(cid:200). Poleć książkęKup książkę 60 ROZDZIA(cid:224) 2. Pierwszy test jednostkowy Poprawienie trzech testów mo(cid:285)e nie jest trudne, ale z (cid:239)atwo(cid:258)ci(cid:200) w systemie mo(cid:
Pobierz darmowy fragment (pdf)

Gdzie kupić całą publikację:

Testy jednostkowe. Świat niezawodnych aplikacji. Wydanie II
Autor:

Opinie na temat publikacji:


Inne popularne pozycje z tej kategorii:


Czytaj również:


Prowadzisz stronę lub blog? Wstaw link do fragmentu tej książki i współpracuj z Cyfroteką: