Metadata: JUnit-ohje

JUnit-tutoriaali

JUnitin ideana on automatisoida luokkien yksikkötestauksien suoritus sekä testien tulosten keruu ja ilmaisu. Itse testitapaukset täytyy suunnitella ja ohjelmoida itse. JUnit-testit voi muodostaa parilla eri tavalla, mutta tässä esitellään vain yksi yksinkertainen ja monipuolinen tapa. Huom. esimerkit eivät ole kokonaan oikeaa Javaa.

Testitapausten suunnittelu ja ohjelmointi

Halutaan testata luokkaa Harvester. Testejä varten luodaan erillinen luokka, esim. HarvesterTest, joka periytetään JUnitin TestCase -luokasta. Testiluokan konstruktori ottaa parametrinä Stringin ja antaa sen parametriksi yliluokan konstruktorille.

Testit suoritetaan yhdessä tai useammassa metodissa. Testitapausten eriyttämisessä eri metodeihin voi käyttää jotakin järkevää logiikkaa, mutta konkreettisempikin syy löytyy (ks. fixture). Testitapauksen toteuttavan metodin nimen täytyy alkaa sanalla "test".

Poikkeuksia ei pidä ottaa huomioon try/catch -rakenteella, paitsi luonnollisesti jos testataan tarkoituksella, että tietystä tilanteesta syntyy poikkeus.

Esimerkissä testataan kahta palautusmetodia, joista jälkimmäisen pitäisi palauttaa sama int-arvo kuin ensimmäisen metodin. AssertTrue -metodi tulee JUnitista. Parametri true tarkoittaa, että testi on onnistunut. False tarkoittaa epäonnistumista, jolloin JUnit lopettaa testauksen ajon ilmoitukseen siitä, millä rivillä oleva assertTrue -kutsu sai parametrin false. Esimerkissä assertTrue:n parametri on true, jos ekaPalautus ja tokaPalautus ovat yhtä suuret (näin siis pitäisi olla jos palautusmetodit on ohjelmoitu virheettömästi).

 package com.xyz.Harvester;

 import junit.framework.TestCase;

 public class HarvesterTest extends TestCase {

	public HarvesterTest(String name) {
		super(name);
	}

	public void testPalautus() throws Exception {
		Harvester h = new Harvester();
		int ekaPalautus = h.palautaJotain();
		int tokaPalautus = h.palautaSama();
		assertTrue(ekaPalautus == tokaPalautus);
	}
 }

Fixture

Fixture tarkoittaa muuttujia, joita tarvitaan useissa testeissä (saman testiluokan sisällä) samoilla alkuarvoilla. Käytännössä nämä siis toteutettaisiin testiluokan ilmentymän kenttinä. Koska muuttujat täytyy alustaa aina ennen testiä, ei riitä että ne alustetaan konstruktorissa.

TestCase-luokasta voidaan korvata metodit setUp() ja tearDown(), joissa muuttujat alustetaan ennen testiä ja mahd. varattu muisti tms. vapautetaan testin jälkeen. Testi tarkoittaa yhden testauksen/testauksia toteuttavan metodin kutsua. Fixturen järkevä ja toimiva käyttö edellyttää siis testitapausten jakamista eri metodeihin.

 package com.xyz.Harvester;

 import junit.framework.TestCase;

 public class HarvesterTest extends TestCase {
	private Harvester harvester1;
	private Harvester harvester2;
	private char *ptr;

	public HarvesterTest(String name) {
		super(name);
	}

	protected void setUp() {
		this.harvester1 = new Harvester("spice");
		this.harvester2 = new Harvester("tiberium");
		this.ptr = malloc(256);
	}

	protected void tearDown() {
		free(this.ptr);
	}

	public void testPalautus() throws Exception {
		int ekaPalautus = this.harvester1.palautaJotain();
		int tokaPalautus = this.harvester1.palautaSama();
		assertTrue(ekaPalautus == tokaPalautus);
	}

	public void testContents() throws Exception {
		assertTrue(this.harvester1.sisaltö() != this.harvester2.sisältö());
	}
 }

Suite

Suurella todennäköisyydellä halutaan ajaa kaikki testiluokan testitapaukset yhdellä kertaa, ja ehkä useampiakin testiluokkia yhdellä kertaa. Tällöin testit kootaan TestSuite -olioksi. Konstruktorille ei tarvitse antaa parametriä. Olion luonnin jälkeen testiluokat voidaan lisätä addTestSuite -metodilla, tai addTest -metodilla jolle voi antaa parametriksi myös jonkin toisen TestSuiten.

 TestSuite suite = new TestSuite();
 suite.addTestSuite(HarvesterTest.class);

Testien ajo JUnitissa

JUnit löytyy kahtena graafisena versiona: junit.awtui.TestRunner ja junit.swingui.TestRunner, sekä tekstiversiona junit.textui.TestRunner. Testiajon voi käynnistää suoraan komentoriviltä suorittamalla jonkin em. TestRunnereista, ja antamalla sille parametriksi testiluokan. Laitoksen Linux-ympäristössä komentorivikäsky voisi olla seuraavanlainen:

 java -cp junit.jar:test/:src/ junit.textui.TestRunner com.xyz.HarvesterTest

Jos halutaan kerätä useampi testiluokka TestSuiteksi, jotta niitä voidaan ajaa kerrallaan, tehdään luokka joka sisältää staattisen suite()-nimisen metodin. Suite() -metodi palauttaa testit sisältävän Test-rajapinnan toteuttavan olion (TestCase tai TestSuite). Esimerkissä on luokkaan AllTests kerätty useita testiluokkia ajettavaksi kerrallaan, ja se käynnistettäisiin komentoriviltä kuten yksittäinen testiluokan ajo.

 package com.xyz.Harvester;

 import junit.framework.Test;
 import junit.framework.TestSuite;

 public class AllTests {

	public static Test suite() {
		TestSuite suite = new TestSuite();
		suite.addTestSuite(HarvesterTest.class);
		suite.addTestSuite(xyz.class);
		suite.addTestSuite(...);
		return suite;
	}
 }

Vaihtoehtoisesti voi kirjoittaa ohjelman, joka kutsuu JUnitin TestRunnerin run-metodia, parametrinä ajettava TestSuite.

Huom. JUnitissa failure tarkoittaa assertTrue(false), kun taas error on esim. testin kaatuminen NullPointerExceptioniin.

Lisätietoa:

Tämä on hyödyllinen: http://www.exubero.com/junit/antipatterns.html

junit.zip:

Eclipsen Java Project -tutoriaali

Page last modified on November 12, 2005, at 03:11 PM