**JUnit** on Java-ohjelmointikielelle suunniteltu testauskehys, jonka avulla voidaan kirjoittaa ja ajaa yksikkötestejä sekä tarkastella testien tuloksia. Se on avoimen lähdekoodin yksikkötestauskirjasto, jolle löytyy tuki lähes kaikista ohjelmointiympäristöistä. JUnit kuuluu xUnit-testauskehysperheeseen, joka on kehittynyt Kent Beckin vuonna 1998 Smalltalkille suunnitellusta SUnitista. Nykyään XUnit-kehyksiä on olemassa useimmille ohjelmointikielille ja kehitysalustoille. Vuonna 2002 ensi kertaa julkaistu JUnit nousi nopeasti kehittäjien suosioon ja nykyään sen on todettu olevan lähes synonyymi automatisoidulle Java-yksikkötestaukselle. JUnit-kirjaston nykyinen versio on 5 (Jupiter).

JUnit on keskeisellä tavalla vaikuttanut testikeskeisen ohjelmistokehitystavan kehitykseen (engl. Test-driven development). Testivetoinen ohjelmistokehitys perustuu ohjelman rakentamiseen pieni osa kerrallaan samalla testaten. Testivetoisessa ohjelmistokehityksessä ohjelman yksittäistä osaa tarkasteleva automaattinen testi kirjoitetaan tyypillisesti koodia ennen.

JUnit rakenne
-------------

JUnit perustuu testimetodeita sisältäviin testiluokkiin, joista yksi tai useampia voidaan suorittaa kerralla. Jokaisen testimetodin tulos ilmaistaan testin suorittamisen jälkeen joko onnistuneena tai epäonnistuneena. Testiluokat nimetään yleensä sen luokan nimellä, johon testi liittyy ja loppuun lisätään sana "Test".

JUnit-kirjaston annotaatiot lisätään testeissä suoritettaviin metodeihin seuraavan mukaisesti:

* @BeforeEach –suoritetaan ennen jokaista testitapausta
* @BeforeClass –suoritetaan ennen luokan ensimmäistä testiä
* @AfterEach –suoritetaan jokaisen testitapauksen jälkeen
* @AfterClass – tehdään lopuksi, kun kaikki luokan testitapaukset suoritettu
* @Test –yksittäinen testitapaus

Before-metodeilla suoritetaan alustustoimenpiteitä, joko ennen jokaista luokan testitapausta tai ennen kunkin yksittäisen testin ajamista. Test-metodit suorittavat varsinaisen testauksen ja vertaamisen odotettuun arvoon. After-metodit vastaavat siivoustoimenpiteistä, ne suoritaan joko yksittäisen testitapauksen ajon jälkeen tai lopuksi, kun kaikki yksittäiset testitapaukset on läpikäyty.

JUnit-kirjaston assert-metodien avulla tarkastetaan testattavan koodin oikeanlainen toimivuus. AssertEquals-metodia käyttämällä varmistetaan, että sille annetut arvot vastaavat toisiaan. AssertEqualsille annetaan ensimmäiseksi parametriksi arvo, joka vastaa ohjelman toiminnassa oikeaa vastausta, toisena parametrina annetaan testattava arvo. Mikäli arvot eivät vastaa toisiaan, kyseinen testi on epäonnistunut.

Yhteensopivuus muihin työkaluihin
---------------------------------

JUnit 5 sopii yhteen useiden alustojen kanssa. Tällaisia alustoja ovat esimerkiksi IDE (integrated development environments) ja CI (continuous integration).

#### Ant laajennus

