wiki:ohj2ComTest
Last modified 5 months ago Last modified on 2017-01-13 21:08:31

























































ComTest ja Ohjelmointi 2 -kurssi

ComTest on lähtöisin alun perin Vesa Lappalaisen ideasta, että yksikkötestauksen pitäisi olla mahdollisimman helppoa ja vaivatonta. Projekti on tällä hetkellä siinä vaiheessa, että Eclipse Pluginilla voidaan luoda ja ajaa kohtuullisella vaivalla testejä. Eclipse ei kuitenkaan tällä hetkellä ymmärrä testien syntaksia ja tämä hieman vaikeuttaa testien kirjoittamista. Ennen pluginin suurempaa hiomista pitää kuitenkin varmistaa perusajatuksen toimivuus.

Tärkeää ComTestissä on yksikkötestaamisen lisäksi se, että siitä saa myös hyvän dokumentaation metodien toiminnasta (ks: Mjonot-dokumentaatio). Lisäksi helppokäyttöisten testien avulla voi mukavasti määritellä itselleen esimerkiksi metodin rajapinnan.

Käyttöesimerkki

Asentaminen kotikoneeseen

Asentaminen mikroluokassa

  1. Tarkista ensin toimiiko ComTest: Java tiedoston päällä paina hiiren oikeata nappia
  2. Jos ComTest näkyy, niin asia on kunnossa.

Ongelmatapauksissa

  • Ongelmatapauksissa katso ensin: ComTestin ongelmia-kohdasta
  • Mainittu Eclipsen configuraatiohakemiston on mikroluokissa u:\config\eclipse (eli jos tulee suuria ongelmia, sammuta Eclipse, poista tämä hakemisto, käynnistä Eclipse uudelleen)

Peruskäyttö

  • Testien hyvän toiminnan kannalta Java-tiedostot kannattaa kirjoittaa paketteihin (ei default package, aloita siis aina luomalla src-hakemiston alle työtäsi kuvaava paketti)
  • ÄLÄ käytä tiedostojen ja pakettien yms. nimissä SKANDEJA (ä,ö,å). Tulee siis ongelmia jos pakettisi nimi on tehtäviä, vaihda siis tällaiset nimet muotoon tehtavia
  • Jos haluat testien menevän eri hakemistoon (isoissa projekteissa tapana), laita Java-tiedostosi hakemistoon tai sen yläpuoliseen hakemistoon tiedosto ComTest.ini jonka sisältö on:
    #BEFORETESTCLASS= @SuppressWarnings("all")
    #DIRECTORY=test
    #PACKAGE=.test  
    
  • Mene sen aliohjelman JavaDoc kommentteihin, jota haluat testata
  • Tee loppuun yksi tyhjä rivi (siis sellainen jossa on * alussa)
  • Kirjoita comtest ja paina Ctrl-Space (katso CtrlSpaceEiToimi). Jos tulee paljon valintoja, niin valitse ComTest Example
  • Sinulle pitäisi tulla tyhjä "raami":
       * @example
       * <pre name="test">
       * 
       * </pre>
    
  • Tähän raamiin kirjoitetaan testi. Esimerkiksi:
       * @example
       * <pre name="test">
       *   poista("Catcat"   ,"at")  ===  "Cc";
       *   poista("Paatti"   ,"at")  ===  "Pi";
       *   poista("Puatit"   ,"at")  ===  "Puit";
       * </pre>
    
  • Voi käyttää myös tarvittaessa esim: #import fi.jyu.mit.ohj2.*;
  • Tallenna työsi ennen testien generoimista ja ajamista.
  • Muista lisätä JUnit 4 projektiisi (menusta: Project/Properties/Java Build Path/Add Library/JUnit/JUnit 4 Finish )
  • Paina hiiren oikeata nappia ja valitse ComTest/Generate, Run JUnit
  • Jos tulee käännösvirheitä, avaa syntynyt testi-ohjelma ja koeta keksiä virheen syy.
  • Jos tulee ajossa ilmoitus väärästä tuloksesta, niin mieti onko väärin testi vai toteutus. Korjaa.
  • Jos testi on sisennetty, JUnit ei välttämättä osaa poistaa sisennystä, vaan etsii esim aliohjelmaa " hypotenuusa()".

Kaikkien testien ajaminen kerralla

