Cyfroteka.pl

klikaj i czytaj online

Cyfro
Czytomierz
01280 012746 11048871 na godz. na dobę w sumie
Java. Praktyczne narzędzia - książka
Java. Praktyczne narzędzia - książka
Autor: Liczba stron: 888
Wydawca: Helion Język publikacji: polski
ISBN: 978-83-246-1932-0 Data wydania:
Lektor:
Kategoria: ebooki >> komputery i informatyka >> programowanie >> java - programowanie
Porównaj ceny (książka, ebook, audiobook).

Poznaj narzędzia, które okażą się niezbędne!

Możliwości języka Java znają już chyba wszyscy. Dlatego warto jedynie wspomnieć o tym, że oprócz podstawowych narzędzi do tworzenia oprogramowania w tym języku, które zna każdy programista, istnieje wiele innych -- przydatnych i użytecznych -- aplikacji. Potrafią one w niezwykle skuteczny sposób przyśpieszyć oraz ułatwić programowanie w języku Java i sprawić, że będzie to zajęcie jeszcze przyjemniejsze. W żadnej innej książce nie znajdziesz tak szczegółowego omówienia tych narzędzi. Zatem jeśli wykorzystujesz język Java na co dzień, musisz ją mieć!

Dzięki tej książce poznasz 33 praktyczne narzędzia, które ułatwią Twoją pracę -- narzędzia, które zwiększą niezawodność Twojego kodu, poprawią wydajność oraz zapewnią bezpieczeństwo Twoim plikom źródłowym. Autor książki omawia kilka grup narzędzi, a wśród nich aplikacje takie, jak Maven, Subversion, JUnit czy też Hudson. Dzięki książce 'Java. Praktyczne narzędzia' dowiesz się, jak bardzo na jakość Twojego rozwiązania może wpłynąć proces ciągłej integracji oraz jak ważne są testy jednostkowe czy integracyjne. Ponadto autor książki omawia 29 innych narzędzi, które zwiększają komfort pracy. Otwórz spis treści i spójrz, jak cenne informacje są zawarte w tej książce!

Zobacz, jak łatwo można wykonać skomplikowane zadania!

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

Darmowy fragment publikacji:

