Borland Developer Days 2004 2-3 czerwca 2004 Testowanie aplikacji Java Servlets Bartosz Walter mailto: Bartek.Walter@man.poznan.pl
Agenda Aplikacje Java Servlets TM Jak testować aplikacje internetowe? W małej skali, czyli testy jednostkowe Całymi funkcjami, czyli testy funkcjonalne Jednak API, czyli obiekty zastępcze Czy można mieć wszystko, czyli Cactus Testowanie aplikacji Java Servlets (c) Bartosz Walter 2
Serwlet i jego środowisko Żądanie Kontener GET /index.html HTTP/1.0 Serwlet <HTML> <HEAD> <BODY>... Odpowiedź Testowanie aplikacji Java Servlets (c) Bartosz Walter 3
Życie serwleta void init(servletconfig) Serwlet void doget(servletrequest, ServletResponse) void dopost(servletrequest, ServletResponse) void destroy() javax.servlet.http.httpservlet Testowanie aplikacji Java Servlets (c) Bartosz Walter 4
Serwlet podatkowy dochód: 100 podatek: 0 19% 30% dochód : 1000 podatek: 89,28 40% dochód : -100 podatek: 0 dochód : xxx Niepoprawna liczba Przeglądarka GET /index.html HTTP/1.0 200 HTTP/1.0 OK Aplikacja Testowanie aplikacji Java Servlets (c) Bartosz Walter 5
Agenda Aplikacje Java Servlets TM Jak testować aplikacje internetowe? W małej skali, czyli testy jednostkowe Całymi funkcjami, czyli testy funkcjonalne Jednak API, czyli obiekty zastępcze Czy można mieć wszystko, czyli Cactus Testowanie aplikacji Java Servlets (c) Bartosz Walter 6
Testowanie aplikacji internetowych Co jest obiektem testowania? Pojedyncze obiekty aplikacji if (request.getparameter("income")... Testowanie aplikacji Java Servlets (c) Bartosz Walter 7
Testowanie aplikacji internetowych Co jest obiektem testowania? Pojedyncze obiekty aplikacji Aplikacja jako całość <P>Podatek: 89,28</P> HTTP Testowanie aplikacji Java Servlets (c) Bartosz Walter 8
Przypadek testowy xunit void setup() TestCase void testxxxx() void testxxxx() void testxxxx() void testxxxx() void teardown() junit.framework.testcase Testowanie aplikacji Java Servlets (c) Bartosz Walter 9
Klasa i jej przypadek testowy Utworzenie instancji klasy Student Student.java + getname() + getage() + computelevel() StudentTest.java Student student + setup() + testgetname() + testgetage() + testcomputelevel() + teardown() Usunięcie instancji klasy Student Testowanie aplikacji Java Servlets (c) Bartosz Walter 10
Testowanie jednostkowe metody Student student = null; void setup() public void setup() { student = new Student(); student.setage(20); student.setname( Janek ); } void testgetage() void teardown() public void testwiek() throws Exception { int age = student.getage(); } assertequals(age, 20); public void teardown() { student = null; } Testowanie aplikacji Java Servlets (c) Bartosz Walter 11
Testowanie jednostkowe aplikacji internetowych void testdoget() testdoget(request, response){...???... } testdopost(request, response){ void testdopost() }...???... testcomputetax(int income) { void testcomputetax() } int tax = computetax(100); assertequals(0, tax); Testowanie aplikacji Java Servlets (c) Bartosz Walter 12
Testowanie jednostkowe aplikacji internetowych void testdoget() brak żądania i odpowiedzi void testdopost() brak żądania i odpowiedzi testcomputetax(int income) { void testcomputetax() } int tax = computetax(100); assertequals(0, tax); Testowanie aplikacji Java Servlets (c) Bartosz Walter 13
Agenda Aplikacje Java Servlets TM Jak testować aplikacje internetowe? W małej skali, czyli testy jednostkowe Całymi funkcjami, czyli testy funkcjonalne Jednak API, czyli obiekty zastępcze Czy można mieć wszystko, czyli Cactus Testowanie aplikacji Java Servlets (c) Bartosz Walter 14
Perspektywa użytkownika: testowanie funkcjonalne PHP perl ASP GET /index.html HTTP/1.0 Przeglądarka 200 HTTP/1.0 OK Serwer Java Servlets Przeglądarka ma dostęp jedynie do protokołu HTTP Testowanie aplikacji Java Servlets (c) Bartosz Walter 15
Perspektywa użytkownika: testowanie funkcjonalne HttpUnit PHP perl ASP GET /index.html HTTP/1.0 Serwer 200 HTTP/1.0 OK Zamiast testera z przeglądarką użyjmy automatu... Java Servlets Testowanie aplikacji Java Servlets (c) Bartosz Walter 16
Architektura HttpUnit i jwebunit Żądanie TestCase Odpowiedź Klient HTTP Parser HTML HTML Web Server Testowanie aplikacji Java Servlets (c) Bartosz Walter 17
Przypadek testowy jwebunit Klient Wskazanie adresu aplikacji StudentTest.java + setup() + testxxx() + teardown() gettestcontext().setbaseurl(baseurl) beginat(specificurl); Testowanie aplikacji Java Servlets (c) Bartosz Walter 18
Przypadek testowy jwebunit Klient Nawigacja i asercje StudentTest.java + setup() + testxxx() + teardown() clicklinkwithtext("formularz"); setformelement("id", "12345"); click(); asserttextpresent("wiek: 20 lat"); assertlinkwithtextpresent("powrót"); Testowanie aplikacji Java Servlets (c) Bartosz Walter 19
Nawigacja: Tabele WebTable[] gettables() table.getcellastext(row, col) HTML ala 34 table.getrowcount() table.getcolumncount() Testowanie aplikacji Java Servlets (c) Bartosz Walter 20
Nawigacja: Linki WebLink getlinkwithtext () link.click() HTML Do formularza link.mouseover() Testowanie aplikacji Java Servlets (c) Bartosz Walter 21
Nawigacja: Formularze WebForms[] getforms() form.getmethod() HTML Imię: Wyślij form.submit() form.getaction() Testowanie aplikacji Java Servlets (c) Bartosz Walter 22
Asercje jwebunit FORMULARZE OGÓLNE assertframepresent (ID) assertwindowpresent (ID) assertformpresent (ID) asserttitleequals(oczekiwany) assertformelementpresent (ID) asserttextpresent(tekst) assertformelementpresentwithlabel(etykieta) TABELE assertlinkpresent(id) assertformelementequals(oczekiwany, asserttablepresent faktyczny) (ID) assertlinkpresentwithtext(id) assertcheckboxselected(id) asserttableequals(id, tabela[][]) assertlinkpresentwithimage(id) assertbuttonpresent(id) asserttextintable (ID, tekst) assertradiooptionpresent(id) asserttablerowsequal(id, wierszpoczątkowy, oczekiwana) assertoptionsequal(nazwa, wzorce[]) Testowanie aplikacji Java Servlets (c) Bartosz Walter 23
Przykład: serwlet podatkowy Testowanie aplikacji Java Servlets (c) Bartosz Walter 24
Agenda Aplikacje Java Servlets TM Jak testować aplikacje internetowe? W małej skali, czyli testy jednostkowe Całymi funkcjami, czyli testy funkcjonalne Jednak API, czyli obiekty zastępcze Czy można mieć wszystko, czyli Cactus Testowanie aplikacji Java Servlets (c) Bartosz Walter 25
Architektura testów z wykorzystaniem Mock Objects Żądanie HTTP Client HTML HttpUnit Serwlet Odpowiedź Testowanie aplikacji Java Servlets (c) Bartosz Walter 26
Architektura testów z wykorzystaniem Mock Objects Żądanie HTTP Client HTML HttpUnit Serwlet Odpowiedź Testowanie aplikacji Java Servlets (c) Bartosz Walter 27
Obiekty zastępcze Obiekt zastępczy (mock object) naśladuje obiekt, który zastępuje posiada minimalną funkcjonalność obserwuje w jaki sposób inne obiekty wywołują jego metody porównuje faktyczne zachowanie z oczekiwanym source: www.mockobjects.com Testowanie aplikacji Java Servlets (c) Bartosz Walter 28
Wykorzystanie obiektu zastępczego 1. Utwórz instancje obiektów zastępczych 2. Ustaw wartości parametrów tych obiektów 3. Zdefiniuj oczekiwane zachowanie obiektów na nich operujących 4. Wywołaj testowany kod przekazując obiekty zastępcze jako parametry 5. Zweryfikuj spójność obiektów zastępczych Testowanie aplikacji Java Servlets (c) Bartosz Walter 29
Obiekty zastępcze: inicjalizacja MockHttpServletRequest mockrequest = null; MockHttpServletResponse mockresponse = null; MockServletConfig mockconfig = null; MyServlet servlet = null; public void setup() { mockrequest = new MockHttpServletRequest(); mockresponse = new MockHttpServletResponse(); mockconfig = new MockServletConfig(); servlet = new MyServlet(); } Testowanie aplikacji Java Servlets (c) Bartosz Walter 30
Obiekty zastępcze: test public void testxxx() { mockrequest.setupaddparameter("imie", "Ala"); mockrequest.setupaddparameter("wiek", "34"); mockrequest.setexpectedattribute("loggedin", "true"); mockresponse.setexpectedoutput( "<html><head/><body>a GET request</body></html>"); servlet.init(mockconfig); servlet.doget(mockrequest, mockresponse); } assertequals("atrybut nie został ustawiony", "true", mockrequest.getattribute("loggedin")); mockrequest.verify(); mockresponse.verify(); Testowanie aplikacji Java Servlets (c) Bartosz Walter 31
Weryfikacja wyników Asercje sprawdzają, czy testowane obiekty dają spodziewane wyniki Weryfikacje sprawdzają, czy testowane obiekty poprawnie porozumiewają się z obiektami zastępczymi liczba wywołań metod obecność parametru, atrybutu, sesji etc. Testowanie aplikacji Java Servlets (c) Bartosz Walter 32
Obiekty zastępcze: test public void testxxx() { mockrequest.setupaddparameter("imie", "Ala"); mockrequest.setupaddparameter("wiek", "34"); mockrequest.setexpectedattribute("loggedin", "true"); mockresponse.setexpectedoutput( "<html><head/><body>a GET request</body></html>"); servlet.init(mockconfig); servlet.doget(mockrequest, mockresponse); } assertequals("atrybut nie został ustawiony", "true", mockrequest.getattribute("loggedin")); mockrequest.verify(); mockresponse.verify(); Testowanie aplikacji Java Servlets (c) Bartosz Walter 33
Przykład: serwlet podatkowy Testowanie aplikacji Java Servlets (c) Bartosz Walter 34
Agenda Aplikacje Java Servlets TM Jak testować aplikacje internetowe? W małej skali, czyli testy jednostkowe Całymi funkcjami, czyli testy funkcjonalne Jednak API, czyli obiekty zastępcze Czy można mieć wszystko, czyli Cactus Testowanie aplikacji Java Servlets (c) Bartosz Walter 35
Architektura testów Cactusa Klient TestXXX Żądanie Odpowiedź Klient HTTP Parser HTML GET /index.html HTTP/1.0 200 HTTP/1.0 OK Testowanie aplikacji Java Servlets (c) Bartosz Walter 36
Architektura testów Cactusa Serwer Żądanie TestXXX GET /index.html HTTP/1.0 200 HTTP/1.0 OK Proxy Serwlet Odpowiedź Testowanie aplikacji Java Servlets (c) Bartosz Walter 37
Przypadek testowy Cactusa Klient YYYTest.java + beginxxx() + setup() + testxxx() + teardown() + endxxx() Serwer YYYTest.java + beginxxx() + setup() + testxxx() + teardown() + endxxx() Testowanie aplikacji Java Servlets (c) Bartosz Walter 38
Przypadek testowy Cactusa Klient konfiguracja połączenia HTTP definicje parametrów, nagłówków, cookies, sesji YYYTest.java + beginxxx() + setup() + testxxx() + teardown() + endxxx() obsługa autentykacji HTTP void beginxxx(webrequest request) { request.addparameter("income", "100"); request.addheader("naglowek", "brak"); request.addcookie("id", 1234); } Testowanie aplikacji Java Servlets (c) Bartosz Walter 39
Przypadek testowy Cactusa inicjacja środowiska testowego Serwer utworzenie obiektów wymaganych przez test dostęp do wybranych obiektów: request, response, config, session ServletContext context = null; void setup() { } context = config.getservletcontext() session.setattribute("loggedin", "true"); YYYTest.java + beginxxx() + setup() + testxxx() + teardown() + endxxx() Testowanie aplikacji Java Servlets (c) Bartosz Walter 40
Przypadek testowy Cactusa utworzenie testowanego obiektu wykonanie metody testowanego obiektu Serwer weryfikacja wyników dostęp do wybranych obiektów: request, response, config, session void testxxx() { } MojSerwlet srv = new MojServlet(); srv.dopost(request, response); assertequals("true", session. getattribute("loggedin")); YYYTest.java + beginxxx() + setup() + testxxx() + teardown() + endxxx() Testowanie aplikacji Java Servlets (c) Bartosz Walter 41
Przypadek testowy Cactusa Serwer usunięcie środowiska testowego dostęp do wybranych obiektów: request, response, config, session ServletContext context = null; void teardown() { } session.removeattribute("loggedin"); context = null; YYYTest.java + beginxxx() + setup() + testxxx() + teardown() + endxxx() Testowanie aplikacji Java Servlets (c) Bartosz Walter 42
Przypadek testowy Cactusa Klient org.apache.cactus.webresponse com.meterware.httpunit.webresponse weryfikacja wyników po stronie klienta YYYTest.java + beginxxx() + setup() + testxxx() + teardown() + endxxx() zakończenie transakcji void endxxx(webresponse response) { } assertequals("brak", response. getconnection().getheaderfield( "naglowek")); assertequals("1234", response.getcookie ("id")); Testowanie aplikacji Java Servlets (c) Bartosz Walter 43
Przykład: serwlet podatkowy Testowanie aplikacji Java Servlets (c) Bartosz Walter 44
Porównanie metod testowania Testy funkcjonalne niezależne od technologii wykonania aplikacji powolne w wykonaniu gruboziarniste Testy z wykorzystaniem obiektów zastępczych bardzo szybkie w wykonaniu, uciążliwe w implementacji drobnoziarniste Testy hybrydowe powolne w wykonaniu ziarnistość zależy od implementacji kompletne Testowanie aplikacji Java Servlets (c) Bartosz Walter 45
Podsumowanie Aplikacje internetowe można testować na różne sposoby Testy uzupełniają się, a nie wykluczają Różne testy różny nakład pracy Testowanie aplikacji Java Servlets (c) Bartosz Walter 46
Readings 1. JUnit, http://www.junit.org/ 2. JWebUnit, http://jwebunit.sf.net/ 3. HttpUnit, http://httpunit.sf.net/ 4. Endo-Testing. Unit Testing with Mock Objects, http://www.mockobjects.com/wiki/ MocksObjectsPaper?action=AttachFile&do=get &target=mockobjects.pdf 5. MockObjects, http://mockobjects.sf.net/ 6. Jakarta-Cactus, http://jakarta.apache.org/catus/ Testowanie aplikacji Java Servlets (c) Bartosz Walter 47
Q & A Testowanie aplikacji Java Servlets (c) Bartosz Walter 48