Nástroje jednotkového testování
              seminář IBA CZ




                          Jakub Holý, 4/2010




1                                       © 2010 IBA CZ, s.r.o.
Obsah

    O čem si povíme...
         Jednotkové testování pro vývojáře
                proč
                jak
                nástroje


    ...a o čem nikoliv
            Místo jednotkového testování ve vývojovém
             cyklu (CI servery apod.)
           Jiné typy testování, jako funkční (Selenium aj.) a
            integrační (až na výjimky)




2                                                  © 2010 IBA CZ, s.r.o.
Díl 1: Co a proč?




3                       © 2010 IBA CZ, s.r.o.
Kvíz




    Jaký je nejefektivnější způsob odhalení chyb v kódu?
     a) Jednotkové testování
     b) Testování aplikace testovacím týmem
     c) Statická analýza kódu – FindBugs ap.
     d) Jiný?




                                                   Odpověď: Revize kódu


4                                               © 2010 IBA CZ, s.r.o.
Kvíz II




    Kdo někdy napsal jednotkový test s JUnit či podobnou?

    Kdo někdy použil pomocnou knihovnu pro testování ve
      specifickém prostředí nebo specifické datové
      struktury?
      (JSFUnit, XmlUnit, DbUnit, mocky, ...)




                                                  Odpověď: Revize kódu


5                                              © 2010 IBA CZ, s.r.o.
Překážky na cestě k testovacímu satori1

    Všichni víme, jak jsou testy důležité, ale nikdo to nedělá.
       Proč?
        
            Není čas (opravdu? šetří později, stojí jen 10%2)
                 Moc práce
                 Neví jak




    1)
         Zenový výraz pro stav dokonalého štěstí, volně řečeno
    2)
         Viz článek Cost of Testing: http://java.dzone.com/articles/cost-testing

6                                                                         © 2010 IBA CZ, s.r.o.
Drobné opakování...




7                         © 2010 IBA CZ, s.r.o.
Proč testovat?

    1. Nutí psát testovatelný a tedy lepší kód
          Koheze: Malé metody/třídy dělající jedinou věc
              Loose coupling (↔ DI; setDependency(..) -
               Google)
              Konfigurovatelnost (JDBC URL apod.)
       ➔       Flexibilní, hezčí, samostatný


    2. Včas najdeme chyby – čím dřív, tím levněji
               Př.: 12 x 24h čas, MobileBackup.LineReader


    3. Zlevňuje údržbu ← bezpečný refactoring




8                                                      © 2010 IBA CZ, s.r.o.
Typy testování

          Testování funkce:
            –   Vývojář: jednotkové x funkční x scenario
                (behavior) driven x integrační
            –   Uživatel: akceptační (FITT, ...)
          NFR: výkonové (stress a load)




9                                                     © 2010 IBA CZ, s.r.o.
Co a jak testovat

     Co testovat?
     Viz dřívější přednáška Petra Adámka.
             očekávané chování
             chování při nesplnění předpokladů → vede na:
               –   explicitní vyjádření předpokladů v kódu
               –   zajištění, že pokud byly mylné a nebudou tedy
                   splněny, aplikace to včas detekuje a dá
                   srozumitelně vědět → ušetřím hodiny/dny
                   zkoumání nečekaného chování
     Jak testovat?
     Pragmaticky!
             Nenechat se zaslepit pravidly – viz The Way of
              Testuvius [WoT]
             Bohužel ne vše lze otestovat
             100% pokrytí je nesmysl (gettery ap.?!)
             Paretovo pravidlo: posledních 20% je 80% práce
             Použít vždy ten pravý nástroj pro daný úkol
10                                                       © 2010 IBA CZ, s.r.o.
Díl 2: Usnadňujeme si práci




