You are on page 1of 34

Java-projekt @ ZEMRIS

Java tečaj

13. dio
Test Driven Development
(TDD)

© 2008.
TDD predavanje

● Prvi dio: testovi


● Drugi dio: TDD
Testovi
Testovi
● Važan korak u izgradnji softverskog proizvoda

● Koraci:
– Zahtjevi
– Izgradnja
– Implementacija
– Testiranje
– Postavljanje

● Ne nužno tim redosljedom! (TDD)


Testovi
● Vrste:
– Unit testing
– Integration testing
– System testing
– Acceptance testing

http://en.wikipedia.org/wiki/Software_testing
Testovi
● Što znači testirati?
– Provjeriti da neki dio koda radi kako ste zamislili (ili
netko drugi)
● Zašto testirati?
– Provjeriti da manja promjena nije uzrokovala
nestabilnost u proizvodu
– Promjena implementacije metode
– Dokumentacija
– 2/3 posla u izgradnji nekog softvera otpada na
održavanje (popravljanje bugova)
● Kako testirati?
Unit testovi
● Testiranje najmanje cjeline (razred)
● Unutar razreda se posebno testiraju metode
(najčešće se jednim testom pokriva jedna
metoda)
● Pretpostavka: sve ostale metode rade
savršeno
● Napomena: unit testing nije specifičan za
Javu ili za objektno orijentiranje jezike
Unit testovi
● Kako testirati?
– princip System.out.println(“T7b – tu sam!”);
● dobro za rješavanje (debugiranje) jednog konkretnog
problema
● što ako je čitav kod isprepleten ovakvim ispisima?
● test je prošao dobro - onda kada developer vidi
zadovoljavajući slijed ispisa
● ekstremno teško za provjeravati ako testova ima više
● vremenski vrlo zahtjevno
Unit testovi
● Kako testirati?
– automatski
● opisati test na način koji razumije računalo
● omogućiti da računalo provjeri je li test prošao ili ne
● tek ako je test pao, ispisati odgovarajuću poruku i
detalje

● za ovo trebamo odgovarajući okvir (framework) za


izradu testova
Riješenje problema
● Koristiti jedan od postojećih unit testing
frameworka za Javu:

– JUnit (danas aktualna verzija 4.x)


– TestNG
– JTigar
– Ostali (komercijalni)
Riješenje problema
● Postoje razni unit testeri za druge jezike (i
ostalo)
– PyUnit
– CUnit
– CppUnit
– NUnit
– HtmlUnit
– HttpUnit
– itd.

http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks
JUnit
● Unit testing framework
● Open source
● Homepage: http://www.junit.org/
● Već se nalazi u eclipse-u
● Najnovija verzija: 4.3
● Pokretanje:

java -cp ... org.junit.runner.JUnitCore TestClass1 TestClass2 ...


Radni problem
● Želimo testirati je li razred LinkedList dobro
implementiran
Anatomija jednog testa
● Napisati razred koji sadrži test
– test je javna metoda koja ne vraća ništa, i (osim u
slučaju parametarskih testova) ne prima ništa
– metoda je označena anotacijom @Test

package hr.fer.zemris.collections;

import org.junit.Test;

public class LinkedListTest {

@Test
public void sizeOfEmptyList() {
// ...
}

}
Anatomija jednog testa
● Napisati razred koji sadrži test
– test je javna metoda koja ne vraća ništa, i (osim u
slučaju parametarskih testova) ne prima ništa
– metoda je označena anotacijom @Test

import static org.junit.Assert.*;

@Test
public void sizeOfEmptyList() {
LinkedList<String> list = new LinkedList<String>();
assertEquals( "Velicina prazne liste nije nula.",
0,
list.size());
list = null;
}
Anatomija jednog testa
● Napisati razred koji sadrži test
– Uvjete koje test mora zadovoljiti provjerava se
nizom assert metoda – metode razreda
org.junit.Assert, koje smo statički importali

assertEquals(message, expected, actual);


assertTrue(message, value);
assertFalse(message, value);
assertNull(message, object);
assertNotNull(message, object);
assertSame(message, expected, actual);
assertNotSame(message, unexpected, actual);
Anatomija jednog testa
@Test
public void sizeOfEmptyList() {

LinkedList<String> list =
new LinkedList<String>(); Priprema testa

assertEquals(
"Velicina prazne liste nije nula.",
Test
0,
list.size());

list = null; Čišćenje nakon testa

}
Anatomija jednog testa
● U isti razred može se smjestiti više testova
● Ako svi zahtjevaju istu pripremu, kod možemo izdvojiti
u zasebne metode, označene s @Before i @After
Anatomija jednog testa
private LinkedList<String> list;

