Hvordan skal man teste med JUnit?

Tags:    junit java test test-driven

Hej allesammen

Jeg har indtil videre ikke prøvet at teste når jeg skulle udvikle, eller i hvertfald ikke bevidst, men har fået fortalt at det er en god måde at udvikle på, da det er med til at eliminerer evt. bugs der kan opstå senere i ens applikation. Til formålet har jeg erhvervet mig JUnit værktøjet, og også læst/lært lidt om hvordan dette fungerer.

Mit spørgsmål er så om hvordan jeg skal begynde at teste? Skal jeg f.eks. skrive selve test klassen først, og herudfra lave mine klasser, som jeg ønsker at teste, eller skal jeg udvikle mine klasser, og herefter skrive selve test klassen, hvor jeg nu ved hvilke metoder jeg skal teste mm?

Grunden til at jeg er i tvivl, er at de nogen steder på nettet fortæller mig at jeg skal skrive en test case (forstår dette som en test klasse), før jeg overhovedet begynder at lave den del af min applikation, som jeg gerne vil teste, mens de andre steder viser en klasse de allerede har lavet, og herefter skriver en test klasse til at teste denne klasse og dens metoder.

Som ekstra information, kan jeg fortælle hvordan jeg mener at det skal gøres med kode eksempler:

1. Jeg opretter min/mine klasser som jeg skal bruge i min applikation. Skal jeg f.eks. lave en lommeregner, så opretter jeg klassen Calculation med dens lommeregner metoder.
Fold kodeboks ind/udJava kode 


2. Herefter skal jeg så teste min klasse, og laver nu først min test klasse
Fold kodeboks ind/udJava kode 


Er dette den rigtige fremgangsmetode, og i så fald, hvorfor er der så nogle der skriver at man skal lave sin test case før man overhovedet går i gang med at programmerer de klasser der skal testes?

Håber at i gider at hjælpe mig med at forstå dette, og håber også at jeg har belyst min problematik godt nok :)



3 svar postet i denne tråd vises herunder
1 indlæg har modtaget i alt 4 karma
Sorter efter stemmer Sorter efter dato
Du kan eks se bogen: Flexible, Reliable Software af min gamle underviser i Århus, Henrik Bærbak. Den beskriver det godt med eksempler.

Hvis ikke du er til bøger er her lidt basalt omkring det:

1. En test case er ikke det samme som en klasse, det er mere en liste af features i dit system du vil have testet. Det vil sige hvad din funktion er og hvad du vil forvente at den returnerer ved et givet input. Det kan nogle gange være "overkill" når man "hobby koder" - da man godt sådan ca kender sine funktioner.

2. Start med at lav en enkelt test metode der tester noget fra din test case, fx. noget fra din calculation klasse. Det svære her er at fange alle de forskellige typer af input der kan komme ind i din metode. (eks. kan der i visse sammenhænge være forskel på hvordan der reageres på positive tal, 0, og netative tal, så du bør teste med alle input)

3. Her kommer noget man lige skal vænne sig til i TDD, du compiler og ser at din test fejler.

4. Du implementerer nu en metode der tilfredsstiller både din compile og dine asserts i din test. Når den er korrekt, tager du det næste fra din test case og se hvad du kan få ud af den.

En af fordelene er at du får struktureret din kode "udefra", det vil sige at du ser dine egne objekter som du vil bruge dem hvis du kodede op mod dit system. MAn har ofte en tendens til som udvikler at starte fra bunden og lave bunker af metoder, der gør en helt masse smart og til sidst udvikler man det ovenliggende lag, som skal kalde det man lige har lavet. Så finder man ud af at metoderne skulle have andre parametre med, eller der ikke rigtig er flow i det - det er noget af det man kommer ud over.

Lidt mere avanceret unit test er at kigge på Dependency Injection og brugen af stubbe og mock objekter.

Men bogen kan anbefales, den gennemgår det hele - og Henrik, der har skrevet den har styr på det.



Indlæg senest redigeret d. 24.02.2012 13:32 af Bruger #2730
Ok... tak for svaret, tror lige jeg skal have et kig på den bog.

Men det jeg kan udlede af det er at man skriver en test case (en definition af hvad der skal testes, samt hvad man forventer af ens test), herefter koder man de metoder som skal testes, og til sidst koder man sin test klasse, for at teste om outputtet er som man forventede da man lavede ens test case. Hvis det er sådan det er, tror jeg at jeg har forstået det basale ved at teste.

Lige et side spørgsmål, hvad er Dependency Injection for noget?



Så fik jeg lige opdateret min post med et link til bogen.

Dependency injection hjælper dig med at isolere din kode, gøre det mere robust og mere testbart.

Forestil dig følgende pseudokode:

Fold kodeboks ind/udJava kode 


problemet i ovenstående er at du aldrig kan isolere din bruger klasse, den har en reference til en anden klasse, det vil sige at i dine tests skal du være koblet på en database for at teste. Hvis du derimod lave nedenstående kode, hvor du sender de instanser med til din bruger klasse som den er afhængig af (afhængigheds insprøjtning = dependency injection), således:

Fold kodeboks ind/udJava kode 


Det du sendet ind er et interface, for du koder jo mod interfaces ikk :-) (første lov for objektorienteret udvikling Java/C#), så under din test laver du blot en anden implementering af din DatabaseConnection som du så sender med (det hedder også en mock - en kunstig database), det eneste din SaveBruger metode så gør er måske at gemme hvor mange gange din SaveBruger metode har været kaldt, måske gør den ingenting. HVis du gemmer hvor mange gange din metode har været kaldt kan du jo efter metoden er kørt, se om du kalder den for meget.

Dette gør også at du kan teste på din Bruger klasse UDEN at være påvirket af dens kald, dem har du afkoblet og kan fokusere udelukkende på at teste din kode i gem rutinen.

Giver det mening?



Indlæg senest redigeret d. 24.02.2012 13:42 af Bruger #2730
t