JUnit-testikehys

Yksikkötestit kirjoitetaan sujuvimmin testikehystä käyttäen. Javalle yksi tällainen on JUnit, joka on tarkoitettu testivetoiseen ohjelmistokehitykseen. JUnitin uusin versio, JUnit 5, sijaitsee pakkauksessa org.junit.jupiter. Aiemmat versiot JUnit 4 ja JUnit 3 sijaitsivat vastaavasti pakkauksissa org.junit ja junit.framework. JUnitin käyttöohjeet löydät verkosta: JUnit User Guide.

JUnitin testikehys on Java olio. Testiluokan koodissa jokainen testimetodi annotoidaan @Test annotaatiolla. Tarvittaessa metodi voidaan määritellä ajettavaksi ennen tai jälkeen jokaisen tai kaikkien testimetodien annotaatioilla @BeforeEach (tai @AfterEach) ja vastaavasti @BeforeAll (tai @AfterAll). Lista JUnitin annotaatioista.

Testiluokan perusrakenne on:

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

public class MyClassTest {
    @BeforeAll
    public static void setUpClass() throws Exception {
        // Toimenpiteet, jotka suoritetaan ennen ensimmäistä testiä
    }

    @BeforeEach
    public void setUp() throws Exception {
        // Toimenpiteet, jotka suoritetaan ennen jokaista testiä
    }

    @Test
    public void testMethod() {
        // Koodi methodin testaamiseksi
    }

    @AfterEach
    public void tearDown() throws Exception {
        // Toimenpiteet, jotka suoritetaan jokaisen testin jälkeen
    }

    @AfterAll
    public static void tearDownClass() throws Exception {
        // Toimenpiteet, jotka suoritetaan viimeisen testin jälkeen.
    }
}

Lisäksi voidaan määritellä testien ajamiselle erilaisia ehtoja, testejä voidaan parametrisoida, määrittää ajettavaksi tietyssä järjestyksessä, määrittää ajettavaksi haluttu määrä kierroksia ja niin edelleen. Esimerkki Javan Date-luokkaa testaavasta testiluokasta:

public class DateTest {
    @Test
    public void testGetYear() {
        // tulostetaan testattavan metodin nimi
        System.out.println("getYear");
        // luodaan testattava luokan instanssi
        Date instance = new Date(2022, 2, 28);
        // määritellään odotettu tulos
        int expResult = 2022;
        // haetaan testi-instanssin tilan arvo
        int result = instance.getYear();
        // tutkitaan vastaako haettu tila odotettua tulosta
        // jos eivät, assertEquals heittää AssertionErrorin
        assertEquals(expResult, result);
    }

    @Test
    public void testGetMonth() {
        System.out.println("getMonth");
        Date instance = new Date(2022, 2, 28);;
        int expResult = 2;
        int result = instance.getMonth();
        assertEquals(expResult, result);
    }

    @Test
    public void testGetDay() {
        System.out.println("getDay");
        Date instance = new Date(2022, 2, 28);;
        int expResult = 28;
        int result = instance.getDay();
        assertEquals(expResult, result);
    }

    @Test
    public void testToString() {
        System.out.println("toString");
        Date instance = new Date(2022, 2, 28);;
        String expResult = "28.02.2022";
        String result = instance.toString();
        assertEquals(expResult, result);
    }

    @Test
    public void whenExceptionThrown() {
        System.out.println("whenExceptionThrown");
        Exception exception = assertThrows(DateException.class, () -> {
            new Date(2022, 2, 29);
        });

        String expectedMessage = "Illegal date 29.02.2022";
        String actualMessage = exception.getMessage();
        System.out.println(actualMessage);
        assertTrue(actualMessage.contains(expectedMessage));
    }

    // Tehdään parametrisoitu testi
    // jolle annetaan syötetiedot intProvider-metodilla
    @ParameterizedTest
    @MethodSource("intProvider")
    void testLegalDates(int year, int month, int day) {
        System.out.println("isLegalDate");
        assertTrue(Date.isLegalDate(day, month, year));
    }

    // Testin parametrit streamina palauttava metodi
    // Streamin ohella mikä tahansa säiliö olisi sallittu, esim. List.
    static Stream<Arguments> intProvider() {
        return Stream.of(
            arguments(2014, 2, 14),
            arguments(2020, 5, 30)
        );
    }
}

Koodin kääntämiseen ja ajamiseen tarvitaan JUnitin pakkaukset. On helpointa antaa IDE:n huolehtia niistä.

Jos kuitenkin päätät määritellä JUnitin riippuvuudet itse, sinun on lisättävä pom.xml-tiedostoon alla olevat määrittelyt. Kolme ensimmäistä määrittelyä ottavat käyttöön JUnit-kirjastot. Nämä määrittelyt voitaisiin antaa ilman versionumeron “toistoa” dependencyManagement-elementtiä käyttäen. Viimeinen määrittely on Surefire-liitännäiselle, jonka tehtävänä on ajaa Maven-projektin testit.

<dependencies>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>5.6.0</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-params</artifactId>
        <version>5.6.0</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <version>5.6.0</version>
        <scope>test</scope>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>3.2.5</version>
        </plugin>
    </plugins>
</build>

Netbeans

NetBeans tarjoaa suoraan JUnitin osana Java SE -liitännäistä. NetBeansin Maven-projektissa on valmiina src\test\java-hakemisto, jonka alle JUnit-testiluokat mahdollisten pakkaushakemistojensa kanssa sijoitetaan. Alla oletaan käytettävän Maven-projektia.

JUnit-testiluokka luodaan NetBeansissa seuraavasti:

  1. Klikkaa Projects-välilehdellä luokkaa, jolle haluat tehdä testiluokan. Varmista, että luokkatiedosto on aktivoituna, jotta seuraava vaihe toimii varmasti.

  2. Luo testiluokka valitsemalla Tools | Create/Update Tests.

Testiluokan voi luoda myös pitempää reittiä New File | Unit Tests | Test for Existing Class -valintojen kautta. Anna tällöin pakkaus, jos testattava luokka on pakkauksessa. Testattavan luokan ja sen pakkauksen määrittely on helpointa Browse-napin kautta valitsemalla.

Kaikki testit voi ajaa Run | Test Project -valinnalla, joka on saatavilla myös Projects-välilehdellä projektin otsikon kautta. Alla oleva kuva on esimerkki NetBeansin Test Results -välilehdillä antamista testituloksista.

NetBeans lisää automaattisesti pom.xml-projektitiedostoon tarvittavat JUnit-riippuvuudet. Joudut valitettavasti lisäämään itse Surefire-liitännäisen määrittelyn pom.xml-tiedostoon, jos haluat ajaa testit Mavenilla myös komentoriviltä käsin.

Visual Studio Code myös tukee JUnitia Java Test Runner laajennuksen, joka asentuu oletuksena osana Java Extension Packia.

testien tulos ajettuna NetBeansissa

Ajetuista testeistä näytetään testin tulos, sekä epäonnistuneen testin kohdalla syy.

Kysymyksiä

Tutustu JUnitin käyttöohjeeseen.