@Before
public void setUp() {
list = new LinkedList<String>();
}

@After
public void tearDown() {
list = null;
}

@Test
public void sizeOfEmptyList() {
assertEquals("Velicina prazne liste nije nula.", 0, list.size());
}

@Test
public void sizeOfNonEmptyList() {
list.add("Podatak");
assertEquals("Velicina liste nije jedan.", 1, list.size());
}
Anatomija jednog testa
● @Test anotacija podržava expected parametar
@Test(expected=NullPointerException.class)

● @Test anotacija podržava timeout parametar


@Test(timeout=5000)
Anatomija jednog testa
● Primjer testa koji uspjeva ako se dogodi iznimka

@Test(expected=IndexOutOfBoundsException.class)
public void removeFromEmptyList() {
list.remove(0);
}
JUnit – dodatne anotacije
● @BeforeClass – metoda se pokreće jednom
prije svih testova
@BeforeClass
public static void imeMetode() { ... }

● @AfterClass – metoda se pokreće jednom


nakon svih testova
@AfterClass
public static void imeMetode() { ... }
JUnit – dodatne anotacije
● @Before – metoda se pokreće prije svakog
testa
@Before
public void imeMetode() { ... }

● @After – metoda se pokreće nakon svakog


testa
@After
public void imeMetode() { ... }
JUnit – dodatne anotacije
● @Ignore – ignoriranje testa

@Ignore
@Test
public void imeMetode() { ... }

@Ignore(value=“Not yet implemented!”)


@Test
public void imeMetode() { ... }
JUnit – dodatne anotacije
● @RunWith – pokretanje testa s drugim
TestRunner-ima
@RunWith(Parametrized.class)
public class ImeRazredaTests {
@Parameters
public static Collection data() { ... }

}
Anatomija jednog testa
@RunWith(value=Parameterized.class)
public class FibboTest {

private int n;
private int expected;

public FibboTest(int n, int expected) {


super();
this.n = n;
this.expected = expected;
}

@Parameters
public static Collection<?> data() {
Object[][] d = new Object[][] {{0,0},{1,1},{2,1},{3,2}};
return Arrays.asList(d);
}

@Test
public void fibbTest() {
Assert.assertEquals("Pogresan izracun.", expected, fibb(n));
}
}
Anatomija jednog testa
@RunWith(value=Parameterized.class)
public class FibboTest {

// ...

public int fibb(int n) {


if(n<1) return 0;
if(n==1) return 1;
return fibb(n-1) + fibb(n-2);
}

// ...
}
JUnit – dodatne anotacije
● @RunWith – pokretanje testa s drugim
TestRunner-ima
@RunWith(Suite.class)
@Suite.SuiteClasses({
FactorialTest.class,
ListTest.class
})
public class AllTests {
}
Test Driven
Development
(TDD)
TDD
● Što je TDD?
– Tehnika kako povećati produktivnost pri stvaranju
proizvoda
– Test First Design (TFS) + refactoring
● Koji je cilj TDD-a?

Clean code that works


-- Ron Jeffries

● Gotovo je nemoguće slijediti TDD bez unit


testing frameworka
TDD
● TDD cikus:
– Dodaj test
– Pokreni sve testove i vidi da je novi pao
– Napravi malu promjenu
– Pokreni sve testove i vidi da su svi prošli
– Makni sve duplikate
TDD
● Dobra strana TDD-a
– Moguće je napraviti jako male korake kada je to
potrebno
– 100% koda je pokriveno testovima (svaka linija
koda)
– Dokumentacija
– Smanjeno vrijeme izrade proizvoda
– Povećana kvaliteta koda
– TDD određuje nacrt proizvoda (design)
– Nepotreban debuger
TDD
● Loša strana TDD-a
– Može ponekad smanjiti kvalitetu napisanog koda
– Daje garanciju samo za testove koji su napisani
– Neće generirati nove algoritme
– U nekim situacijama ga je jako teško primjeniti (GUI,
relacijske baze podataka)
– Nije izvediv u nekim područjima računalne znanosti
(kriptografija, umjetna inteligencija, računalna sigurnost itd.)
– Privatne metode ili članovi se nemogu testirati

● TDD treba kombinirati s ostalim tehnikama


● http://en.wikipedia.org/wiki/Agile_software_development
Kraj
● JUnit
– http://www.instrumentalservices.com/index.php?option=com_co
– http://junit.sourceforge.net/doc/faq/faq.htm
● TDD
– http://en.wikipedia.org/wiki/Test-driven_development
– http://www.agiledata.org/essays/tdd.html

You might also like