Java. Praktyczne narzêdzia Autor: John Ferguson Smart T³umaczenie: Miko³aj Szczepaniak ISBN: 978-83-246-1932-0 Tytu³ orygina³u: Java Power Tools Format: 168x237, stron: 888 Poznaj narzêdzia, które oka¿¹ siê niezbêdne! • Jak zapewniæ wysok¹ jakoœæ tworzonego rozwi¹zania? • Jak wprowadziæ proces ci¹g³ej integracji? • Jak testowaæ kod? Mo¿liwoœci jêzyka Java znaj¹ ju¿ chyba wszyscy. Dlatego warto jedynie wspomnieæ o tym, ¿e oprócz podstawowych narzêdzi do tworzenia oprogramowania w tym jêzyku, które zna ka¿dy programista, istnieje wiele innych — przydatnych i u¿ytecznych — aplikacji. Potrafi¹ one w niezwykle skuteczny sposób przyœpieszyæ oraz u³atwiæ programowanie w jêzyku Java i sprawiæ, ¿e bêdzie to zajêcie jeszcze przyjemniejsze. W ¿adnej innej ksi¹¿ce nie znajdziesz tak szczegó³owego omówienia tych narzêdzi. Zatem jeœli wykorzystujesz jêzyk Java na co dzieñ, musisz j¹ mieæ! Dziêki tej ksi¹¿ce poznasz 33 praktyczne narzêdzia, które u³atwi¹ Twoj¹ pracê — narzêdzia, które zwiêksz¹ niezawodnoœæ Twojego kodu, poprawi¹ wydajnoœæ oraz zapewni¹ bezpieczeñstwo Twoim plikom Ÿród³owym. Autor ksi¹¿ki omawia kilka grup narzêdzi, a wœród nich aplikacje takie, jak Maven, Subversion, JUnit czy te¿ Hudson. Dziêki ksi¹¿ce „Java. Praktyczne narzêdzia” dowiesz siê, jak bardzo na jakoœæ Twojego rozwi¹zania mo¿e wp³yn¹æ proces ci¹g³ej integracji oraz jak wa¿ne s¹ testy jednostkowe czy integracyjne. Ponadto autor ksi¹¿ki omawia 29 innych narzêdzi, które zwiêkszaj¹ komfort pracy. Otwórz spis treœci i spójrz, jak cenne informacje s¹ zawarte w tej ksi¹¿ce! • Wykorzystanie narzêdzi kompiluj¹cych (Ant, Maven2) • Zastosowanie systemów kontroli wersji (CVS, Subversion) • Sposoby oceny jakoœci kodu (CheckStyle, PMD, FindBugs, Jupiter) • Tworzenie wysokiej jakoœci dokumentacji • Przygotowanie testów jednostkowych (JUnit, TestNG) • Przeprowadzanie testów integracyjnych • Systemy raportowania i œledzenia b³êdów (Bugzilla, Trac) • Narzêdzia pozwalaj¹ce na wprowadzenie procesu ci¹g³ej integracji (Continuum, Hudson) • Sposoby przeprowadzania testów obci¹¿eniowych • Profilowanie i monitorowanie aplikacji za pomoc¹ narzêdzi dostêpnych w pakiecie JDK oraz Eclipse Zobacz, jak ³atwo mo¿na wykonaæ skomplikowane zadania! Spis treļci Sĥowo wstýpne ........................................................................................................................17 Przedmowa ............................................................................................................................. 19 Wprowadzenie .......................................................................................................................33 I Narzýdzia kompilujéce ...........................................................................37 1. Przygotowywanie projektu z wykorzystaniem Anta ................................................ 41 41 41 44 51 53 57 75 77 81 1.1. Rola narzödzia Ant w procesie kompilacji 1.2. Instalacja Anta 1.3. Päynne wprowadzenie w Ĉwiat Anta 1.4. Kompilowanie kodu Javy za pomocñ Anta 1.5. Dostosowywanie skryptów kompilacji za pomocñ wäaĈciwoĈci 1.6. Przeprowadzanie testów jednostkowych za pomocñ Anta 1.7. Generowanie dokumentacji za pomocñ narzödzia Javadoc 1.8. Pakowanie gotowej aplikacji 1.9. WdraĔanie aplikacji 1.10.Automatyczne przygotowywanie Ĉrodowiska dla uruchamianych skryptów kompilacji 1.11. Stosowanie zaleĔnoĈci narzödzia Maven w Ancie wraz z zadaniami Mavena 1.12. Stosowanie Anta w Ĉrodowisku Eclipse 1.13. Stosowanie Anta w Ĉrodowisku NetBeans 1.14. Modyfikowanie kodu XML-a za pomocñ zadania XMLTask 1.15. Konkluzja 83 85 89 89 90 95 2. Przygotowywanie projektu z wykorzystaniem Mavena 2 ........................................97 97 98 99 101 2.1. Rola narzödzia Maven w procesie kompilacji 2.2. Maven i Ant 2.3. Instalacja Mavena 2.4. Kompilacje deklaratywne i model obiektu projektu Mavena 5 2.5. Zrozumieè cykl Ĕycia Mavena 2 2.6. Struktura katalogów Mavena 2.7. Konfigurowanie Mavena pod kñtem naszego Ĉrodowiska 2.8. Zarzñdzanie zaleĔnoĈciami w Mavenie 2 2.9. Poszukiwanie zaleĔnoĈci za poĈrednictwem witryny Maven Repository 2.10. Dziedziczenie i agregacja projektów 2.11. Tworzenie szablonu projektu za pomocñ tzw. archetypów 2.12. Kompilacja kodu 2.13. Testowanie kodu 2.14. Pakowanie i wdraĔanie naszej aplikacji 2.15. WdraĔanie aplikacji z wykorzystaniem narzödzia Cargo 2.16. Stosowanie Mavena w Ĉrodowisku Eclipse 2.17. Stosowanie Mavena w Ĉrodowisku NetBeans 2.18. Dostosowywanie procesu kompilacji do specyficznych potrzeb projektu za pomocñ wäasnych moduäów rozszerzeþ 2.19. Konfigurowanie repozytorium korporacyjnego za pomocñ narzödzia Archiva 2.20. Konfigurowanie repozytorium korporacyjnego z wykorzystaniem narzödzia Artifactory 2.21. Stosowanie narzödzia Ant w Mavenie 2.22. Archetypy zaawansowane 2.23. Stosowanie podzespoäów 112 114 115 118 126 127 131 135 136 138 140 144 147 147 154 166 178 183 187 II Narzýdzia kontroli wersji......................................................................193 3. Kontrola wersji z wykorzystaniem systemu CVS ..................................................... 195 195 3.1. Wprowadzenie do systemu CVS 196 3.2. Konfigurowanie repozytorium systemu CVS 196 3.3. Tworzenie nowego projektu w systemie CVS 3.4. WypoĔyczanie projektu 198 3.5. Praca na plikach — aktualizowanie i zatwierdzanie plików z kodem Ēródäowym 200 3.6. Blokowanie repozytorium 204 204 3.7. Praca z mechanizmem zastöpowania säów kluczowych 205 3.8. Praca z plikami binarnymi 207 3.9. Znaczniki systemu CVS 3.10. Tworzenie odgaäözieþ w systemie CVS 208 210 3.11. Scalanie zmian z odgaäözienia 211 3.12. Przeglñdanie historii zmian 213 3.13. Wycofywanie zmian 3.14. Stosowanie CVS-a w systemie Windows 214 6 _ Spis treļci 4. Kontrola wersji z wykorzystaniem systemu Subversion ..........................................217 217 221 221 223 225 227 228 230 231 235 237 239 243 244 246 4.1. Wprowadzenie do systemu Subversion 4.2. Instalacja systemu Subversion 4.3. Typy repozytoriów systemu Subversion 4.4. Konfigurowanie repozytorium systemu Subversion 4.5. Tworzenie nowego projektu w systemie Subversion 4.6. WypoĔyczanie kopii roboczej 4.7. Importowanie istniejñcych plików do repozytorium systemu Subversion 4.8. Zrozumieè adresy URL repozytorium systemu Subversion 4.9. Praca z plikami 4.10. Sprawdzanie bieĔñcej sytuacji — polecenie status 4.11. Rozwiñzywanie konfliktów 4.12. Stosowanie znaczników, odgaäözieþ i operacji scalania 4.13. Przywracanie poprzedniej rewizji 4.14. Blokowanie dostöpu do plików binarnych 4.15. Zdejmowanie i przechwytywanie blokad 4.16. Udostöpnianie zablokowanych plików tylko do odczytu za pomocñ wäaĈciwoĈci svn:needs-lock 248 249 252 253 257 258 263 4.17. Stosowanie wäaĈciwoĈci 4.18. Historia zmian w systemie Subversion — rejestrowanie zdarzeþ i okreĈlanie odpowiedzialnoĈci za zmiany 4.19.Konfigurowanie serwera systemu Subversion z wykorzystaniem serwera svnserve 4.20. Konfigurowanie bezpiecznego serwera svnserve 4.21. Konfigurowanie serwera Subversion z obsäugñ protokoäu WebDAV/DeltaV 4.22. Konfigurowanie bezpiecznego serwera WebDAV/DeltaV 4.23. Dostosowywanie dziaäania systemu Subversion za pomocñ skryptów przechwytujñcych 264 4.24. Instalacja systemu Subversion w formie usäugi systemu operacyjnego Windows 266 4.25. Sporzñdzanie kopii zapasowej i przywracanie repozytorium systemu Subversion 268 268 4.26. Stosowanie systemu Subversion w Ĉrodowisku Eclipse 4.27. Stosowanie systemu Subversion w Ĉrodowisku NetBeans 275 281 4.28. Stosowanie systemu Subversion w systemie operacyjnym Windows 287 4.29. ćledzenie usterek i kontrola zmian 4.30. Stosowanie systemu Subversion w Ancie 290 292 4.31. Konkluzja III Ciégĥa integracja .................................................................................. 293 5. Konfigurowanie serwera ciégĥej integracji za pomocé narzýdzia Continuum ......297 297 297 5.1. Wprowadzenie do narzödzia Continuum 5.2. Instalacja serwera narzödzia Continuum Spis treļci _ 7 5.3. Röczne uruchamianie i zatrzymywanie serwera 5.4. Sprawdzanie stanu serwera 5.5. Uruchamianie serwera narzödzia Continuum w trybie ze szczegóäowymi 301 302 komunikatami 302 303 5.6. Dodawanie grupy projektów 303 5.7. Dodawanie projektu Mavena 306 5.8. Dodawanie projektu Anta 307 5.9. Dodawanie projektu kompilowanego za pomocñ skryptu powäoki 307 5.10. Zarzñdzanie kompilacjami projektu 309 5.11. Zarzñdzanie uĔytkownikami 311 5.12. Konfigurowanie mechanizmów powiadomieþ 311 5.13. Konfigurowanie planowanych kompilacji 314 5.14. Diagnozowanie procesu kompilacji 314 5.15. Konfigurowanie serwera poczty elektronicznej narzödzia Continuum 5.16. Konfigurowanie portów witryny internetowej serwera Continuum 315 5.17. Automatyczne generowanie witryny Mavena za pomocñ narzödzia Continuum 316 317 5.18. Konfigurowanie zadania röcznej kompilacji 5.19. Konkluzja 319 6. Konfigurowanie serwera ciégĥej integracji za pomocé narzýdzia CruiseControl ......... 321 321 322 323 329 336 338 339 340 6.1. Wprowadzenie do narzödzia CruiseControl 6.2. Instalacja narzödzia CruiseControl 6.3. Konfigurowanie projektu Anta 6.4. Powiadamianie czäonków zespoäu za pomocñ mechanizmów publikujñcych 6.5. Konfigurowanie projektu Mavena 2 w narzödziu CruiseControl 6.6. Panel administracyjny narzödzia CruiseControl 6.7. Dodatkowe narzödzia 6.8. Konkluzja 7. LuntBuild — serwer ciégĥej integracji z interfejsem WWW .................................... 341 341 341 343 345 352 353 355 7.1. Wprowadzenie do narzödzia LuntBuild 7.2. Instalowanie narzödzia LuntBuild 7.3. Konfigurowanie serwera LuntBuild 7.4. Dodawanie projektu 7.5. Wykorzystywanie zmiennych projektowych do numerowania wersji 7.6. Diagnostyka wyników kompilacji 7.7. Stosowanie narzödzia LuntBuild w Ĉrodowisku Eclipse 7.8. Raportowanie w systemie LuntBuild o pokryciu testami z wykorzystaniem narzödzia Cobertura 7.9. Integrowanie narzödzia LuntBuild z Mavenem 7.10. Konkluzja 359 365 370 8 _ Spis treļci 8. Ciégĥa integracja z wykorzystaniem narzýdzia Hudson ...........................................371 371 371 372 373 374 376 381 382 383 385 386 386 387 388 388 390 8.1. Wprowadzenie do narzödzia Hudson 8.2. Instalacja narzödzia Hudson 8.3. Zarzñdzanie katalogiem domowym Hudsona 8.4. Instalacja aktualizacji 8.5. Konfigurowanie Hudsona 8.6. Dodawanie nowego zadania kompilacji 8.7. Organizowanie zadaþ 8.8. Monitorowanie kompilacji 8.9. Przeglñdanie i awansowanie wybranych kompilacji 8.10. Zarzñdzanie uĔytkownikami 8.11. Uwierzytelnianie i bezpieczeþstwo 8.12. Przeglñdanie zmian 8.13. Moduäy rozszerzeþ Hudsona 8.14. ćledzenie wyników testów 8.15. ćledzenie mierników kodu Ēródäowego 8.16. Raportowanie o pokryciu kodu 9. Konfigurowanie platformy natychmiastowej komunikacji za pomocé serwera Openfire ....................................................................................393 393 9.1. Natychmiastowa komunikacja w projekcie informatycznym 394 9.2. Instalacja serwera Openfire 394 9.3. Konfigurowanie uĔytkowników i kont uĔytkowników serwera Openfire 9.4. Uwierzytelnianie uĔytkowników z wykorzystaniem zewnötrznej bazy danych 396 397 9.5. Uwierzytelnianie uĔytkowników na serwerze POP3 398 9.6. Organizowanie wirtualnych spotkaþ zespoäu z wykorzystaniem czatu grupowego 9.7. Rozszerzanie funkcjonalnoĈci serwera Openfire za pomocñ moduäów rozszerzeþ 400 400 9.8. Stosowanie serwera Openfire z systemem Continuum 401 9.9. Stosowanie serwera Openfire z systemem CruiseControl 9.10. Stosowanie serwera Openfire z narzödziem LuntBuild 402 9.11. Wysyäanie komunikatów Jabbera z poziomu aplikacji Javy za poĈrednictwem interfejsu API Smack 9.12. Wykrywanie obecnoĈci interfejsu API Smack 9.13. Otrzymywanie wiadomoĈci z wykorzystaniem interfejsu API Smack 402 405 405 IV Testy jednostkowe .............................................................................. 407 10. Testowanie kodu z wykorzystaniem frameworku JUnit .........................................409 409 410 412 10.1. Frameworki JUnit 3.8 i JUnit 4 10.2. Testowanie jednostkowe z wykorzystaniem frameworku JUnit 4 10.3. Konfigurowanie i optymalizacja przypadków testów jednostkowych Spis treļci _ 9 10.4. Proste testy wydajnoĈci z wykorzystaniem limitów czasowych 10.5. Prosta weryfikacja wystöpowania wyjñtków 10.6. Stosowanie testów sparametryzowanych 10.7. Stosowanie metody assertThat() i biblioteki Hamcrest 10.8. Teorie we frameworku JUnit 4 10.9. Stosowanie frameworku JUnit 4 w projektach Mavena 2 10.10. Stosowanie frameworku JUnit 4 w projektach Anta 10.11. Selektywne wykonywanie testów frameworku JUnit 4 w Ancie 10.12. Testy integracyjne 10.13. Korzystanie z frameworku JUnit 4 w Ĉrodowisku Eclipse 414 415 415 418 421 423 423 426 428 429 11. Testowanie nowej generacji z wykorzystaniem frameworku TestNG ...................433 433 433 435 437 440 443 444 449 451 454 455 456 456 457 11.1. Wprowadzenie do frameworku TestNG 11.2. Tworzenie prostych testów jednostkowych za pomocñ frameworku TestNG 11.3. Definiowanie pakietów testów frameworku TestNG 11.4. Moduä rozszerzenia frameworku TestNG dla Ĉrodowiska Eclipse 11.5. Stosowanie frameworku TestNG w Ancie 11.6. Korzystanie z frameworku TestNG w Mavenie 2 11.7. Zarzñdzanie cyklem Ĕycia testów 11.8. Stosowanie grup testów 11.9. Zarzñdzanie zaleĔnoĈciami 11.10. Testowanie równolegäe 11.11. Parametry testów i testowanie sterowane danymi 11.12. Weryfikacja wyjñtków 11.13. Obsäuga bäödów czöĈciowych 11.14. Ponowne wykonywanie testów zakoþczonych niepowodzeniem 12. Maksymalizacja pokrycia testami za pomocé narzýdzia Cobertura .......................459 459 460 463 465 467 469 471 473 475 12.1. Pokrycie testami 12.2. Uruchamianie narzödzia Cobertura za poĈrednictwem Anta 12.3. Weryfikacja pokrycia kodu testami frameworku TestNG 12.4. Interpretacja raportu narzödzia Cobertura 12.5. Wymuszanie duĔego pokrycia kodu 12.6. Generowanie raportów narzödzia Cobertura w Mavenie 12.7. Integracja testów pokrycia kodu z procesem kompilacji Mavena 12.8. Badanie pokrycia kodu w Ĉrodowisku Eclipse 12.9. Konkluzja 10 _ Spis treļci V Testy integracyjne, funkcjonalne, obciéŜeniowe i wydajnoļciowe ...477 13. Testowanie aplikacji frameworku Struts z wykorzystaniem frameworku StrutsTestCase ......................................................481 13.1. Wprowadzenie 481 482 13.2. Testowanie aplikacji frameworku Struts 483 13.3. Wprowadzenie do frameworku StrutsTestCase 483 13.4. Testy obiektów zastöpczych z wykorzystaniem frameworku StrutsTestCase 13.5. Testowanie mechanizmów obsäugi bäödów w aplikacji frameworku Struts 488 489 13.6. Dostosowywanie Ĉrodowiska testowego 489 13.7. Testy wydajnoĈciowe pierwszego stopnia 13.8. Konkluzja 490 14. Testy integracyjne baz danych z wykorzystaniem frameworku DbUnit ................ 491 491 491 493 497 498 506 510 516 520 524 14.1. Wprowadzenie 14.2. Przeglñd 14.3. Struktura frameworku DbUnit 14.4. Przykäadowa aplikacja 14.5. Wypeänianie bazy danych 14.6. Weryfikacja bazy danych 14.7. Zastöpowanie wartoĈci 14.8. Alternatywne formaty zbiorów danych 14.9. Obsäuga niestandardowych testów danych 14.10. Pozostaäe zastosowania 15. Testy wydajnoļciowe z wykorzystaniem frameworku JUnitPerf ...........................533 533 534 536 15.1. Wprowadzenie do frameworku JUnitPerf 15.2. Badanie wydajnoĈci za pomocñ klasy TimedTest 15.3. Symulowanie obciñĔenia za pomocñ klasy LoadTest 15.4. Przeprowadzanie testów wydajnoĈciowych, które nie gwarantujñ bezpieczeþstwa przetwarzania wielowñtkowego 15.5. Oddzielanie testów wydajnoĈciowych od testów jednostkowych w Ancie 15.6. Oddzielanie testów wydajnoĈciowych od testów jednostkowych w Mavenie 539 540 541 16. Wykonywanie testów obciéŜeniowych i wydajnoļciowych za pomocé narzýdzia JMeter.....................................................................................543 543 16.1. Wprowadzenie 544 16.2. Instalacja narzödzia JMeter 16.3. Testowanie prostej aplikacji internetowej 544 550 16.4. Projektowanie struktury naszego przypadku testowego 16.5. Rejestrowanie i wyĈwietlanie wyników testu 553 Spis treļci _ 11 16.6. Rejestrowanie przypadku testowego za pomocñ serwera proxy narzödzia JMeter 556 16.7. Testowanie z wykorzystaniem zmiennych 558 560 16.8. Testowanie na wielu komputerach 17. Testowanie usĥug sieciowych za pomocé narzýdzia SoapUI ..................................563 563 563 565 565 567 573 576 578 579 580 581 17.1. Wprowadzenie 17.2. Wprowadzenie do narzödzia SoapUI 17.3. Instalacja narzödzia SoapUI 17.4. Instalacja lokalnej usäugi sieciowej 17.5.Testowanie usäug sieciowych za pomocñ narzödzia SoapUI 17.6. Przeprowadzanie testów obciñĔeniowych za pomocñ narzödzia SoapUI 17.7. Uruchamianie narzödzia SoapUI z poziomu wiersza poleceþ 17.8. Uruchamianie narzödzia SoapUI za poĈrednictwem Anta 17.9. Uruchamianie narzödzia SoapUI za poĈrednictwem Mavena 17.10. Testy ciñgäe 17.11. Konkluzja 18. Profilowanie i monitorowanie aplikacji Javy za pomocé narzýdzi pakietu Sun JDK .......................................................................583 18.1. Narzödzia profilujñce i monitorujñce pakietu Sun JDK 583 18.2. Nawiñzywanie poäñczenia z aplikacjñ Javy i monitorowanie jej dziaäania za pomocñ narzödzia JConsole 583 18.3. Monitorowanie zdalnej aplikacji na serwerze Tomcat za pomocñ narzödzia JConsole 18.4. Wykrywanie i identyfikacja wycieków pamiöci za pomocñ narzödzi pakietu JDK 18.5. Diagnozowanie wycieków pamiöci z wykorzystaniem zrzutów sterty oraz narzödzi jmap i jhat 18.6. Wykrywanie zakleszczeþ 587 588 593 595 19. Profilowanie aplikacji Javy w ļrodowisku Eclipse ...................................................599 599 599 601 601 602 607 609 610 611 613 613 19.1. Profilowanie aplikacji z poziomu Ĉrodowiska IDE 19.2. Platforma TPTP Ĉrodowiska Eclipse 19.3. Instalacja platformy TPTP 19.4. Platformy TPTP i Java 6 19.5. Podstawowe techniki profilowania z wykorzystaniem platformy TPTP 19.6. Ocena uĔycia pamiöci na podstawie wyników podstawowej analizy pamiöci 19.7. Analiza czasu wykonywania 19.8. WyĈwietlanie statystyk pokrycia 19.9. Stosowanie filtrów zawöĔajñcych uzyskiwane wyniki 19.10. Profilowanie aplikacji internetowej 19.11. Konkluzja 12 _ Spis treļci 20. Testowanie interfejsów uŜytkownika ...................................................................... 615 615 615 642 651 20.1. Wprowadzenie 20.2. Testowanie aplikacji internetowej za pomocñ narzödzia Selenium 20.3. Testowanie graficznych interfejsów Swinga za pomocñ narzödzia FEST 20.4. Konkluzja VI Narzýdzia pomiaru jakoļci................................................................... 653 21. Wykrywanie i wymuszanie standardów kodowania za pomocé narzýdzia Checkstyle ..............................................................................657 657 21.1. Wymuszanie standardów kodowania za pomocñ narzödzia Checkstyle 659 21.2. Stosowanie narzödzia Checkstyle w Ĉrodowisku Eclipse 21.3. Modyfikowanie reguä narzödzia Checkstyle w Ĉrodowisku Eclipse 663 21.4. Dostosowywanie reguä narzödzia Checkstyle z wykorzystaniem plików konfiguracyjnych w formacie XML 21.5. Dostosowywanie pracy narzödzia Checkstyle — reguäy, bez których moĔemy sobie poradziè, i kilka reguä, z których warto korzystaè 21.6. Stosowanie narzödzia Checkstyle do definiowania reguä dla nagäówków w kodzie Ēródäowym 21.7. Wstrzymywanie testów narzödzia Checkstyle 21.8. Korzystanie z narzödzia Checkstyle w Ancie 21.9. Korzystanie z narzödzia Checkstyle w Mavenie 665 667 671 672 673 674 22. Wstýpne wykrywanie bĥýdów za pomocé narzýdzia PMD ..................................... 677 677 677 680 681 684 685 686 687 688 691 22.1. Narzödzie PMD i statyczna analiza kodu 22.2. Korzystanie z narzödzia PMD w Ĉrodowisku Eclipse 22.3.Konfiguracja reguä narzödzia PMD w Ĉrodowisku Eclipse 22.4. Wiöcej o zbiorach reguä narzödzia PMD 22.5. Pisanie wäasnych zbiorów reguä narzödzia 22.6. Generowanie raportu narzödzia PMD w Ĉrodowisku Eclipse 22.7. Wstrzymywanie reguä narzödzia PMD 22.8. Wykrywanie praktyki „wytnij i wklej” za pomocñ narzödzia CPD 22.9. Stosowanie narzödzia PMD w Ancie 22.10. Stosowanie narzödzia PMD w Mavenie 23. Wstýpne wykrywanie bĥýdów za pomocé narzýdzia FindBugs ..............................693 693 695 697 698 23.1. FindBugs jako wyspecjalizowany zabójca bäödów 23.2.Stosowanie narzödzia FindBugs w Ĉrodowisku Eclipse 23.3. Wybiórcze zawieszanie stosowania reguä za pomocñ filtrów narzödzia FindBugs 23.4. Stosowanie adnotacji narzödzia FindBugs Spis treļci _ 13 23.5. Korzystanie z narzödzia FindBugs w Ancie 23.6. Korzystanie z narzödzia FindBugs w Mavenie 23.7. Konkluzja 700 702 704 24. Analiza wyników — póĥautomatyczne przeglédy kodu za pomocé narzýdzia Jupiter ....................................................................................705 24.1. Wprowadzenie do Jupitera — narzödzia do przeglñdania kodu w Ĉrodowisku Eclipse 24.2. Instalacja narzödzia Jupiter w Ĉrodowisku Eclipse 24.3.Zrozumieè proces przeglñdów kodu narzödzia Jupiter 24.4. Prowadzenie przeglñdów wäasnego kodu 24.5. Konfiguracja 24.6. Ustawianie domyĈlnych wartoĈci konfiguracyjnych 24.7. Przeglñdy indywidualne 24.8. Przeglñdy zespoäowe 24.9. Faza wprowadzania poprawek 24.10. Wewnötrzne dziaäania Jupitera 24.11. Konkluzja 705 706 706 708 709 713 714 716 719 719 721 25. Koncentrujmy siý na tym, co naprawdý waŜne — narzýdzie Mylyn ......................723 723 724 725 727 25.1. Wprowadzenie do narzödzia Mylyn 25.2. Instalacja rozszerzenia Mylyn 25.3. ćledzenie zadaþ i problemów 25.4. Korzystanie z repozytoriów zadaþ 25.5.Koncentrowanie siö na wybranych zadaniach z wykorzystaniem mechanizmów zarzñdzania kontekstami 25.6. Korzystanie ze zbiorów zmian Ĉrodowiska Eclipse 25.7. Wspóädzielenie kontekstu z pozostaäymi programistami 25.8. Konkluzja 731 734 736 737 26. Monitorowanie statystyk kompilacji.........................................................................739 739 739 747 748 26.1. Wprowadzenie 26.2. Narzödzie QALab 26.3. Mierzenie iloĈci kodu Ēródäowego za pomocñ moduäu rozszerzenia StatSCM 26.4. Statystyki narzödzia StatSVN w Ancie VII Narzýdzia do zarzédzania problemami ..............................................751 27. Bugzilla ......................................................................................................................753 753 753 757 27.1. Wprowadzenie do narzödzia Bugzilla 27.2. Instalacja narzödzia Bugzilla 27.3. Konfigurowanie Ĉrodowiska narzödzia Bugzilla 14 _ Spis treļci 27.4. Zarzñdzanie kontami uĔytkowników 758 27.5. Ograniczanie dostöpu do bazy danych z wykorzystaniem grup uĔytkowników 760 762 27.6. Konfigurowanie produktu 764 27.7. ćledzenie postöpu z wykorzystaniem tzw. kamieni milowych 27.8. Zarzñdzanie grupami produktów z wykorzystaniem klasyfikacji 764 765 27.9. Przeszukiwanie bäödów 767 27.10. Tworzenie nowego bäödu 768 27.11. Cykl Ĕycia bäödu reprezentowanego w systemie Bugzilla 27.12. Tworzenie harmonogramu rozsyäania powiadomieþ (pojökiwania) 770 771 27.13. Dostosowywanie pól systemu Bugzilla do potrzeb konkretnego projektu 27.14. Konkluzja 772 28. Trac — lekkie zarzédzanie projektami ..................................................................... 773 773 774 776 778 779 780 781 783 28.1. Wprowadzenie do narzödzia Trac 28.2. Instalacja narzödzia Trac 28.3. Definiowanie projektu narzödzia Trac 28.4. Uruchamianie narzödzia Trac w formie autonomicznego serwera 28.5 Konfiguracja polecenia tracd jako usäugi systemu Windows 28.6. Instalacja narzödzia Trac na serwerze Apache 28.7. Administrowanie witrynñ internetowñ Traca 28.8. Zarzñdzanie kontami uĔytkowników 28.9. Dostosowywanie witryny internetowej narzödzia Trac — korzystanie z funkcji witryn typu wiki 28.10. Stosowanie systemu zarzñdzania biletami Traca 28.11. Aktualizowanie bäödów reprezentowanych w narzödziu Trac na podstawie zawartoĈci repozytorium systemu Subversion 28.12. Modyfikowanie pól biletów Traca 28.13. Konfigurowanie powiadomieþ wysyäanych pocztñ elektronicznñ 28.14. Raportowanie z wykorzystaniem zapytaþ i raportów Traca 28.15. Zarzñdzanie postöpami prac za pomocñ map drogowych i diagramów linii czasu 28.16. Przeglñdanie repozytorium z kodem Ēródäowym 28.17. Stosowanie kanaäów RSS i formatu iCalendar 28.18. Dostosowywanie stron witryny wiki za pomocñ skryptów Pythona 28.19. Konkluzja 786 790 794 795 797 797 800 802 802 805 806 VIII Narzýdzia do dokumentacji technicznej ............................................ 807 29. Komunikacja w ramach zespoĥu projektowego za poļrednictwem witryny Mavena 2 ......................................................................809 809 29.1.Witryna internetowa Mavena 2 jako narzödzie komunikacyjne 29.2. Konfigurowanie mechanizmu generowania witryny o projekcie Mavena 810 Spis treļci _ 15 29.3. Wäñczanie do witryny Mavena raportów generowanych przez inne narzödzia 29.4. Tworzenie dedykowanego projektu witryny Mavena 29.5. Definiowanie szkicu witryny 29.6. Architektura mechanizmu generujñcego witryny Mavena 29.7. Stosowanie fragmentów kodu 29.8. Modyfikowanie wyglñdu i sposobu obsäugi witryny Mavena 29.9. Udostöpnianie witryny 815 819 821 822 826 827 830 30. Automatyczne generowanie dokumentacji technicznej .........................................833 833 833 841 30.1. Wprowadzenie 30.2. Wizualizacja struktury bazy danych za pomocñ narzödzia SchemaSpy 30.3. Generowanie dokumentacji kodu Ēródäowego za pomocñ Doxygena 30.4. Umieszczanie diagramów notacji UML w dokumentacji narzödzia Javadoc z wykorzystaniem narzödzia UmlGraph 30.5. Konkluzja 850 854 Bibliografia ...........................................................................................................................855 Skorowidz............................................................................................................................. 857 16 _ Spis treļci ROZDZIAĤ 10. Testowanie kodu z wykorzystaniem frameworku JUnit 10.1. Frameworki JUnit 3.8 i JUnit 4 JUnit w chwili wprowadzenia na rynek byä naprawdö rewolucyjnym oprogramowaniem — od tego czasu powstaäo mnóstwo przydatnych rozszerzeþ tego frameworku uäatwiajñcych nam wykonywanie testów jednostkowych w najbardziej wyspecjalizowanych obszarach. Wiele z tych rozszerzeþ do tej pory bazuje na frameworku JUnit 3.x. Kilka takich rozszerzeþ omówimy w dalszej czöĈci tej ksiñĔki. W niniejszym podrozdziale spróbujemy sobie przy- pomnieè framework 3.8, aby lepiej rozumieè dalszy materiaä poĈwiöcony zmianom wprowadzo- nym w nowszych frameworkach, jak JUnit 4 czy TestNG (patrz rozdziaä 20.). We frameworku JUnit 3 pisane przez nas testy jednostkowe majñ postaè klas Javy okreĈlanych mianem przypadków testowych. Wszystkie przypadki testowe tego frameworku muszñ rozsze- rzaè klasö TestCase. Testy jednostkowe implementujemy w formie metod tych klas — definiujñc te metody, musimy przestrzegaè specjalnych konwencji nazewniczych: metody testowe muszñ zwracaè void, nie mogñ pobieraè Ĕadnych parametrów, a ich nazwy muszñ siö rozpoczynaè od säowa test. TakĔe nazwy klas testowych muszñ byè zgodne z prostñ konwencjñ — nazwa kaĔdej takiej klasy musi siö koþczyè säowem Test. PoniĔej przedstawiono prostñ klasö testowñ frameworku JUnit 3.8 testujñcñ innñ klasö, która z kolei odpowiada za obliczanie podatku od wartoĈci dodanej (ang. Value Added Tax — VAT), nazywanego teĔ podatkiem od towarów i usäug. Przyjmijmy, Ĕe podstawowa stawka podatku VAT wynosi 22 procent. Nasz klasa testu jednostkowego moĔe mieè nastöpujñcñ postaè: public class PriceCalculatorTest extends TestCase { public void testCalculateVAT() { calculator = new PriceCalculator(); double amountWithVat = calculator.calculatePriceWithVAT(100.00); assertEquals( Podstawowa stawka VAT wynosi 22 , 122.00, amountWithVat, 0.0); } } Klasa bazowa TestCase oferuje mnóstwo metod z rodziny assert: assertEquals(), assert ´True(), assertNotNull() i wiele innych. WäaĈnie wymienione metody skäadajñ siö na jñdro testów jednostkowych, poniewaĔ za ich poĈrednictwem wykonujemy nasze testy. Metody assert säuĔñ do sprawdzania, czy uzyskiwane wyniki sñ zgodne z wartoĈciami oczekiwanymi. 409 Za poĈrednictwem pierwszego parametru metody assert moĔemy przekazaè opcjonalny komunikat, który w przyszäoĈci powinien nam uäatwiè identyfikacjö bäödu (szczególnie jeĈli korzystamy z duĔej liczby testów jednostkowych). Metody setUp() i tearDown() (zwróèmy uwagö na wielkie litery!) moĔna przykryè wersjami odpowiednio inicjalizujñcymi i przywracajñcymi (przed i po kaĔdym teĈcie) stan Ĉrodowiska testowego, w którym wykonujemy nasz kod. JeĈli na przykäad korzystamy z wielu przypadków testowych operujñcych na obiekcie calculator, moĔemy zdecydowaè o jego jednorazowym utworzeniu w kodzie metody setUp(): public class PriceCalculatorTest extends TestCase { PriceCalculator calculator; protected void setUp() throws Exception { calculator = new PriceCalculator(); } public void testCalculateVAT() { double amountWithVat = calculator.calculatePriceWithVAT(100.00); assertEquals( Podstawowa stawka VAT wynosi 22 , 122.00, amountWithVat, 0.0); } // Pozostaáe testy obiektu calculator... } MoĔliwoĈci frameworku JUnit 3 oczywiĈcie nie ograniczajñ siö do zaprezentowanych mecha- nizmów, jednak uzyskana wiedza o architekturze tego frameworku powinna w zupeänoĈci wystarczyè do zrozumienia innowacji wprowadzonych w nowszych frameworkach i rozszerzeþ frameworku JUnit 3 omawianych w pozostaäych rozdziaäach. Framework JUnit 4 pod wieloma wzglödami przewyĔsza framework JUnit 3, jednak wersja 3.8 wciñĔ cieszy siö duĔñ popularno- Ĉciñ, a wiele atrakcyjnych moduäów rozszerzeþ nadal nie doczekaäo siö aktualizacji do wersji 4. W kolejnych podrozdziaäach tego rozdziaäu skoncentrujemy siö wyäñcznie na frameworku JUnit 4. 10.2. Testowanie jednostkowe z wykorzystaniem frameworku JUnit 4 W Ĉwiecie frameworków testów jednostkowych JUnit jest de facto standardem. Jest powszechnie stosowany i doskonale znany niemal kaĔdemu programiĈcie. JUnit oferuje teĔ wiele przydatnych rozszerzeþ stworzonych z myĈlñ o bardziej wyspecjalizowanych procesach testowych. Frame- work JUnit (w oryginalnej wersji autorstwa Kenta Becka i Ericha Gammy) jest uwaĔany za rozwiñzanie, które (przynajmniej teoretycznie) spopularyzowaäo praktyki testów jednostko- wych wĈród programistów Javy. Okazuje siö jednak, Ĕe wskutek spadku dynamiki zmian wprowadzanych w podstawowym interfejsie API w ostatnich latach powstaäo i zyskaäo popularnoĈè kilka innych, jeszcze bardziej innowacyjnych frameworków, na przykäad TestNG (patrz rozdziaä 20.). JUnit 3 nakäada na programistów wiele ograniczeþ, które nie znajdujñ Ĕadnego uzasadnienia w dobie Javy 5, adnotacji i paradygmatu odwrócenia sterowania (ang. Inversion of Control — IoC). We frameworku JUnit 3 klasy testów muszñ rozszerzaè klasö bazowñ samego frameworku JUnit, a testy muszñ byè definiowane zgodnie ze specjalnymi konwencjami nazewnictwa — nie moĔemy uĔyè w roli klasy testu dowolnej klasy Javy. Klasy testów frameworku JUnit 3 410 _ Rozdziaĥ 10. Testowanie kodu z wykorzystaniem frameworku JUnit sñ inicjalizowane za kaĔdym razem, gdy wykonujemy jakiĈ test, co znacznie utrudnia refaktory- zacjö i optymalizacjö kodu testowego. JUnit 3 w Ĕaden sposób nie wspiera na przykäad testowa- nia sterowanego danymi (czyli wykonywania testów na danych pochodzñcych z zewnñtrz). We frameworku JUnit 3 brakuje teĔ takich mechanizmów jak funkcje zarzñdzania zaleĔnoĈciami pomiödzy testami czy grupami testów. JUnit 4 jest niemal caäkowicie przebudowanym interfejsem API JUnit, który ma na celu wyko- rzystanie postöpu obserwowanego w Ĉwiecie technologii Javy w ciñgu ostatnich kilku lat. Framework JUnit 4 jest prostszy, äatwiejszy w uĔyciu i bardziej elastyczny od swojego poprzed- nika; oferuje teĔ kilka nowych funkcji! JUnit 4 wprowadza mnóstwo nowych mechanizmów, które mogñ nam znacznie uäatwiè pisanie testów jednostkowych, w tym obsäugö adnotacji i bardziej elastyczny model inicjalizacji klas testów. We frameworku JUnit test moĔe mieè postaè dowolnej klasy Javy, a metody testów nie muszñ byè zgodne z Ĕadnymi konwencjami nazewniczymi. SprawdĒmy wiöc, jak nasze testy kalkulatora podatkowego (patrz podrozdziaä 10.1) wyglñdaäyby we frameworku JUnit 4: import org.junit.Before; import org.junit.Test; import static org.junit.Assert.*; public class PriceCalculatorTest { @Test public void calculateStandardVAT() { PriceCalculator calculator = new PriceCalculator(); double vat = calculator.calculatePriceWithVAT(100.00); assertEquals(vat, 122.00 , 0.0); } @Test public void calculateReducedVAT() { PriceCalculator calculator = new PriceCalculator(); double vat = calculator.calculatePriceWithReducedVAT(100.00); assertEquals(vat, 105.00 , 0.0); } } Warto w pierwszej kolejnoĈci zwróciè uwagö na brak koniecznoĈci rozszerzania konkretnej klasy przez przypadki testowe frameworku JUnit 4 (takie wymaganie obowiñzywaäo we frame- worku JUnit 3). Podobnie jak TestNG, framework JUnit 4 wykorzystuje adnotacje do oznaczania metod, które powinny byè traktowane jako testy jednostkowe. Za testy jednostkowe uwaĔa siö wszystkie metody oznaczone adnotacjñ @Test. JUnit 4 co prawda nie narzuca nam Ĕadnej kon- wencji nazewniczej (metody testów nie muszñ siö rozpoczynaè od säowa test, jak testThis() czy testThat()), ale wymaga, by metody testów jednostkowych zwracaäy void i nie pobieraäy Ĕadnych parametrów. Teoretycznie moĔna by nawet umieszczaè testy jednostkowe w tej samej klasie, w której znajduje siö testowany kod, jednak w praktyce lepszym rozwiñzaniem jest definiowanie kodu testowego w odröbnych klasach. Klasa org.junit.Assert zawiera tradycyjne metody assert frameworku JUnit 3.x, do których zdñĔyliĈmy siö przyzwyczaiè i które tak lubimy. We frameworku JUnit 3 metody assert byäy definiowane w klasie TestCase, czyli klasie bazowej dla wszystkich klas testów tego frameworku — dziöki temu moĔna byäo z nich korzystaè w dowolnych testach. Z zupeänie innñ sytuacjñ mamy do czynienia w przypadku frameworku JUnit 4, gdzie klasy testów nie muszñ dzie- dziczyè po klasie TestCase. Nie ma jednak powodów do zmartwieþ — moĔemy dla tej klasy 10.2. Testowanie jednostkowe z wykorzystaniem frameworku JUnit 4 _ 411 uĔyè operacji statycznego importowania, aby korzystaè z niezbödnych klas assert (w tym assertEquals, assertNotNull itp.; patrz przykäady w dalszej czöĈci tego rozdziaäu) w dokäadnie taki sam sposób jak w testach jednostkowych frameworku JUnit 3.x. Alternatywnym rozwiñzaniem jest stosowanie wyraĔeþ assert dostöpnych w Javie 5: assert (vat == 100*PriceCalculator.DEFAULT_VAT_RATE); WyraĔenie w tej formie sprawia wraĔenie bardziej eleganckiego, jednak musimy pamiötaè o pewnej puäapce — Java ignoruje nasze wyraĔenia assert, chyba Ĕe w wierszu poleceþ uĔyjemy opcji -ea (od ang. enable assertions). 10.3. Konfigurowanie i optymalizacja przypadków testów jednostkowych Jak kaĔdy kod Ēródäowy, testy jednostkowe wymagajñ efektywnego kodowania i — w razie koniecznoĈci — refaktoryzacji. Framework JUnit 4 oferuje kilka adnotacji, które mogñ nam to zadanie bardzo uäatwiè. Adnotacja @Before wskazuje metodö, która musi byè wywoäana przed kaĔdym testem, czyli w praktyce zastöpuje znanñ z frameworku JUnit 3.x metodö setup(). MoĔemy teĔ uĔyè adnotacji @After do wskazania metod przywracajñcych stan Ĉrodowiska testowego po kaĔdym wykonanym teĈcie. W tym przypadku metoda initialize() bödzie wywoäywana przed, a metoda tidyup() po kaĔdym teĈcie jednostkowym: import org.junit.Before; import org.junit.Test; import static org.junit.Assert.*; public class PriceCalculatorTest { private PriceCalculator calculator; @Before public void initialize() { calculator = new PriceCalculator(); } @Test public void calculateStandardVAT() { PriceCalculator calculator = new PriceCalculator(); double vat = calculator.calculatePriceWithVAT(100.00); assertEquals(vat, 122.00 , 0.0); } @Test public void calculateReducedVAT() { PriceCalculator calculator = new PriceCalculator(); double vat = calculator.calculatePriceWithReducedVAT(100.00); assertEquals(vat, 105 , 0.0); } @After public void tidyup() { calculator.close(); calculator = null; } } 412 _ Rozdziaĥ 10. Testowanie kodu z wykorzystaniem frameworku JUnit Takie rozwiñzanie wciñĔ nie jest optymalne. JUnit oferuje kilka innych adnotacji, których moĔna z powodzeniem uĔywaè do dodatkowego doskonalenia kodu naszych testów jednostko- wych. W pewnych sytuacjach warto poprawiè efektywnoĈè testów przez skonfigurowanie niektórych zasobów przed wykonaniem któregokolwiek z testów jednostkowych zdefinio- wanych w danej klasie i ich zwolnienie po zakoþczeniu wykonywania testów tej klasy. Cel ten moĔna osiñgnñè odpowiednio za pomocñ adnotacji @BeforeClass i @AfterClass. Metody oznaczone adnotacjñ @BeforeClass zostanñ wywoäane tylko raz, przed wykonaniem którego- kolwiek z testów jednostkowych definiowanych przez danñ klasö. Jak äatwo siö domyĈliè, metody oznaczone adnotacjñ @AfterClass zostanñ wywoäane dopiero po zakoþczeniu wszyst- kich testów. W powyĔszym przykäadzie obiekt calculator zostaäby utworzony tylko raz (na poczñtku testów jednostkowych) i zniszczony dopiero po wykonaniu wszystkich testów. Klasö tö moĔna uzupeäniè o metodö reset() wywoäywanñ przed kaĔdym testem jednostkowym i odpowiedzialnñ za kaĔdorazowe ponowne inicjalizowanie testowanego obiektu calculator. MoĔliwy sposób implementacji tak zoptymalizowanej klasy testów jednostkowych przedstawio- no poniĔej: import org.junit.Before; import org.junit.Test; import static org.junit.Assert.*; public class PriceCalculatorTest { private PriceCalculator calculator; @BeforeClass public void initialize() { calculator = new PriceCalculator(); } @Before public void resetCalculator() { calculator.reset(); } @Test public void calculateStandardVAT() { PriceCalculator calculator = new PriceCalculator(); double vat = calculator.calculatePriceWithVAT(100.00); assertEquals(vat, 122.00 , 0.0); } @Test public void calculateReducedVAT() { PriceCalculator calculator = new PriceCalculator(); double vat = calculator.calculatePriceWithReducedVAT(100.00); assertEquals(vat, 105 , 0.0); } @AfterClass public void tidyup() { calculator.close(); } } 10.3. Konfigurowanie i optymalizacja przypadków testów jednostkowych _ 413 10.4. Proste testy wydajnoļci z wykorzystaniem limitów czasowych Jednym z najprostszych sposobów przeprowadzania testów wydajnoĈci jest sprawdzanie, czy okreĈlony test zawsze jest wykonywany w okreĈlonych ramach czasowych. Takie rozwiñzanie bywa szczególnie przydatne w przypadku zapytaþ wykonywanych na bazie danych z uĔyciem takich narzödzi odwzorowaþ obiektowo-relacyjnych jak Hibernate. Nawet proste bäödy w plikach odwzorowaþ tego narzödzia mogñ skutkowaè znacznie wydäuĔonymi czasami odpowiedzi (takĔe w przypadku stosunkowo prostych zapytaþ). W przeciwieþstwie do trady- cyjnego testu jednostkowego, test z okreĈlonym limitem czasowym umoĔliwia wykrywanie tego rodzaju bäödów. Tego rodzaju testy sprawdzajñ siö takĔe w roli mechanizmów wykrywajñcych pötle nieskoþczo- ne, chociaĔ wskazanie fragmentów kodu, które mogñ zawieraè tego rodzaju konstrukcje, jest oczywiĈcie nieporównanie trudniejsze. Opisanñ technikö zintegrowano bezpoĈrednio z adnotacjñ @Test, która umoĔliwia ustawianie górnego limitu czasu, w którym dany test musi siö zakoþczyè — w przeciwnym razie po upäy- niöciu tego czasu test koþczy siö bäödem. W tym celu naleĔy zdefiniowaè parametr timeout (reprezentujñcy limit czasowy wyraĔony w milisekundach) adnotacji @Test: @Test(timeout=100) public void lookupVAT() { double vat = calculator.lookupRateForYear(2006); assertEquals(vat, VAT_RATE_IN_2006 , 0.0); } JeĈli uĔyte zapytanie zajmuje testowanej funkcji wiöcej niĔ 100 milisekund, nasz test koþczy siö niepowodzeniem: Testsuite: com.wakaleo.jpt.alexandria.services.PriceCalculatorTest Tests run: 3, Failures: 0, Errors: 1, Time elapsed: 0.136 sec Testcase: calculateStandardVAT took 0.009 sec Testcase: lookupVAT took 0.128 sec Caused an ERROR test timed out after 100 milliseconds java.lang.Exception: test timed out after 100 milliseconds W przypadku niektórych metod, od których oczekujemy wysokiej wydajnoĈci i których efektywnoĈè ma kluczowe znaczenie dla funkcjonowania naszej aplikacji, warto dodatkowo sprawdziè, czy oferowana przepustowoĈè speänia nasze oczekiwania. OczywiĈcie im mniejsza bödzie wartoĈè limitu czasowego, tym wiöksze bödzie ryzyko wystñpienia sytuacji, w której jakiĈ czynnik zewnötrzny spowalniajñcy nasze testy doprowadzi do nieuzasadnionego przekro- czenia tego limitu. Na przykäad w poniĔszym przypadku testowym sprawdzamy, czy Ĉredni czas wykonywania metody calculateInterest() nie przekracza milisekundy: @Test(timeout=50) public void perfTestCalculateInterest() { InterestCalculator calc = new InterestCalculatorImpl(); for(int i = 0 ; i 50; i++) { calc.calculateInterest(principal, interestRate, startDate, periodInDays); } } 414 _ Rozdziaĥ 10. Testowanie kodu z wykorzystaniem frameworku JUnit Tego rodzaju testy gwarantujñ nam, Ĕe uzyskiwane wyniki bödñ zbliĔone do rzeczywistoĈci i Ĕe badane metody nie sñ szczególnie powolne — nie powinniĈmy byè zbyt wymagajñcy. 10.5. Prosta weryfikacja wystýpowania wyjétków W niektórych przypadkach warto sprawdzaè, czy w okreĈlonych okolicznoĈciach nastöpuje prawidäowe generowanie wyjñtków. We frameworku JUnit 3.x to doĈè pracochäonne zadanie wiñĔe siö z koniecznoĈciñ przechwytywania wyjñtku — jeĈli wyjñtek uda siö przechwyciè, przyjmujemy, Ĕe test zakoþczyä siö pomyĈlnie; w przeciwnym razie test koþczy siö niepowo- dzeniem. We frameworku JUnit 4 mamy do dyspozycji parametr expected adnotacji @Test, któremu naleĔy przypisaè klasö oczekiwanego wyjñtku (wäaĈnie ten wyjñtek powinien zostaè wygenerowany zgodnie z naszym planem). W poniĔszym (doĈè maäo realistycznym) przykäadzie oczekujemy od aplikacji wygenerowania wyjñtku IllegalArgumentException, jeĈli dany rok jest mniejszy od przyjötego progu. We frameworku JUnit 4 odpowiedni test jest bardzo prosty: @Test(expected = IllegalArgumentException.class) public void lookupIllegalVATYear() { double vat = calculator.lookupRateForYear(1066); } JeĈli badana metoda nie wygeneruje wyjñtku IllegalArgumentException, nasz test zakoþczy siö niepowodzeniem: Testsuite: com.wakaleo.jpt.alexandria.services.PriceCalculatorTest Tests run: 3, Failures: 1, Errors: 0, Time elapsed: 0.114 sec Testcase: calculateStandardVAT took 0.009 sec Testcase: lookupVAT took 0.01 sec Testcase: lookupIllegalVATYear took 0.003 sec FAILED Expected exception: java.lang.IllegalArgumentException junit.framework.AssertionFailedError: Expected exception: java.lang.IllegalArgumentException 10.6. Stosowanie testów sparametryzowanych Pisanie testów jednostkowych jest doĈè nuĔñce, zatem wielu programistów próbuje iĈè na skróty. Okazuje siö jednak, Ĕe od pewnych czynnoĈci nie uciekniemy — dobre testy jednostkowe muszñ weryfikowaè dziaäanie funkcji biznesowych dla rozmaitych danych, jak przypadki skrajne, klasy danych itp. Ten sam test moĔe siö zakoþczyè pomyĈlnie dla jednego zbioru danych, by chwilö póĒniej wykazaè powaĔne bäödy dla innego zbioru. JeĈli jednak programista musi napisaè odröbny przypadek testowy dla kaĔdej wartoĈci (zgodnie z najlepszymi praktykami testowania), najprawdopodobniej jego kod bödzie weryfikowaä stosunkowo niewielki zbiór wartoĈci. CzyĔ nie byäoby wspaniale, gdybyĈmy mogli wielokrotnie wykonywaè ten sam test jednostkowy z wykorzystaniem róĔnych danych? Okazuje siö, Ĕe JUnit 4 oferuje dopracowany mechanizm uäatwiajñcy nam testowanie kodu na dowolnych zbiorach danych. Za pomocñ tego mechanizmu moĔemy zdefiniowaè kolekcjö danych testowych i wymusiè jej automatyczne wypeänianie w ramach naszych metod testów jednostkowych. Przeanalizujmy teraz prosty przykäad. PrzypuĈèmy, Ĕe musimy napisaè klasö wyznaczajñcñ wysokoĈè podatku dochodowego dla okreĈlonych dochodów we wskazanym roku. Interfejs naszej klasy biznesowej moĔe mieè nastöpujñcñ postaè: 10.6. Stosowanie testów sparametryzowanych _ 415 public interface TaxCalculator { public double calculateIncomeTax(int year, double taxableIncome); } Wyznaczanie podatku dochodowego z reguäy wymaga wykonywania kilku nieäatwych obliczeþ. W wiökszoĈci krajów stosuje siö system podatków progresywnych, gdzie stawki podatkowe rosnñ wraz ze wzrostem opodatkowanych dochodów. Stawki definiuje siö dla odröbnych przedziaäów dochodów. Co wiöcej, same progi podatkowe (a wiöc takĔe przedziaäy dochodów) nierzadko sñ zmieniane w kolejnych latach. W przypadku aplikacji odpowiedzialnej za tego rodzaju obliczenia niezwykle waĔne jest przetestowanie wartoĈci z kaĔdego przedziaäu, a takĔe przypadków skrajnych. W tej sytuacji powinniĈmy opracowaè kolekcjö danych testowych obejmujñcych moĔliwie wiele dochodów, lat i oczekiwanych obciñĔeþ podatkowych. SprawdĒmy, jak moĔna to zrobiè. JUnit 4 umoĔliwia nam definiowanie zbiorów danych testowych, które moĔna nastöpnie przekazywaè do naszych testów jednostkowych. W tym przypadku musimy przetestowaè róĔne dochody podlegajñce opodatkowaniu w róĔnych przedziaäach podatkowych. W prezento- wanym przykäadzie skoncentrujemy siö tylko na roku 2006, jednak w rzeczywistej aplikacji powinniĈmy poddaè testom wiele lat podatkowych. Nasze zbiory testowe bödñ wiöc zawieraè po trzy wartoĈci: opodatkowane dochody, rok podatkowy oraz prawidäowñ wysokoĈè podatku dochodowego. Korzystanie z tych danych testowych wymaga skonfigurowania sparametryzowanej klasy testowej. MoĔe to byè zwykäa klasa testowa z konstruktorem otrzymujñcym na wejĈciu kilka parametrów, a konkretnie po jednym parametrze dla kaĔdej wartoĈci naszego zbioru danych. Oznacza to, Ĕe w analizowanym przypadku wspomniany konstruktor bödzie pobieraä trzy parametry: opodatkowane dochody, rok podatkowy i oczekiwanñ wysokoĈè podatku docho- dowego. Sparametryzowana klasa testowa z reguäy obejmuje zmienne skäadowe reprezentu- jñce kaĔde z tych pól. Za inicjalizacjö tych pól odpowiada konstruktor, a wäaĈciwe metody testów jednostkowych wykorzystujñ je w czasie testowania. JUnit tworzy odröbny obiekt naszej klasy testów dla kaĔdego wiersza danych testowych, po czym wykonuje na tych danych testy jednostkowe (metody) tej klasy. Oznacza to, Ĕe jeĈli nasze dane testowe obejmujñ 20 wierszy, JUnit utworzy obiekt naszej klasy 20 razy i kaĔdorazo- wo wykona testy jednostkowe na innym wierszu tego zbioru danych. SprawdĒmy teraz, jak moĔna ten mechanizm zaimplementowaè. Kompletny kod naszej klasy testowej (dla fikcyjnych progów podatkowych) przedstawiono poniĔej: @RunWith(Parameterized.class) public class TaxCalculatorTest { @Parameters public static Collection data() { return Arrays.asList(new Object[][]{ /* Dochód Rok Podatek */ { 0.00, 2006, 0.00}, { 10000.00, 2006, 1950.00}, { 20000.00, 2006, 3900.00}, { 38000.00, 2006, 7410.00}, { 38001.00, 2006, 7410.33}, { 40000.00, 2006, 8070.00}, { 60000.00, 2006, 14670.00}, {100000.00, 2006, 30270.00}, }); } 416 _ Rozdziaĥ 10. Testowanie kodu z wykorzystaniem frameworku JUnit private double revenue; private int year; private double expectedTax; public TaxCalculatorTest(double input, int year, double expectedTax) { this.revenue = revenue; this.year = year; this.expectedTax = expectedTax; } @Test public void calculateTax() { TaxCalculator calculator = getTaxCalculator(); double calculatedTax = calculator.calculateIncomeTax(year, revenue); assertEquals(expectedTax, calculatedTax); } private TaxCalculator getTaxCalculator() { TaxCalculator calculator = new TaxCalculatorImpl(); return calculator; } } Przeanalizujmy teraz poszczególne fragmenty tej klasy. Po pierwsze, musimy uĔyè adnotacji @RunWith wskazujñcej na klasö Parameterized, aby zasygnalizowaè frameworkowi JUnit, Ĕe nasza klasa testowa zawiera sparametryzowane przypadki testowe: @RunWith(Parameterized.class) public class TaxCalculatorTest {... Musimy teraz sporzñdziè kolekcjö naszych danych testowych. W tym celu definiujemy funkcjö oznaczonñ adnotacjñ @Parameters i zwracajñcñ dane testowe w formie kolekcji. Dane testowe wewnötrznie czösto majñ postaè listy tablic. W naszym przypadku dane testowe przyjmujñ formö listy tablic wartoĈci, gdzie kaĔda tablica obejmuje trzy elementy: dochód, rok i oczekiwanñ wysokoĈè podatku dochodowego (od danego dochodu osiñgniötego we wskazanym roku podatkowym): @Parameters public static Collection data() { return Arrays.asList(new Object[][]{ /* Dochód Rok Podatek */ { 0.00, 2006, 0.00}, { 10000.00, 2006, 1950.00}, { 20000.00, 2006, 3900.00}, { 38000.00, 2006, 7410.00}, { 38001.00, 2006, 7410.33}, { 40000.00, 2006, 8070.00}, { 60000.00, 2006, 14670.00}, {100000.00, 2006, 30270.00}, }); } Jak juĔ wspomniano, kiedy framework JUnit 4 wykonuje naszñ klasö testowñ, w rzeczywistoĈci tworzy po jednym obiekcie tej klasy dla kaĔdego wiersza kolekcji danych testowych. W tej sytuacji musimy zdefiniowaè zmienne skäadowe reprezentujñce te wartoĈci, a takĔe konstruk- tor publiczny odpowiedzialny za ich inicjalizacjö, aby framework JUnit mógä tworzyè kolejne obiekty z wäaĈciwymi danymi testowymi: private double revenue; private int year; private double expectedTax; 10.6. Stosowanie testów sparametryzowanych _ 417 public TaxCalculatorTest(double revenue, int year, double expectedTax) { this.revenue = revenue; this.year = year; this.expectedTax = expectedTax; } MoĔemy teraz przetestowaè nasz kod z wykorzystaniem tych wartoĈci: @Test public void calculateTax() { TaxCalculator calculator = getTaxCalculator(); double calculatedTax = calculator.calculateIncomeTax(year, revenue); assertEquals(expectedTax, calculatedTax); } Kiedy uruchomimy te testy jednostkowe, okaĔe siö, Ĕe nasze testy zostanñ wykonane wielokrot- nie — osobno dla kaĔdego wiersza uĔytych danych testowych: Testsuite: com.wakaleo.jpt.alexandria.services.TaxCalculatorTest Tests run: 8, Failures: 0, Errors: 0, Time elapsed: 0.119 sec Testcase: calculateTax[0] took 0.012 sec Testcase: calculateTax[1] took 0.001 sec Testcase: calculateTax[2] took 0.002 sec Testcase: calculateTax[3] took 0.001 sec Testcase: calculateTax[4] took 0.001 sec Testcase: calculateTax[5] took 0.001 sec Testcase: calculateTax[6] took 0.002 sec Testcase: calculateTax[7] took 0.003 sec Warto pamiötaè o moĔliwoĈci umieszczania wielu testów jednostkowych w jednej sparame- tryzowanej klasie testów (podobnie jak w przypadku tradycyjnych klas testów jednostkowych). KaĔda metoda testu jednostkowego bödzie wywoäywana osobno dla kaĔdego wiersza danych testowych. 10.7. Stosowanie metody assertThat() i biblioteki Hamcrest We frameworku JUnit 4.4 wprowadzono nowe pojöcie dla wyraĔeþ asercji, aby intencje programistów byäy bardziej zrozumiaäe i äatwiejsze w interpretacji. Opisywana koncepcja, której oryginalnym pomysäodawcñ byä Joe Walnes1, sprowadza siö do stosowania metody assertThat äñcznie ze zbiorem wyraĔeþ dopasowujñcych (okreĈlanych teĔ mianem ograniczeþ lub predykatów), co w wielu przypadkach znacznie poprawia czytelnoĈè testów. Na przykäad poniĔsza klasa sprawdza, czy w danej sytuacji testowana funkcja wyznacza zerowy podatek dochodowy: import static org.junit.Assert.*; import static org.hamcrest.CoreMatchers.*; public class TaxCalculatorTest { @Test public void calculateTax() { TaxCalculator calculator = getTaxCalculator(); 1 Patrz http://joe.truemesh.com/blog/000511.html. 418 _ Rozdziaĥ 10. Testowanie kodu z wykorzystaniem frameworku JUnit double calculatedTax = calculator.calculateIncomeTax(2007, 0); assertThat(calculatedTax, is(0.0)); } } Wywoäanie assertThat(calculatedTax, is(0.0)) jest duĔo bardziej czytelne niĔ wywoäanie assertEquals(calculatedTax, 0.0, 0.0), choè oczywiĈcie wszystko zaleĔy od osobistych preferencji programisty. Sam uwaĔam wywoäanie w tej formie za bardziej naturalne. Jest krótsze i nie zmusza nas do podĈwiadomego täumaczenia samego wyraĔenia assertsEquals na zdanie „no dobrze, zatem wyznaczany podatek musi byè równy zero”. W przypadku pierwszego wyraĔenia nasz mózg od razu dochodzi do interpretacji: „Ĉwietnie, zakäadamy, Ĕe podatek bödzie zerowy”, co zajmuje nieporównanie mniej czasu. Bardziej czytelne testy oznaczajñ teĔ wiökszñ niezawodnoĈè i äatwoĈè w utrzymaniu. JeĈli interpretacja naszych testów jest prostsza, duĔo äatwiej i szybciej moĔemy stwierdziè, czy sñ prawidäowe. WyraĔenie dopasowujñce equalTo (lub is, czyli jego skrócona forma) moĔe byè z powodzeniem wykorzystywane w roli bardziej czytelnej wersji metody assertEquals: String result = czerwony ; assertThat(result, equalTo( czerwony )); Opisywane wyraĔenia moĔna teĔ äñczyè w bardziej zäoĔone zadania. MoĔemy na przykäad wykorzystaè wyraĔenie dopasowujñce anyOf do sprawdzenia, czy zmienna color zawiera äaþcuch czerwony , zielony lub niebieski : assertThat(color, anyOf(is( czerwony ),is( zielony ),is( niebieski ))); W razie koniecznoĈci moĔemy skojarzyè z naszym testem opis, który dodatkowo uäatwi jego interpretacjö: String color = hebanowy ; assertThat( czarny to czarny , color, is( czarny )); PowyĔsze wyraĔenie spowoduje wygenerowanie komunikatu o bäödzie uzupeänionego o nasz opis: FAILURE! java.lang.AssertionError: czarny to czarny Expected: czarny got: hebanowy ... MoĔemy teĔ uĔyè intuicyjnego wyraĔenia dopasowujñcego not, które neguje wszystkie pozostaäe wyraĔenia dopasowujñce: String color = czarny ; assertThat(color, is(not(( biaĪy )))); Te nowe metody w rzeczywistoĈci pochodzñ z zewnötrznej biblioteki nazwanej Hamcrest. Wachlarz wyraĔeþ dopasowujñcych oferowanych w ramach frameworku JUnit 4.4 jest doĈè ograniczony. MoĔna jednak ten zbiór uzupeäniè, doäñczajñc do realizowanego projektu bibliotekö hamcrest-all.jar. Wspomniany interfejs API moĔna pobraè z witryny internetowej biblioteki Hamcrest2. JeĈli korzystamy z Mavena, moĔemy po prostu dodaè odpowiedniñ referencjö do pliku POM: 2 Patrz http://code.google.com/p/hamcrest/downloads/list. 10.7. Stosowanie metody assertThat() i biblioteki Hamcrest _ 419 dependency groupId org.hamcrest /groupId artifactId hamcrest-all /artifactId version 1.1 /version scope test /scope /dependency W ten sposób zastöpujemy statyczne wyraĔenie importujñce bibliotekö org.hamcrest.Core ´Matchers wyraĔeniem importujñcym bardziej rozbudowanñ bibliotekö org.hamcrest. ´Matchers. Prezentowane rozwiñzanie daje nam dostöp do znacznie bogatszego zbioru wyraĔeþ dopasowujñcych. Niektóre z tych dodatkowych wyraĔeþ zostanñ omówione w dal- szej czöĈci tego podrozdziaäu. Do najbardziej interesujñcych wyraĔeþ dopasowujñcych naleĔñ mechanizmy upraszczajñce operacje na kolekcjach. Na przykäad wyraĔenie hasItem moĔna z powodzeniem wykorzystywaè do przeszukiwania zawartoĈci struktury typu List (w przypadku struktur tablicowych ten sam efekt moĔna uzyskaè, stosujñc wyraĔenie hasItemInArray): List String colors = new ArrayList String (); colors.add( czerwony ); colors.add( zielony ); colors.add( niebieski ); ... assertThat(colors, hasItem( czerwony )); WyraĔeþ dopasowujñcych hasItem i hasItemInArray moĔna uĔywaè do konstruowania skomplikowanych testów operujñcych na listach wartoĈci. PoniĔej przedstawiono przykäad sprawdzania, czy dana lista nie zawiera Ĕadnych elementów: List Integer ages = new ArrayList Integer (); ages.add(20); ages.add(30); ages.add(40); ... assertThat(ages, not(hasItem(lessThan(18)))); I odwrotnie, wyraĔenie dopasowujñce isIn umoĔliwia nam sprawdzanie, czy interesujñca nas lista zawiera konkretny obiekt: assertThat(20, isIn(ages)); Obsäuga kolekcji nie ogranicza siö tylko do list. WyraĔeþ dopasowujñcych hasKey i hasValue moĔna uĔywaè do sprawdzania, czy dana mapa (struktura typu Map) zawiera odpowiednio interesujñcy nas klucz lub wartoĈè: Map map = new HashMap(); map.put( color , czerwony ); ... assertThat(map, hasValue( czerwony )); Istnieje nawet wyraĔenie dopasowujñce hasProperty, które umoĔliwia nam testowanie wäa- ĈciwoĈci obiektów: Client client = new Client(); client.setClientName( Janina ); ... assertThat(client, hasProperty( clientName , is( Janina ))); W tym podrozdziale dokonaliĈmy przeglñdu zaledwie kilku moĔliwych zastosowaþ tego rodzaju wyraĔeþ. Inne dostöpne rozwiñzania moĔna znaleĒè w dokumentacji najnowszej wersji tego API. WyraĔenia dopasowujñce w tej formie umoĔliwiajñ nam tworzenie bardziej czytelnych 420 _ Rozdziaĥ 10. Testowanie kodu z wykorzystaniem frameworku JUnit i äatwiejszych w utrzymaniu testów, co z kolei stwarza szansö lepszego, szybszego i prostszego kodowania naszych testów. 10.8. Teorie we frameworku JUnit 4 Innñ nowñ i niezwykle przydatnñ (choè wciñĔ uwaĔanñ za element eksperymentalny) funkcjñ wprowadzonñ we frameworku 4.4 jest pojöcie teorii (przypuszczenia). Teoria wyraĔa ogólne przekonanie, które pozostaje prawdziwe dla wielu (byè moĔe nieskoþczenie wielu) zbiorów danych. Wszelkie ograniczenia zbiorów danych, dla których stosuje siö danñ teoriö, okreĈla siö mianem zaäoĔeþ. Programista w pierwszej kolejnoĈci definiuje zbiór punktów danych na potrzeby testów swojej teorii. Punkt danych jest (z reguäy staäym) elementem danych testowych identyfikowanym przez adnotacjö @DataPoint. Alternatywnym rozwiñzaniem jest uĔycie zautomatyzowanych narzödzi analizujñcych nasz kod i automatycznie tworzñcych zbiory danych wzmacniajñcych lub obalajñcych teoriö. Na przykäad poniĔej definiujemy prawidäowe wartoĈci dla lat 2007 i 2008: @DataPoint public static int YEAR_2007 = 2007; @DataPoint public static int YEAR_2008 = 2008; MoĔemy teraz uĔyè innego zbioru danych do zdefiniowania danych testowych wykorzysty- wanych w roli potencjalnych dochodów podatników: @DataPoint public static double INCOME_1 = 0.0; @DataPoint public static double INCOME_2 = 0.01; @DataPoint public static double INCOME_3 = 100.0; @DataPoint public static double INCOME_4 = 13999.99; @DataPoint public static double INCOME_5 = 14000.0; Aby zdefiniowaè test wykorzystujñcy teoriö, naleĔy w miejsce standardowej adnotacji @Test uĔyè adnotacji @Theory. Teoria jest zwykäñ metodñ otrzymujñcñ na wejĈciu pewnñ liczbö parametrów. Framework sam okreĈla, których punktów danych naleĔy uĔyè dla poszczególnych parametrów naszych metod testowych, na podstawie ich typów. KaĔdy punkt danych jest przekazywany za poĈrednictwem kaĔdego parametru tego samego typu. Takie rozwiñzanie stwarza pewne problemy, jeĈli stosujemy wiele parametrów tego samego typu. Jak siö za chwilö przekonamy, do ograniczania moĔliwych wartoĈci przypisywanych poszczególnym parametrom säuĔñ tzw. zaäoĔenia. Kolejnym krokiem jest zdefiniowanie wspomnianych zaäoĔeþ za pomocñ adnotacji @assumeThat. Stosujñc zaäoĔenia w ramach przypadku testowego wykorzystujñcego teoriö, moĔemy äatwo ograniczyè dane testowe, które bödñ uĔywane podczas wykonywania tego przypadku testowego. W poniĔszym przykäadzie ograniczamy zakres testów naszego przypadku do roku 2007 i dochodów z przedziaäu od 0 do 14 tys. zäotych: assumeThat(year, is(2007)); oraz assumeThat(income, both(greaterThan(0.00)).and(lessThan(14000.00))); Moduä rozszerzenia JUnitRunner wykonuje dany test dla wszystkich moĔliwych kombinacji punktów danych zgodnych z zaäoĔeniami, czyli w tym przypadku dla kombinacji staäej YEAR_2007 i staäych INCOME_2, INCOME_3 oraz INCOME_4: 10.8. Teorie we frameworku JUnit 4 _ 421 import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; import static org.junit.Assume.assumeThat; import java.math.BigDecimal; import org.junit.experimental.theories.DataPoint; import org.junit.experimental.theories.Theories; import org.junit.experimental.theories.Theory; import org.junit.runner.RunWith; @RunWith(Theories.class) public class TaxCalculatorTheoryTest { @DataPoint public static int YEAR_2007 = 2007; @DataPoint public static int YEAR_2008 = 2008; @DataPoint public static BigDecimal INCOME_1 = new BigDecimal(0.0); @DataPoint public static double INCOME_2 = 0.01; @DataPoint public static double INCOME_3 = 100.0; @DataPoint public static double INCOME_4 = 13999.99; @DataPoint public static double INCOME_5 = 14000.0; @SuppressWarnings( unchecked ) @Theory public void lowTaxRateIsNineteenPercent(int year, double income) { assumeThat(year, is(2007)); assumeThat(income, allOf(greaterThan(0.00),lessThan(14000.00))); TaxCalculator calculator = getTaxCalculator(); double calculatedTax = calculator.calculateIncomeTax(year, income); double expectedIncome = calculatedTax * 1000/195; assertThat(expectedIncome, closeTo(income,0.001)); System.out.println( Rok: + year + , Dochód: + income + , Podatek: + calculatedTax); } private TaxCalculator getTaxCalculator() { return new TaxCalculatorImpl(); } } W wyniku wykonania tego kodu otrzymamy nastöpujñce dane: Rok: 2007, Dochód: 0.01, Podatek: 0.0019500000000000001 Rok: 2007, Dochód: 100.0, Podatek: 19.5 Rok: 2007, Dochód: 13999.99, Podatek: 2729.99805 Dla uproszczenia wykorzystujemy wartoĈci typu double. W prawdziwej aplikacji biznesowej prawdopodobnie naleĔaäoby uĔyè typu gwarantujñcego wiökszñ precyzjö operacji na danych pieniöĔnych, czyli typu BigDecimal lub dedykowanej klasy Money. W razie niepowodzenia tego testu zostanie wyĈwietlony opisowy komunikat obejmujñcy szczegóäy punktów danych, które doprowadziäy do bäödu: org.junit.experimental.theories.internal.ParameterizedAssertionError: lowTaxRateIsNineteenPercent(2007, 0.01) Caused by: java.lang.AssertionError: Expected: is 0.01 Got: is 0.0 MoĔemy teraz dodaè do tego testu inne teorie, aby zweryfikowaè inne podzbiory naszych danych testowych. MoĔliwy zbiór punktów danych (po zastosowaniu zaäoĔeþ) jest stosowany osobno dla kaĔdej takiej teorii. 422 _ Rozdziaĥ 10. Testowanie kodu z wykorzystaniem frameworku JUnit 10.9. Stosowanie frameworku JUnit 4 w projektach Mavena 2 Maven 2 do wykonywania testów jednostkowych wykorzystuje moduä rozszerzenia Surefire (patrz podrozdziaä 2.13). Moduä rozszerzenia obsäuguje testy jednostkowe zarówno frameworku JUnit 3, jak i frameworku JUnit 4 — klasy testów muszñ siö znajdowaè w katalogu test, a Maven automatycznie je wykrywa i uruchamia. MoĔna nawet äñczyè testy frameworków JUnit 3 i JUnit 4 w ramach tej samej aplikacji. Testy jednostkowe wykonujemy dokäadnie tak samo jak pozostaäe testy Mavena, czyli za pomocñ polecenia mvn test: $ mvn test [INFO] Scanning for project
Pobierz darmowy fragment (pdf)

Gdzie kupić całą publikację:

Java. Praktyczne narzędzia
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ą: