Testowanie kodu
(naprawdę wszyscy to robią ;)
Po co
Po co zastanawiać się czy kod który napisałeś(aś) jest poprawny?
- Po co zastanawiać się czy zmiany nie zepsuły niczego innego?
- Inne argumenty.
Testy pozwalają szybko sprawdzić działanie programu.
Sprężyste zderzenia w (prawie) 1d
public class Ball {
private double[] coords = new double[6];
public Ball(double x, double y, double vx,
double vy, double mass, double radius){
coords = new double[]{x, y, vx, vy, mass, radius};
}
public void iteration(double dt){
coords[0]+=coords[2]*dt;
coords[1]+=coords[3]*dt;
}
Testy
public class BallTests {
@Test
public void testMove(){
Ball ball = new Ball(0, 0, 1, 2, 5, 1);
ball.iteration(0.1);
Assert.assertEquals(ball.getX(), 0.1, 0.001);
Assert.assertEquals(ball.getY(), 0.2, 0.001);
}
Wyjaśnienie
- @Test jest adnotacją (wyjaśnienie, tutorial)
- Informuje ona Framework JUnit że dana metoda jest metodą
testową - Taka metoda zostanie automatycznie wykonana podczas uruchamiania testów jednostkowych
- Test zostaje uznany za "zaliczony pozytywnie" jeśli zakończył się bez zgłaszania wyjątku
- Można sprawdzić różne zachowania programu za pomocą funkcji Assert.
Uruchomienie testów

Uruchamianie testów 2

Wyniki

- Wielki zielony napis że wszystko OK!
Klasa z metodami użytkowymi
public class BallUtils{
public static double distance(Ball b1, Ball b2){
return Math.sqrt(
Math.pow(
b1.getX()-b2.getX(), 2
) +
Math.pow(
b1.getY()-b2.getY(), 2
)
);
}
public static boolean overlaps(Ball b1, Ball b2){
return distance(b1, b2) <= (b1.getRadius() + b2.getRadius());
}
}
Testy
public class BallTests { ...
@Test
public void testDistance1(){
double distance = BallUtils.distance(
ballFromPositions(0, 0),
ballFromPositions(0, 1)
);
Assert.assertEquals(1.0, distance, 0.0001);
}
...
@Test
public void testOverlaps(){
Assert.assertTrue(BallUtils.overlaps(
ballFromPositions(0, 0, 1),
ballFromPositions(0, 0.5, 1)
));
}
Cykl życia testów
public class Engine {
private ArrayList<Ball> balls = new ArrayList<Ball>();
public void addBalls(Ball b){
balls.add(b);
}
public List<Ball> getBalls(){
return Collections.unmodifiableList(balls);
}
public void iterate(double dt){
for (int ii=0;ii<balls.size(); ii++){
Ball b1 = balls.get(ii);
for (int jj=ii+1; jj<balls.size(); jj++){
Ball b2 = balls.get(jj);
if (BallUtils.overlaps(b1, b2)){
b1.collision(b2);
}
}
b1.iteration(dt);
}
}
}
Cykl życia testów
public class CollisionTest{
Engine engine;
@Before
public void setUp(){
engine = new Engine();
engine.addBalls(new Ball(0, 0, 0, 1, 0, 1));
}
@Test
public void testNoCollision(){
engine.addBalls(new Ball(0, 3, 0, -2, 0, 1));
engine.iterate(0.1);
Assert.assertEquals(engine.getBalls().get(0).getVY(), 1, 0.01);
Assert.assertEquals(engine.getBalls().get(1).getVY(), -2, 0.01);
}
@Test
public void testCollision(){
engine.addBalls(new Ball(0, 2, 0, -2, 0, 1));
engine.iterate(0.1);
Assert.assertEquals(engine.getBalls().get(0).getVY(), -2, 0.01);
Assert.assertEquals(engine.getBalls().get(1).getVY(), 1, 0.01);
}
}
Cykl życia testów
- Test to każda metodą z adnotacją @Test
- przed każdym testem wykonywana jest metoda z adnotacją @Before
- po każdym teście wykonywalna jest metoda z adnotacją @After
Znajdź błąd

Zasady pisania testów
- Działanie testu A nie może zależeć od działania innych testów
- Każda ścieżka wykonania kodu powinna mieć jeden test
Jak dodać biblioteki unittestów
- Niestety biblioteka junit nie jest w JDK (trzeba ją oddzielnie pobrać)
- Na szczęście można ją bardzo łatwo dodać do projektu!



Można też dodać do projektu

Przykładowy projekt
- Do pobrania tutaj: https://github.com/jbzdak/pojava-unittest
Testowanie kodu
By Jacek Bzdak
Testowanie kodu
- 2,004