Harjoitustyön tekemisen yhteydessä kaikkien tiedostojen testaaminen yksitellen voi olla hidasta. Voit ajaa kaikki ComTest-testit kerralla seuraavasti:

  • Valitse Package Explorerista ne tiedostot, jotka haluat testata. Jos esim. haluat testata jonkun paketin kaikki tiedostot, niin klikkaa paketin ylimmäistä tiedostoa, Shift pohjaan ja klikkaa alimmaista tiedostoa.
  • Klikkaa hiiren oikeaa ja ComTest -> Generate tests.
  • Valitse generoidut testitiedostot (yleensä riittää valita paketti, jossa ne sijaitsevat) ja klikkaa hiiren oikeaa -> Run As -> JUnit Test.

Hieman edistyneempi käyttö

  • Reaalilukuja testataan seuraavasti:
       * @example
       * <pre name="test">
       * #TOLERANCE=0.01    // Määrää vertailun tarkkuuden
       * hypotenuusa(0,0) ~~~ 0.0;
       * hypotenuusa(0,1) ~~~ 1.0;
       * hypotenuusa(1,1) ~~~ 1.41;
       * hypotenuusa(1,2) ~~~ 2.24;
       * hypotenuusa(5,6) ~~~ 7.81;
       * </pre>
    
  • Jos halutaan merkkijonoista "epämääräisyyksiä", käytetään Regular Expressionia:
       * @example
       * <pre name="test">
       * Henkilo2 hlo = new Henkilo2("Aku","Ankka",1934);
       * hlo.toString() =R= "Aku.*";   // Ensin pitää lukea Aku ja sitten saa olla mitä kirjainta (.) tahansa kuinka monta tahansa (*)
       * </pre>
    
  • Muista että reg expin kanssa voi joutua laittamaan\-viivoja useampia, jotta ne saa menemään "mätserille" saakka. Esimerkiksi:
       * @example
       * <pre name="test">
       * "kissa\n" =R= "kissa\\s";  // \s olisi reg.expin "tyhjä merkki", mutta Java syö \:n pois joten tarvii olla \\
       * </pre>
    

Taulukoiden testaaminen

Esimerkki taulukon sisällön testaamisesta

	/**
	 * Käännetään taulukon alkiot päinvastaiseen järjestykseen
	 * @param t taulukko jonka alkiot käännetään
	 * @example
	 * <pre name="test">
	 * #import java.util.Arrays;
	 *    int[] t = {2, 32, 76, 62, 31, 86};
	 *    kaanna(t); 
	 *    Arrays.toString(t) === "[86, 31, 62, 76, 32, 2]";
	 * </pre>
	 */

Esimerkki taulukon luomisesta kutsussa:

	/**
	 * Lasketaan yhteen taulukon kaikki luvut
	 * @param t taulukko jonka luvut lasketaan 
	 * @return lukujen summa
	 * @example
	 * <pre name="test">
	 *   int[] t = {1,2,3,4,5,6};
	 *   summa(t) === 21;
	 *   summa(new int[]{1,1,1,1,1,1}) === 6;
	 * </pre>
	 */

Huom! Kutsuun kirjoitettu 2-ulotteisen taulukkon luominen ei toistaiseksi toimi. 2-ulotteiset taulukot pitää toistaiseksi luoda apumuuttujaan.

Taulukkomuotoinen testaaminen

  • Opettele myös taulukkomuotoinen testaaminen, se vähentää monesti kirjoittamista.
  • Esimerkki kurssin Ali-paketista:
       * @example
       * <pre name="testTayta">
       * tayta($jono,$n) === $tulos
       * 
       *    $jono   | $n | $tulos
       *  -------------------------------
       *    "kissa" |  3 | "kissakissakissa"
       *    ""      | 10 | ""
       *    "kissa" |  0 | ""     
       *    "kissa" |  1 | "kissa"
       *    "a"     | 10 | "aaaaaaaaaa"     
       * </pre>
    
    • Lyhyesti: dollarimerkki ($) merkitsee muuttujia, viivamerkit (-----..) ovat koristeita, putkimerkit (|) erottelevat muuttujia ja niiden arvoja.
  • Katso lisää esimerkkejä esim: kurssin Ali-paketista ja erityisesti Mjonot.java.

StringBuilder

StringBuilderin ongelma on se, että sen yhtäsuuruusvertailu palauttaa String-olion kanssa aina false.

Siksi vertailu pitää tehdä niin, että muutetaan StringBuilder-olio ensin merkkijonoksi:

   * @example
   * <pre name="test">
   * StringBuilder jono = new StringBuilder("Kissa");
   * jono === "Kissa";  // EI TOIMI
   * jono.toString() === "Kissa"; // TOIMII 
   * </pre>