Apache Ant on yksi monipuolisimmista rakentajista (build tool). Ant keskittyy `build.xml`-tiedoston ympärille, jota käytetään projektin suorittamiseen tarvittavien tehtävien määrittämiseen. Apache Ivy on Ant laajennus, joka on luotu helpottamaan riippuvuuksien erottelua. Projektin riippuvuudet voidaan ilmoittaa `ivy.xml`-tiedostossa. JUnit 5 voidaan liittää osaksi Ant ympäristöä määrittämällä JaCoCo (Java code coverage tools) `ivy.xml`-tiedostolle. `ivy.xml` voidaan tämän jälkeen konfiguroida `java-platform-console`- ja `junit- platform-runner` kanssa JUnit 5 käyttöön ottamiseksi.

#### Maven laajennus

Maven käyttää standardisoitua ja yhtenäistä lähestymistapaa rakennusprosessissa. Maven noudattaa riippuvuuksiensa hallinnassa "convention over configuration" -paradigmaa. Mavenia voidaan käyttää missä tahansa Java-projektissa. Se käyttää POM-mallia (Project Object Model), joka on XML pohjainen lähestymistapa projektin koontivaiheiden määrittämiseen. Mavenin toimimiseksi, täytyy Mavenin reitin olla rakennettu oikein. JUnit 5 voidaan liittää toimimaan osaksi Maven-ympäristöä käyttämällä `jacoco-maven-plugin`-liitintä, joka tukee valmiita toimintoja JUnit 5 -testeissä.

#### Gradle laajennus

Gradle on rakentaja, joka lainaa monia toiminnallisuuksiaan edeltäjistään Ant ja Maven. Toisin kuin Ant ja Maven, jotka ovat XML-pohjaisia, Gradle vaatii Apache Groovy:n käyttöä, joka on Java-pohjainen ohjelmointikieli. Gradle noudattaa Mavenin "convention over configuration" -lähestymistapaa ja lisäksi samaa rakennetta `src/main/java`- ja `src/test/java` -hakemistoissa. JUnit 5 voidaan liittää toimimaan osaksi Gradle-ympäristöä käyttämällä `jacoco`-liitintä yhdessä JUnit 5 koontitiedoston tarjoaman alustalaajennuksen kanssa.

#### JUnit Lisäosamalli

JUnit seuraa lisäosamallia, jossa kaikkia ominaisuuksia ei ole sisällytetty yhteen pakettiin. JUnit tiimin päätös olla lisäämättä kaikkia ominaisuuksia suoraan JUnitin ydinversioon, mahdollistaa ydinpaketin pienemmän koon ja tarjoaa kehittäjille tilaisuuden sovittaa toiminta erilaisten lisäosien kautta ohjelmistoon. 

JUnit 4:ssä on kaksi erilaista lisäosamekanismia, Runner API ja Rule API, joissa molemmissa on omat heikot puolensa.

Merkittävin ongelma Runner API:ssa on se, että kehittäjän tulee luoda koko elinkaari vaikka tarve olisi vain yhdelle elämänkaaren vaiheelle. Tämä on liian monimutkaista suurimmalle osasta tapauksista. Toinen merkittävä ongelma on tarve luoda jokaiselle tapaukselle oma Runner -luokkansa, sillä ne eivät ole yhteensopivia keskenään. Esimerkkinä tästä toimii Mockito ja Parametrisoidut Runnerit, sillä ne eivät voi olla samassa testiluokassa.

Rule -rajapinnan merkittävä ongelma on sen kyvyttömyys hallita koko testin elinkaarta, tehden siitä mahdottoman hyödyntää jokaisessa käyttötapauksessa. Sitä voidaan käyttää ainoastaa sellaisissa tapauksissa, missä jotain pitää tehdä ennen tai jälkeen testin suorittamista. Lisäksi, säännöt luokkatasolle ja metoditasolle tulee tehdä erikseen, vaikeuttaen testien kirjoittamista. 

JUnit 5:ssä lisäosarajapinta on sisäänrakennettu JUnit Jupiter -moottoriin, mahdollistaen kehittäjien yhtyä eri vaiheisiin testin elinkaaressa. Saavutettaessa tietty elinkaaren vaihe, Jupiter -moottori pystyy yhdistämään vaiheessa vaaditut lisäosat. Kehittäjän on mahdollista yhtyä viiteen keskeiseen vaiheeseen:

1. Testin elinkaaren takaisinpyyntö - Mahdollistaa kehittäjän yhtyä tiettyyn elinkaaren vaiheeseen
2. Testin instanssin jälkiprosessointi - Kehittäjä voi yhtyä testi-instanssin luonnin jälkeen tekemällä TestInstancePostProcessor -rajapinnan
3. Ehdollinen testin suorittaminen - Kehittäjä pystyy suorittamaan testin kun tietyt ehdot täyttyvät
4. Parametriresoluutio - Kehittäjä voi selvittää testimetodista tai rakentajasta saadun parametrin
5. Virheenkäsittely - Mahdollistaa testiajon sopeuttamisen virheen heittämisen sijaan.

Aikaisemmat JUnit-versiot
-------------------------

Martin Fowler, yksi JUnitin varhaisista käyttäjistä, kertoo:

"JUnit syntyi lennolla Zürichistä vuoden 1997 OOPSLAan Atlantassa. Kent (Beck) lensi Erich Gamman kanssa, ja mitä muuta kaksi nörttiä tekisi pitkällä lennolla kuin ohjelmoisi? JUnitin ensimmäinen versio rakennettiin siellä, pariohjelmoitiin ja testattiin ensi kertaa."

Laajan käytön sivuvaikutuksena JUnitin aiemmat versiot ovat edelleen suosittuja, sillä JUnit 4:llä on yli 100 000 käyttöä muilla Maven Central -tietovaraston ohjelmistokomponenteilla.

JUnit 4:ssä testin suorittamisen takaisinkutsujen merkinnät olivat `@BeforeClass`, `@Before`, `@After` ja `@AfterClass`, toisin kuin JUnit 5:n `@BeforeAll`, `@BeforeEach`, `@AfterEach` ja `@AfterAll`.

JUnit 3:ssa testien oli perittävä `junit.framework.TestCase`. Lisäksi testimenetelmien eteen piti liittää "test".

Lähteet
-------

* https://www.tutorialspoint.com/junit/junit\_overview.htm
* https://junit.org/junit5/
* https://www.theseus.fi/bitstream/handle/10024/118620/Haltiapuu\_Inka.pdf?sequence=1
* https://ohjelmointi2.github.io/kalvot/yksikkotestaus.pdf

1. 1 2  Gulati, Shekhar & Sharma, Rahul: *Java Unit Testing with JUnit 5*, s. 108-112. Berkeley, CA, 2017. ISBN 978-1-4842-3014-5. doi:10.1007/978-1-4842-3015-2.
2. ↑  Gulati, Shekhar & Sharma, Rahul: *Java Unit Testing with JUnit 5*, s. 116-117. Berkeley, CA, 2017. ISBN 978-1-4842-3014-5. doi:10.1007/978-1-4842-3015-2.
3. 1 2  Gulati, Shekhar & Sharma, Rahul: *Java Unit Testing with JUnit 5*, s. 104-108. Berkeley, CA, 2017. ISBN 978-1-4842-3014-5. doi:10.1007/978-1-4842-3015-2.
4. 1 2 3  Gulati, Shekhar & Sharma, Rahul: *Java Unit Testing with JUnit 5*, s. 99-103. Berkeley, CA, 2017. ISBN 978-1-4842-3014-5. doi:10.1007/978-1-4842-3015-2.
5. ↑  Gulati, Shekhar & Sharma, Rahul: *Java Unit Testing with JUnit 5*, s. 115. Berkeley, CA, 2017. ISBN 978-1-4842-3014-5. doi:10.1007/978-1-4842-3015-2.
6. ↑  Gulati, Shekhar & Sharma, Rahul: *Java Unit Testing with JUnit 5*, s. 113-114. Berkeley, CA, 2017. ISBN 978-1-4842-3014-5. doi:10.1007/978-1-4842-3015-2.