Søger du en specifik kategori?

 



Oprettet ons. d. 17. februar 2010 kl. 04:21

arne_v
arne_v (1.005.658 point)
Guidens karaktér
1
2
3
4
5
Mangler vurderinger

Test med JUnit 4

Denne artikel introducerer JUnit 4. Den forklarer ideen med JUnit. Og den viser hvordan man konkret bruger det. Den forudsætter kendskab til Java og noget generel udviklings erfaring.
Historie:
V1.0 - 16/02/2010 - original

Versioner

Denne artikel omhandler JUnit 4.x.

For samme artikel omkring JUnit 3.x se:
  http://www.eksperten.dk/ (...)

JUnit 4.x kan kun en lille smule mere end JUnit 3.x, men den bruges helt
anderledes, fordi den bruger Java 1.5 annotations.

Unit test

Unit test er ikke en ny opfindelse. Det har man brugt i mange år.
Developere skulle teste deres lille stump inden hele projektet
blev afleveret til test.

Men der er kommet rigtig meget fokus på den i de sidste
10-15 år. Det er ikke længere bare noget som man principielt
burde huske at gøre men en meget vigtig del af hele udviklings
processen.

Det hænger lidt sammen med begreber som XP (eXtreme Programming),
Refactoring, Agile Software Development, Test Driven Development
etc.. Men er også accepteret udenfor disse metodikker.

Man er beyndt at skrive unit test kode til at teste systematisk
og automatisk.

Det med automatisk er uhyre vigtigt i. Hvis man har en stor
suite af unit tests som tester en given kode, så kan man
nemmere tillade sig at rette i den, fordi man kan teste
store dele af funktionaliteten på få sekunder/minutter.

Samtidigt har unit test også flyttet sig tidsmæssigt.

Engang skrev man unit test kode til sidst efter at man havde skrevet
selve koden. Det er nu almindeligt accepteret, at det ikke er
så godt. Folk skriver nemlig så unit test koden efter hvordan
de ved koden virker d.v.s. at de finder færre fejl.

Så nu er det alment accepteret at man bør skrive unit test koden
først udfra hvad koden bør kunne og ikke hvad den kan.

Nogen er endda begyndt at flytte det at skrive unit teste
kode op som en del af design. Det er jo en præcis måde at beskrive
hvad koden skal gøre og dermed dets interface udadtil.

JUnit

Unit test i Java er næsten synonymt med JUnit. Næsten alle
bruger JUnit eller en overbygning på JUnit.

JUnit kan hentes her:
  http://www.junit.org/

Og ZIP filen skal bare unzippes og så er man kørende.

De fleste Java IDE'er kommer idag med JUnit og indbyggede
måder at køre JUNit på. Men det vil jeg dog ikke komme ind på her.

Eksempel

Lad os tage et simpelt eksempel for at illustrere hvordan det
ser ud i praksis.

Vi har følgende kode som skal testes:

public class MathVector {
  private int[] v;
  public MathVector(int n) {
      v = new int[n];
  }
  public MathVector(int[] v) {
      this.v = v;
  }
  public MathVector add(int k) {
      int[] res = new int[v.length];
      for(int i = 0; i < v.length; i++) res[i] = v[i] + k;
      return new MathVector(res);
  }
  public MathVector sub(int k) {
      int[] res = new int[v.length];
      for(int i = 0; i < v.length; i++) res[i] = v[i] - k;
      return new MathVector(res);
  }
  public MathVector mul(int k) {
      int[] res = new int[v.length];
      for(int i = 0; i < v.length; i++) res[i] = v[i] * k;
      return new MathVector(res);
  }
  public MathVector div(int k) {
      int[] res = new int[v.length];
      for(int i = 0; i < v.length; i++) res[i] = v[i] / k;
      return new MathVector(res);
  }
  public MathVector mod(int k) {
      int[] res = new int[v.length];
      for(int i = 0; i < v.length; i++) res[i] = v[i] - (v[i]/k);
      return new MathVector(res);
  }
  public int size() {
      return v.length;
  }
  public int[] getV() {
      return v;
  }
}

(der er en simpel fejl !)

Vi laver nu følgende test kode:

import org.junit.*;
import static org.junit.Assert.*;