11                             © 2010 IBA CZ, s.r.o.
Základy jednotkového testování

                                    Frameworky: JUnit 3.8/4.x (lepší integrace
                                     všude) vs. TestNG (mocnější?)
                                      –   spouštění testů, výsledky, verifikace hodnot
                                      –   JUnit 4: Parametrizované testy
                                      –   JUnit 4.4: assertThat a fluent API s Hamcrestem
                                      –   prostředí: Java 5 x 1.4 x 1.4 s retroweaverem
                                    O podpoře tvorby a spouštění v IDE ...
                                    Show: Ukázka reálného kódu
                                      –   demonstrace užití a přínosu
                                      –   testing-seminar-junit/ITaxServiceTest, viz
                                          poznámky
                                    Pozn.: Že testy prošly neznamená že vše ok,
     Eclipse: JUnit runner           možná jsou jen nedostatečné!




12                                                                              © 2010 IBA CZ, s.r.o.
Co se závislostmi? (I)

     Simulujeme čili mock-ujeme
        = „náhrada předprogramovaným simulantem“
         Mockito, JMock, EasyMock
         PowerMock pro E.M./Mockito (statické m.,..)
         Groovy Gmock
         AOP




                       Simul-sestřička




13                                              © 2010 IBA CZ, s.r.o.
Co se závislostmi? (II)

     Závislosti na prostředí
           Databáze: DbUnit (a DbUnitTestSkeleton)
            Servlety: Cactus (používá JUnit 3.8.1, prý
             nefunguje s 4), Spring MockHttpServletRequest
            EJB: embeddable OpenEJB, JBoss embedded,
             EJB 3.1: embedded container
            Portlety: ?
            Web UI: ?HttpUnit, WebUnit...?, JSFUnit (nad
             Cactusem :-( ) x JBoss jsf-mock
     Závěr: Vždy se podívejte, zda neexistuje pomocná
     knihovna pro testování ve vašem prostředí.




14                                               © 2010 IBA CZ, s.r.o.
Mockito a proč si je zvolit

                         Snadnost užití – specifikujte jen co chcete
                             Jinde musíte předem specifikovat povolená volání
                             Mockuje rozhraní i třídy
                         Malé, dobře dokumentované, hezké API
 // Ukázka Mockita:
 l =                     Portováno i do Javy 1.4
 mock(List.class);
                         Pokročilé schopnosti
 when(l.get(0)).
  thenReturn(“X“);
                             Partial mocks

 assert l.get(0) ==
                             Spying on real objects
 “X“;                        Custom Answer callback
 assert l.get(1) ==
 null;                       Co vrací: RETURNS_SMART_NULLS,
                              RETURNS_DEEP_STUBS (zřetězení mocků), …
                         Rozumné výchozí chování & velmi přizpůsobitelný
                         Přečíst FAQ! (omezení, doporučení aj.)


15                                                                      © 2010 IBA CZ, s.r.o.
DbUnit a DbUnit Test Skeleton

                       1. DbUnit
                              Před každým testem naplní DB z dat v XML [← Jailer]
                       2. DbUnit Test Skeleton (dbunit-embeddedderby-parenttest)
                              Přednastaven pro vnořenou Derby DB => netřeba externí
                               DB; umí ji i vytvořit
                              Načte data z připraveného XML – stačí upravit
                              Užiteční pomocníci
                               (RowComparator, getDataSource(), ...)
                              Lepší zpracování chyb + rady jak řešit
                              V Central Maven repository
Kompletní (!) test:
public class MyDerbyDbTest {
 EmbeddedDbTester testDb = new EmbeddedDbTester();

 @Before void setUp() throws Exception { testDb.onSetup();}

 @Test public void testIt() throws Exception {
   new MyTestedClass().storeGeek(1, "Kuba Holy");
   testDb.createCheckerForSelect("select ...")
    .assertRowCount(1)
    .assertNext(new Object[]{ 1, "Kuba Holy"});
}}
// + .ddl, data v XML
16                                                                         © 2010 IBA CZ, s.r.o.
Groovy, jazyk testera

                          Co je Groovy?
                               Skriptovací jazyk, 99% Javy + mnoho navíc
                               Koupil Spring Source (dnes VMWare)
                               Odstraňuje ukecanost, usnadňuje práci, moduly


                          Pár ukázek
                                “““fakt dlouhý
     spock                          text“““
     specification fwrk
                                 Map m = [“klíč“:“hodnota“, …]
                                 def u = new User(
                                   name: “Jan“, věk: 18, muž: true)
                                 new File(“s.txt“).eachLine {
                                   assertEquals(“line${++cnt}“, it)}
                                 Moduly: GSQL, RE, XML, …
                                 Tvorba a srovnání objektových stromů
17                                                                   © 2010 IBA CZ, s.r.o.
Groovy Spock

                             testing and specification framework for Java and
                              Groovy
     spock
     specification fwrk      beautiful and highly expressive specification
                              language
                             has a JUnit runner → out-of-the-box IDE integration
                             perfect for data-driven tests
                             plus all the power of Groovy

                          def "maximum of two numbers"() {
                            expect:
                            Math.max(a, b) == c

                              where:
                              a | b |   c
                              3 | 7 |   7
                              5 | 4 |   5
                              9 | 9 |   9
                          }

18                                                                       © 2010 IBA CZ, s.r.o.
Neutříděný seznam nástrojů a knihoven

        Spring je velmi silný v testování jednotkovém i
         integračním (JPA,..): *.mock.jndi|web|portlet
        Unitils – integruje DbUnit, JPA, JMock aj.
         Vychytávky jako reflexivní porovnávač bean.
        Testy správnosti vícevláknových aplikací
            ConcuTest.org (2009, Java 1.4/5; testy dětí) viz notes
            IBM ConTest (2009, J.1.4/5; ovlivň. scheduler)
            MultithreadedTC (2007, ?; explic. scheduling)
        JEE a integrace: JBoss Arquillian
        NetBeans' Memory Leak Unit Test
        XmlUnit (porovnává XML)
        a mnoho dalších … → pravděpodobně už někde
         existuje ten nástroj, který potřebujete!



19                                                     © 2010 IBA CZ, s.r.o.
Pokročilá témata

     Test-Driven Development/Design (TDD)
       nejdřív test, pak kód, pak design (refactor)
        doplňuje se s akceptačním TDD
        zaměřuje pozornost na podstatné x předesignování


     Mutační testování (mutation testing)
        Kontrola kvality testů zavedením chyb do kódu
        Výzvou odstínění nepodstatných změn
            Př: compareTo vrátí -2 místo -1
        Výkonově náročné
        Viz framework Javalanche.org a MuJava
        Viz Beautiful Testing, O'Reilly 2010, kpt.18: Seeding
         Bugs to Find Bugs:Beautiful Mutation Testing
         (Andreas Zeller, David Schuler)


20                                                     © 2010 IBA CZ, s.r.o.
Odkazy

     Bibliografie
       [WoT] The Way of Testuvius:
        http://www.agitar.com/downloads/TheWayOfTestivus.
        pdf
        Odkazy z této prezentace: http://bit.ly/jhtstlinks

     Rozšiřující zdroje
         Google Talks by Misko Hevery
        pniederw.wordpress.com/category/spock-framework

     Knihy
       Martin Fowler: XUnit Test Patterns - Refactoring Test
        Code, 2008 - vzory a anti-vzory pro jednotkové testy
        Lasse Koskela: Test-Driven - Practical TDD and
         Acceptance TDD for Java Developers, Manning
         2008



21                                                    © 2010 IBA CZ, s.r.o.

Seminar Nastroje Jednotk Testovani

  • 1.
    Nástroje jednotkového testování seminář IBA CZ Jakub Holý, 4/2010 1 © 2010 IBA CZ, s.r.o.
  • 2.
    Obsah O čem si povíme...  Jednotkové testování pro vývojáře  proč  jak  nástroje ...a o čem nikoliv  Místo jednotkového testování ve vývojovém cyklu (CI servery apod.)  Jiné typy testování, jako funkční (Selenium aj.) a integrační (až na výjimky) 2 © 2010 IBA CZ, s.r.o.
  • 3.
    Díl 1: Coa proč? 3 © 2010 IBA CZ, s.r.o.
  • 4.
    Kvíz Jaký je nejefektivnější způsob odhalení chyb v kódu? a) Jednotkové testování b) Testování aplikace testovacím týmem c) Statická analýza kódu – FindBugs ap. d) Jiný? Odpověď: Revize kódu 4 © 2010 IBA CZ, s.r.o.
  • 5.
    Kvíz II Kdo někdy napsal jednotkový test s JUnit či podobnou? Kdo někdy použil pomocnou knihovnu pro testování ve specifickém prostředí nebo specifické datové struktury? (JSFUnit, XmlUnit, DbUnit, mocky, ...) Odpověď: Revize kódu 5 © 2010 IBA CZ, s.r.o.
  • 6.
    Překážky na cestěk testovacímu satori1 Všichni víme, jak jsou testy důležité, ale nikdo to nedělá. Proč?  Není čas (opravdu? šetří později, stojí jen 10%2)  Moc práce  Neví jak 1) Zenový výraz pro stav dokonalého štěstí, volně řečeno 2) Viz článek Cost of Testing: http://java.dzone.com/articles/cost-testing 6 © 2010 IBA CZ, s.r.o.
  • 7.
    Drobné opakování... 7 © 2010 IBA CZ, s.r.o.
  • 8.
    Proč testovat? 1. Nutí psát testovatelný a tedy lepší kód  Koheze: Malé metody/třídy dělající jedinou věc  Loose coupling (↔ DI; setDependency(..) - Google)  Konfigurovatelnost (JDBC URL apod.) ➔ Flexibilní, hezčí, samostatný 2. Včas najdeme chyby – čím dřív, tím levněji  Př.: 12 x 24h čas, MobileBackup.LineReader 3. Zlevňuje údržbu ← bezpečný refactoring 8 © 2010 IBA CZ, s.r.o.
  • 9.
    Typy testování  Testování funkce: – Vývojář: jednotkové x funkční x scenario (behavior) driven x integrační – Uživatel: akceptační (FITT, ...)  NFR: výkonové (stress a load) 9 © 2010 IBA CZ, s.r.o.
  • 10.
    Co a jaktestovat Co testovat? Viz dřívější přednáška Petra Adámka.  očekávané chování  chování při nesplnění předpokladů → vede na: – explicitní vyjádření předpokladů v kódu – zajištění, že pokud byly mylné a nebudou tedy splněny, aplikace to včas detekuje a dá srozumitelně vědět → ušetřím hodiny/dny zkoumání nečekaného chování Jak testovat? Pragmaticky!  Nenechat se zaslepit pravidly – viz The Way of Testuvius [WoT]  Bohužel ne vše lze otestovat  100% pokrytí je nesmysl (gettery ap.?!)  Paretovo pravidlo: posledních 20% je 80% práce  Použít vždy ten pravý nástroj pro daný úkol 10 © 2010 IBA CZ, s.r.o.
  • 11.
    Díl 2: Usnadňujemesi práci 11 © 2010 IBA CZ, s.r.o.
  • 12.
    Základy jednotkového testování  Frameworky: JUnit 3.8/4.x (lepší integrace všude) vs. TestNG (mocnější?) – spouštění testů, výsledky, verifikace hodnot – JUnit 4: Parametrizované testy – JUnit 4.4: assertThat a fluent API s Hamcrestem – prostředí: Java 5 x 1.4 x 1.4 s retroweaverem  O podpoře tvorby a spouštění v IDE ...  Show: Ukázka reálného kódu – demonstrace užití a přínosu – testing-seminar-junit/ITaxServiceTest, viz poznámky  Pozn.: Že testy prošly neznamená že vše ok, Eclipse: JUnit runner možná jsou jen nedostatečné! 12 © 2010 IBA CZ, s.r.o.
  • 13.
    Co se závislostmi?(I) Simulujeme čili mock-ujeme = „náhrada předprogramovaným simulantem“  Mockito, JMock, EasyMock  PowerMock pro E.M./Mockito (statické m.,..)  Groovy Gmock  AOP Simul-sestřička 13 © 2010 IBA CZ, s.r.o.
  • 14.
    Co se závislostmi?(II) Závislosti na prostředí  Databáze: DbUnit (a DbUnitTestSkeleton)  Servlety: Cactus (používá JUnit 3.8.1, prý nefunguje s 4), Spring MockHttpServletRequest  EJB: embeddable OpenEJB, JBoss embedded, EJB 3.1: embedded container  Portlety: ?  Web UI: ?HttpUnit, WebUnit...?, JSFUnit (nad Cactusem :-( ) x JBoss jsf-mock Závěr: Vždy se podívejte, zda neexistuje pomocná knihovna pro testování ve vašem prostředí. 14 © 2010 IBA CZ, s.r.o.
  • 15.
    Mockito a pročsi je zvolit  Snadnost užití – specifikujte jen co chcete  Jinde musíte předem specifikovat povolená volání  Mockuje rozhraní i třídy  Malé, dobře dokumentované, hezké API // Ukázka Mockita: l =  Portováno i do Javy 1.4 mock(List.class);  Pokročilé schopnosti when(l.get(0)). thenReturn(“X“);  Partial mocks assert l.get(0) ==  Spying on real objects “X“;  Custom Answer callback assert l.get(1) == null;  Co vrací: RETURNS_SMART_NULLS, RETURNS_DEEP_STUBS (zřetězení mocků), …  Rozumné výchozí chování & velmi přizpůsobitelný  Přečíst FAQ! (omezení, doporučení aj.) 15 © 2010 IBA CZ, s.r.o.
  • 16.
    DbUnit a DbUnitTest Skeleton 1. DbUnit  Před každým testem naplní DB z dat v XML [← Jailer] 2. DbUnit Test Skeleton (dbunit-embeddedderby-parenttest)  Přednastaven pro vnořenou Derby DB => netřeba externí DB; umí ji i vytvořit  Načte data z připraveného XML – stačí upravit  Užiteční pomocníci (RowComparator, getDataSource(), ...)  Lepší zpracování chyb + rady jak řešit  V Central Maven repository Kompletní (!) test: public class MyDerbyDbTest { EmbeddedDbTester testDb = new EmbeddedDbTester(); @Before void setUp() throws Exception { testDb.onSetup();} @Test public void testIt() throws Exception { new MyTestedClass().storeGeek(1, "Kuba Holy"); testDb.createCheckerForSelect("select ...") .assertRowCount(1) .assertNext(new Object[]{ 1, "Kuba Holy"}); }} // + .ddl, data v XML 16 © 2010 IBA CZ, s.r.o.
  • 17.
    Groovy, jazyk testera Co je Groovy?  Skriptovací jazyk, 99% Javy + mnoho navíc  Koupil Spring Source (dnes VMWare)  Odstraňuje ukecanost, usnadňuje práci, moduly Pár ukázek  “““fakt dlouhý spock text“““ specification fwrk  Map m = [“klíč“:“hodnota“, …]  def u = new User( name: “Jan“, věk: 18, muž: true)  new File(“s.txt“).eachLine { assertEquals(“line${++cnt}“, it)}  Moduly: GSQL, RE, XML, …  Tvorba a srovnání objektových stromů 17 © 2010 IBA CZ, s.r.o.
  • 18.
    Groovy Spock  testing and specification framework for Java and Groovy spock specification fwrk  beautiful and highly expressive specification language  has a JUnit runner → out-of-the-box IDE integration  perfect for data-driven tests  plus all the power of Groovy def "maximum of two numbers"() { expect: Math.max(a, b) == c where: a | b | c 3 | 7 | 7 5 | 4 | 5 9 | 9 | 9 } 18 © 2010 IBA CZ, s.r.o.
  • 19.
    Neutříděný seznam nástrojůa knihoven  Spring je velmi silný v testování jednotkovém i integračním (JPA,..): *.mock.jndi|web|portlet  Unitils – integruje DbUnit, JPA, JMock aj. Vychytávky jako reflexivní porovnávač bean.  Testy správnosti vícevláknových aplikací  ConcuTest.org (2009, Java 1.4/5; testy dětí) viz notes  IBM ConTest (2009, J.1.4/5; ovlivň. scheduler)  MultithreadedTC (2007, ?; explic. scheduling)  JEE a integrace: JBoss Arquillian  NetBeans' Memory Leak Unit Test  XmlUnit (porovnává XML)  a mnoho dalších … → pravděpodobně už někde existuje ten nástroj, který potřebujete! 19 © 2010 IBA CZ, s.r.o.
  • 20.
    Pokročilá témata Test-Driven Development/Design (TDD)  nejdřív test, pak kód, pak design (refactor)  doplňuje se s akceptačním TDD  zaměřuje pozornost na podstatné x předesignování Mutační testování (mutation testing)  Kontrola kvality testů zavedením chyb do kódu  Výzvou odstínění nepodstatných změn  Př: compareTo vrátí -2 místo -1  Výkonově náročné  Viz framework Javalanche.org a MuJava  Viz Beautiful Testing, O'Reilly 2010, kpt.18: Seeding Bugs to Find Bugs:Beautiful Mutation Testing (Andreas Zeller, David Schuler) 20 © 2010 IBA CZ, s.r.o.
  • 21.
    Odkazy Bibliografie  [WoT] The Way of Testuvius: http://www.agitar.com/downloads/TheWayOfTestivus. pdf  Odkazy z této prezentace: http://bit.ly/jhtstlinks Rozšiřující zdroje  Google Talks by Misko Hevery  pniederw.wordpress.com/category/spock-framework Knihy  Martin Fowler: XUnit Test Patterns - Refactoring Test Code, 2008 - vzory a anti-vzory pro jednotkové testy  Lasse Koskela: Test-Driven - Practical TDD and Acceptance TDD for Java Developers, Manning 2008 21 © 2010 IBA CZ, s.r.o.

Editor's Notes

  • #3 ITaxServiceTest 1. Postup Rozhraní -> test -> implementace 2. Zapamatovánihodnosti Stejný package, jiný adresář -> test/čti protected a package metody/atributy Bez anotací platný JUnit 3.x text dík pojmenování setUp() či @Before: (re)inicializace k provedení před každým testem Junit 4: @Test(expected=...) Dostupné assert* viz třída Assert - (Not)Null, True/False, Equals // JUnit by měla být přidána přes Maven
  • #5 ITaxServiceTest 1. Postup Rozhraní -> test -> implementace 2. Zapamatovánihodnosti Stejný package, jiný adresář -> test/čti protected a package metody/atributy Bez anotací platný JUnit 3.x text dík pojmenování setUp() či @Before: (re)inicializace k provedení před každým testem Junit 4: @Test(expected=...) Dostupné assert* viz třída Assert - (Not)Null, True/False, Equals // JUnit by měla být přidána přes Maven
  • #6 ITaxServiceTest 1. Postup Rozhraní -> test -> implementace 2. Zapamatovánihodnosti Stejný package, jiný adresář -> test/čti protected a package metody/atributy Bez anotací platný JUnit 3.x text dík pojmenování setUp() či @Before: (re)inicializace k provedení před každým testem Junit 4: @Test(expected=...) Dostupné assert* viz třída Assert - (Not)Null, True/False, Equals // JUnit by měla být přidána přes Maven
  • #7 ITaxServiceTest 1. Postup Rozhraní -> test -> implementace 2. Zapamatovánihodnosti Stejný package, jiný adresář -> test/čti protected a package metody/atributy Bez anotací platný JUnit 3.x text dík pojmenování setUp() či @Before: (re)inicializace k provedení před každým testem Junit 4: @Test(expected=...) Dostupné assert* viz třída Assert - (Not)Null, True/False, Equals // JUnit by měla být přidána přes Maven
  • #13 ITaxServiceTest 1. Postup Rozhraní -> test -> implementace 2. Zapamatováni hodnosti Stejný package, jiný adresář -> test/čti protected a package metody/atributy Bez anotací platný JUnit 3.x text dík pojmenování setUp() či @Before: (re)inicializace k provedení před každým testem Junit 4: @Test(expected=...) Dostupné assert* viz třída Assert - (Not)Null, True/False, Equals // JUnit by měla být přidána přes Maven
  • #20 ConcuTest (2009, Java 1.4/5): ConcJUnit: Upravený junit.jar, který navíc v dětských vláknech a) hlásí výjimky b) hlásí, když dítě přežije rodiče. Thread Checker: A lightweight annotation language, which can be used to specify and check the threading invariants of both existing and new code; Schedule-Based Execution: A testing framework that WILL execute unit tests according to a specified set of recorded or generated schedules, elevating the unit testing of concurrent programs to a rigorous, deterministic process.