Asiaa hankaloittaa vielä se, että StringBuilder-luokassa ei ole ylikirjoitettua equals-metodia ja siksi kahden StringBuilder-tyyppisen olion vertaaminen ei onnistu vaan molemmat pitää muuttaa ensin merkkijonoksi,

OutputStreamin testaaminen

  • Funktio, jolle viedään parametrina OutputStream. Esimerkiksi:
        public void tulosta(OutputStream os) {
            PrintStream out = new PrintStream(os);
            out.println("Tulostetaan jotain");
        }
    
  • Tätä kutsutaan
      tulosta(System.out);
    
  • Testaus voidaan tehdä seuraavasti:
         * <pre name="test">
         * #import java.io.ByteArrayOutputStream;
         * ByteArrayOutputStream outContent = new ByteArrayOutputStream();
         * Henkilo hlo = new Henkilo("Antti","Virtanen", 30);
         * hlo.tulosta(outContent);
         * outContent.toString() === "Antti Virtanen, 30v\r\n"; // Varoitus: Kaikissa järjestelemissä ei ole sama rivin loppu!
    
  • Huom! outContent.toString antaa myös rivinerotinmerkin, kun siihen on ne tulostettu. Vertaillessa ne pistää poistaa tai lisätään vertailutekstiin \r\n kuten yllä.
  • \r\n sijaan olisi hyvä käyttää System.getProperty("line.separator")-kutsun antamaa merkkiä, joka antaa kulloisenkin järjestelmän rivierottimen.

Vanhat ComTestin versiot

  • Uudet ComTest-versiot, 1.06:sta asti eivät tarvitse alla olevia
  • Lisää johonkin kohti vielä kommentteihin tällaisen testin tapauksessa
     // #STATICIMPORT  
    
    jotta kääntäjä osaa käyttää poista-metodia oikeasta luokasta ilman viitettä luokkaan. Huom! Kommenttimerkin ja #:n välissä saa olla korkeintaan yksi välilyönti ja sen on oltava välilyönti. JavaDoc kommentteihin kirjoitettuna *-merkin perään taas ei saa olla noita -merkkejä ettei tule sisäkkäisiä kommentteja. Toki voit kirjoittaa testeissä myös:
       *   Poista.poista("Catcat"   ,"at")  ===  "Cc";
    
    mutta #STATICIMPORT-rivin ansiosta luokkaa ei ole pakko mainita testeissä.
  • Toinen usein tarvittava import voi olla #CLASSIMPORT, jolloin luokka lisätään import-lauseeseen.

Dokumentti ei tule tai se on sekaisin

Seuraavasta voi olla apua mikäli tuntuu ettei dokumentaatioon tule jostakin metodista dokumenttia tai dokumentti on testien esimerkkien osalta sekaisin.

Doxygen on se ohjelma, jolla tehdään TIMissä dokumentaatio doukmenttikommenttien (/**) pohjalta.

Doxygenissä on sellainen "inhoittava" ominaisuus, että jos siellä pre-lohkossa on tyhjiä rivejä, niin ne helposti katkaisevat sen pre-lohkon.

Lisäksi ----------- rivi muuttaa edellisen rivin otsikoksi.

Ja mikäli ~~~ yhdistelmiä on pariton määrä, ei tule koko dokumenttia ko. aliohjelmasta.

Korjaus:

1) pidä huoli että kommenttilohkossa on parillinen määrä ~~~ yhdistelmiä. Lisää vaikka kommentti rivinloppuun ~~~ tai lisää yksi testi, jotta noita tulee parillinen määrä

2) Pistä tyhjien rivien alkuun (tai loppuun) kommenttimerkki

3) jos käytät <pre>-lohkossa ------, niin pistä perään kommentti tyyliin ------- //

Eli esimerkiksi:

     * <pre name="test">
     * suurinKirjeenPainoIf($rahaa) ~~~ $paino; // ~~~
     *                                          //
     *   $rahaa | $paino
     * ------------------- //
     *    10.00 | 2000
     *     3.60 | 1000
     *     3.50 | 1000
     *     3.40 |  500
     *     0.50 |    0
     * </pre>

Toinen mahdollisuus on lisätä @code ja @endcode tägit:

     * @example
     * @code
     * <pre name="test">
     * suurinKirjeenPainoIf($rahaa) ~~~ $paino;  
     *                                           
     *   $rahaa | $paino
     * -------------------  
     *    10.00 | 2000
     *     3.60 | 1000
     *     3.50 | 1000
     *     3.40 |  500
     *     0.50 |    0
     * </pre>
     * @endcode