public class TestMathVector {
    @Before
    public void setUp() {
    }
    @After
    public void tearDown() {
    }
    @Test
    public void testAdd() {
        int[] v = { -1000000, -1, 0, 1, 1000000 };
        MathVector mv = new MathVector(v);
        MathVector mv2 = mv.add(777);
        assertEquals("add size", mv.size(), mv2.size());
        for(int i = 0; i < mv2.size(); i++) {
            assertEquals("add " + i, mv.getV()[i] + 777, mv2.getV()[i]);
        }
    }
    @Test
    public void testSub() {
        int[] v = { -1000000, -1, 0, 1, 1000000 };
        MathVector mv = new MathVector(v);
        MathVector mv2 = mv.sub(777);
        assertEquals("sub size", mv.size(), mv2.size());
        for(int i = 0; i < mv2.size(); i++) {
            assertEquals("sub " + i, mv.getV()[i] - 777, mv2.getV()[i]);
        }
    }
    @Test
    public void testMul() {
        int[] v = { -1000000, -1, 0, 1, 1000000 };
        MathVector mv = new MathVector(v);
        MathVector mv2 = mv.mul(777);
        assertEquals("mul size", mv.size(), mv2.size());
        for(int i = 0; i < mv2.size(); i++) {
            assertEquals("mul " + i, mv.getV()[i] * 777, mv2.getV()[i]);
        }
    }
    @Test
    public void testDiv() {
        int[] v = { -1000000, -1, 0, 1, 1000000 };
        MathVector mv = new MathVector(v);
        MathVector mv2 = mv.div(777);
        assertEquals("div size", mv.size(), mv2.size());
        for(int i = 0; i < mv2.size(); i++) {
            assertEquals("div " + i, mv.getV()[i] / 777, mv2.getV()[i]);
        }
    }
    @Test
    public void testMod() {
        int[] v = { -1000000, -1, 0, 1, 1000000 };
        MathVector mv = new MathVector(v);
        MathVector mv2 = mv.mod(777);
        assertEquals("mod size", mv.size(), mv2.size());
        for(int i = 0; i < mv2.size(); i++) {
            assertEquals("mod " + i, mv.getV()[i] % 777, mv2.getV()[i]);
        }
    }
}


Bemærk at tests markeres med @Test annotation og setup/teardown med @Before/@After
annotation.

(jeg har brugt klasse og metode navne som i JUnit 3.x, men hele pointen med
JUnit 4.x er at det 1) ikke skal arves fra en bestemt klasse 2) man kan
kalde klasser og metoder hvad man har lyst til)

Jeg kalder assertEquals med 3 argumenter:
  - tekst som identificerer stedet i koden
  - forventet værdi
  - faktisk værdi
(jeg anbefaler klart at man bruger versionen med 3 argumenter, da den
identificerende tekst ofte er meget nyttig)

Der findes også assertTrue, assertNotNull etc. metoder. De kan slåes op
i JavaDoc for JUnit.

Og når vi kører med:

javac -classpath . MathVector.java
javac -classpath .;/DivJava/junit4.4/junit-4.4.jar TestMathVector.java
java -classpath .;/DivJava/junit4.4/junit-4.4.jar org.junit.runner.JUnitCore TestMathVector

Får vi følgende fejl:

.....F
Time: 0
There was 1 failure:
1) testMod(TestMathVector)junit.framework.AssertionFailedError: mod 0 expected:<-1> but was:<-998713>
        at TestMathVector.testMod(TestMathVector.java:53)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

FAILURES!!!
Tests run: 5,  Failures: 1,  Errors: 0

Vi kigger lidt i koden og opdager at der mangler en multiplikation,
så vi retter koden til:

  public MathVector mod(int k) {
      int[] res = new int[v.length];
      for(int i = 0; i < v.length; i++) res[i] = v[i] - (v[i]/k)*k;
      return new MathVector(res);
  }

Og nu får vi:

.....
Time: 0

OK (5 tests)


Hvis man bruger ant, så ser build.xml ud som:

<project name="junitdemo" default="testrun">
    <property name="junitlib" value="/DivJava/junit4.4/junit-4.4.jar"/>
    <target name="compile">
        <javac classpath="." srcdir="." destdir="."/>
    </target>
    <target name="testcompile" depends="compile">
        <javac classpath=".;${junitlib}" srcdir="." destdir="."/>
    </target>
    <target name="testrun" depends="testcompile">
        <junit fork="on">
            <classpath path=".;${junitlib}"/>
            <formatter type="plain" usefile="false"/>
            <test name="TestMathVector"/>
        </junit>
    </target>
</project>

og output ser ud som:

Buildfile: build.xml

compile:

testcompile:

testrun:
    [junit] Testsuite: TestMathVector
    [junit] Tests run: 5, Failures: 0, Errors: 0, Time elapsed: 0.015 sec
    [junit] Testcase: testAdd took 0 sec
    [junit] Testcase: testSub took 0 sec
    [junit] Testcase: testMul took 0 sec
    [junit] Testcase: testDiv took 0 sec
    [junit] Testcase: testMod took 0 sec

BUILD SUCCESSFUL
Total time: 1 second

Det kan anbefales at bruge ant.

Vigtigt:
  - fork="on"

Man kan så samle flere test cases i en test suite som:

import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)
@SuiteClasses({TestMathVector.class,Abc.class,Xyz.class})
public class AllTests {
}

Og teste den.

Det her var Java SE - man kan naturligvis også bruge JUnit til Java EE.
Remote interfaces til EJB's kan testes umiddelbart i JUnit. Det er
lidt vanskeligere med local interfaces og JCA connectorer, da de kun
kan kaldes inde fra. Til det formål er der lavet overbygninger til
JUnit bl.a. Apache Cactus:
  http://jakarta.apache.org/ (...)

God test lyst.

Skriv en kommentar



Mest populære guides

Guidens karakter
!!!Karaktér: 3
12 stemmer
31/01 - 2011
Af: heinzdmx

Dropbox - gratis online lagerplads

Jeg vil i denne guide forklare lidt om hvad Dropbox er og også hvordan du får mest mulig plads på Dropbox. Dropbox er kort sagt en service hvor du har dine data lagt til backup på både nettet og din egen computer.
Guidens karakter
!!!Karaktér: 4
33 stemmer
02/02 - 2009
Af: jkrons

Dato- og tidsberegninger i Excel

En introduktion til simple beregninger med dato og tid i Excel. Opdateret med afsnit om beregning af tillæg.
Excel  |  Læs »
Guidens karakter
!!!Karaktér: 4
21 stemmer
06/11 - 2011
Af: fromsej

Sådan fjerner du virus og malware

Udviklingen går stærkt på "skidt"fronten, så vi har sammensat en ny og effektiv programpakke til fjernelse af det.
Virus  |  Læs »

Log ind

   

   

Seneste guides

Installer win 7
Den gode bruger


   




Tips & Tricks fra PC World

Teaser billede

Her er fem sjove danske websider du skal kende

Trænger dine lattermuskler til en omgang fitness på dansk? Vi viser vej til fem websider fyldt med humor og vanvittig satire.


Anmeldelser fra PC World

Teaser billede

Test: Denne super-tablet er iPads hårdeste konkurrent

Eee Pad Transformer Prime er frygtindgydende med sin quadcore processor og evne til at trylle sig om til bærbar. Apple bør kigge i bagspejlet, for Asus' tablet-pc kommer buldrende - og gør det...


Seneste blogindlæg

Teaser billede

Tvangslukke spørgsmål: Hvad er den bedste løsning?

Hej Vi har mange åbne spørgsmål på Eksperten. Vi ville gerne tvangslukke dem - så et spørgsmål efter f.eks. 6 måneder lukkes. Men der er et par uklarheder som ville være gode at få lidt input til:...


Nyheder fra PC World

Teaser billede

Nu kan du snart hente Windows 8

Den nye offentlige betaversion af Windows 8 er klar i denne måned.


Nyheder fra Computerworld

Teaser billede

Måske snart slut med Androids helt store problem

Android-platformen har længe været plaget af et særligt problem. Men måske er problemet nu ved at være elimineret.


Kurser
Samarbejdspartnere

Udgiver · © 2012 IDG Danmark A/S · Hørkær 18 · 2730 Herlev · Tlf.: 77 300 300 · Fax: 77 300 301 · Brug af personoplysninger