Testy jednostkowe - JUnit,
Testy jednostkowe - JUnit,
wraz z przykładami
wraz z przykładami
Michał Wojewoda s4929
2
2
Testy jednostkowe –
Testy jednostkowe –
przyomnienie
przyomnienie
Test jednostkowy (ang. unit test, test
Test jednostkowy (ang. unit test, test
modułowy) to w programowaniu,
modułowy) to w programowaniu,
metoda testowania tworzonego
metoda testowania tworzonego
oprogramowania poprzez
oprogramowania poprzez
wykonywanie testów weryfikujących
wykonywanie testów weryfikujących
poprawność działania pojedynczych
poprawność działania pojedynczych
elementów (jednostek) programu.
elementów (jednostek) programu.
3
3
xUnit - historia
xUnit - historia
Ogólnie przyjęta nazwa dla narzędzi
Ogólnie przyjęta nazwa dla narzędzi
testujących dla różnych języków
testujących dla różnych języków
programowania
programowania
Pierwszy z nich to SUnit dla języka
Pierwszy z nich to SUnit dla języka
smalltalk stworzony przez Kenta Beck’a
smalltalk stworzony przez Kenta Beck’a
okoł0 1994 roku.
okoł0 1994 roku.
4
4
JUnit - historia
JUnit - historia
Powstawał od 1998 roku.
Powstawał od 1998 roku.
Umożliwia tworzenie zarówno bardzo
Umożliwia tworzenie zarówno bardzo
prostych, jak i bardzo
prostych, jak i bardzo
skomplikowanych testów.
skomplikowanych testów.
5
5
JUnit
JUnit
Narzędzie służące do przeprowadzania
Narzędzie służące do przeprowadzania
testów jednostkowych aplikacji.
testów jednostkowych aplikacji.
Jest napisane w języku Java i służy do
Jest napisane w języku Java i służy do
testowania aplikacji w tym języku.
testowania aplikacji w tym języku.
Projekt OpenSource tworzony przez
Projekt OpenSource tworzony przez
społeczność JUnit.org.
społeczność JUnit.org.
6
6
JUnit w.g. JUnit.org
JUnit w.g. JUnit.org
Asercje
Asercje
Test fixtures
Test fixtures
Test runners
Test runners
7
7
Idea działania
Idea działania
Wywoływanie metod programu ze
Wywoływanie metod programu ze
wszystkimi kombinacjami parametrów
wszystkimi kombinacjami parametrów
wejściowych.
wejściowych.
Sprawdzanie otrzymanych wyników
Sprawdzanie otrzymanych wyników
poprzez porównanie z arbitralnie
poprzez porównanie z arbitralnie
określonymi wartościami.
określonymi wartościami.
Testowane są metody, konstruktory,
Testowane są metody, konstruktory,
klasy.
klasy.
8
8
import junit.framework.TestCase;
import junit.framework.TestCase;
public class SampleTest extends TestCase {
public class SampleTest extends TestCase {
private java.util.List emptyList;
private java.util.List emptyList;
/**
/**
* Sets up the test fixture.
* Sets up the test fixture.
* (Called before every test case method.)
* (Called before every test case method.)
*/
*/
protected void setUp() {
protected void setUp() {
emptyList = new java.util.ArrayList();
emptyList = new java.util.ArrayList();
}
}
/**
/**
* Tears down the test fixture.
* Tears down the test fixture.
* (Called after every test case method.)
* (Called after every test case method.)
*/
*/
protected void tearDown() {
protected void tearDown() {
emptyList = null;
emptyList = null;
}
}
public void testSomeBehavior() {
public void testSomeBehavior() {
assertEquals("Empty list should have 0 elements", 0,
assertEquals("Empty list should have 0 elements", 0,
emptyList.size());
emptyList.size());
}
}
public void testForException() {
public void testForException() {
try {
try {
Object o = emptyList.get(0);
Object o = emptyList.get(0);
fail("Should raise an IndexOutOfBoundsException");
fail("Should raise an IndexOutOfBoundsException");
}
}
catch (IndexOutOfBoundsException success) {}
catch (IndexOutOfBoundsException success) {}
}}
}}
Przykład:
9
9
Przykładowa klasa wykonująca operacje
matematyczne na różnych
walutach.
class Money {
private int fAmount;
private String fCurrency;
public Money(int amount, String
currency) {
fAmount= amount;
fCurrency= currency;
}
public int amount() {
return fAmount;
}
public String currency() {
return fCurrency;
}}
10
10
Implementacja metody
klasy Money dodającej
waluty.
public Money add(Money m) {
return new Money(amount()
+m.amount(), currency());
}
11
11
Klasa testowa,
Klasa testowa,
rozszerzająca TestCase
rozszerzająca TestCase
public class MoneyTest extends TestCase {
//…
public void testSimpleAdd() {
Money m12CHF= new Money(12, "CHF"); // (1)
Money m14CHF= new Money(14, "CHF");
Money expected= new Money(26, "CHF");
Money result= m12CHF.add(m14CHF); // (2)
Assert.assertTrue(expected.equals(result)); // (3)
}}
12
12
Metoda porównująca w
Metoda porównująca w
klasie Money
klasie Money
public boolean equals(Object anObject) {
if (anObject instanceof Money) {
Money aMoney= (Money)anObject;
return aMoney.currency().equals(currency())
&& amount() == aMoney.amount();
}
return false;
}
13
13
Testowanie metody
Testowanie metody
porównującej
porównującej
public void testEquals() {
Money m12CHF= new Money(12, "CHF");
Money m14CHF= new Money(14, "CHF");
Assert.assertTrue(!m12CHF.equals(null));
Assert.assertEquals(m12CHF, m12CHF);
Assert.assertEquals(m12CHF, new
Money(12, "CHF")); // (1)
Assert.assertTrue(!
m12CHF.equals(m14CHF));
}
14
14
Metody setUp i tearDown
Metody setUp i tearDown
public void testEquals() {
Assert.assertTrue(!f12CHF.equals(null));
Assert.assertEquals(f12CHF, f12CHF);
Assert.assertEquals(f12CHF, new Money(12, "CHF"));
Assert.assertTrue(!f12CHF.equals(f14CHF));
}
public void testSimpleAdd() {
Money expected= new Money(26, "CHF");
Money result= f12CHF.add(f14CHF);
Assert.assertTrue(expected.equals(result));
}
15
15
Statyczne uruchamianie
Statyczne uruchamianie
testu
testu
TestCase test= new
MoneyTest("simple add") {
public void runTest() {
testSimpleAdd();
}
};
16
16
Dynamiczne
Dynamiczne
uruchamianie testu
uruchamianie testu
TestCase test= new
MoneyTest("testSimpleAdd");
17
17
Program uruchamiający
Program uruchamiający
testy
testy
import junit.framework.*;
public class DoTests {
public static void main (String[] args) {
junit.textui.TestRunner.run (suite());
}
public static Test suite ( ) {
return new TestSuite(MoneyTest.class);
}
}
18
18
Test suite: dynamicznie
Test suite: dynamicznie
public static Test suite() {
TestSuite suite= new TestSuite();
suite.addTest(new MoneyTest("testEquals"));
suite.addTest(new MoneyTest("testSimpleAdd"));
return suite;
}
public static Test suite() {
return new TestSuite(MoneyTest.class);
}
19
19
Test suite: statycznie
Test suite: statycznie
public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTest(
new MoneyTest("money equals") {
protected void runTest() { testEquals(); }
}
);
suite.addTest(
new MoneyTest("simple add") {
protected void runTest() { testSimpleAdd(); }
}
);
return suite;
}
20
20
Uwagi
Uwagi
Nowy test należy utworzyć w momencie, gdy chcemy wpisać daną zmienną
do debugger’a lub użyć print do jej wyświetlenia na ekranie.
Początkowo pisanie testów wymaga sporego nakładu pracy, jednak z
biegiem pisania nakład czasu na dodawanie testów maleje (nie trzeba
deklarować nowych zmiennych, itp).
Nie trzeba pisać wszystkich testów, tylko te, które mogą spowodować
błędy.
Do debuggowania błędów pisze się testy, które gwarantują poprawność
wykonania operacji i następnie poprawia program, aż do momentu uzyskania
tego poprawnego działania.
W czasie pisania kodów warto najpierw napisać test, dopiero później
implementować metodę.
Test suite trzeba utrzymywać w odpowiednim stanie (z czasem może być
on
za duży, żeby uruchamiać go za każdym razem). Wskazana jest
hierarchizacja testów.
Testowanie prowadzi do oszczędności czasu (nie traci się czasu na
poprawianie błędów).
Testowanie ułatwia znajdowanie błędów.
Testowanie jest bardzo ważne w zastosowaniach komercyjnych.
21
21
Bibliografia
Bibliografia
Wikipedia.org
Wikipedia.org
JUnit.org
JUnit.org
http://zgk.wi.ps.pl/data/Wyklad_JUNIT
http://zgk.wi.ps.pl/data/Wyklad_JUNIT