There seems to be some repeated questions about using JUnit. So I made a short example using JUnit 4 with ant.
First here is the directory structure of my files.
build build/build.sh build/build.xml lib lib/hamcrest-core-1.3.jar lib/junit-4.11.jar src src/org src/org/javachannel src/org/javachannel/SimulatedSpring.java test test/org test/org/javachannel test/org/javachannel/SimulatedSpringTest.java
The class I want to test is a simulation of a mass on a spring:
package org.javachannel;
public class SimulatedSpring{
public double velocity = 0;
public double position = 0;
public double time = 0;
private double kom;
private double bom;
private double A,B,omega;
public SimulatedSpring(double mass, double friction, double xnot){
kom = 1/mass;
bom = friction/mass;
position = xnot;
omega = Math.sqrt(kom - bom*bom*3.0/4.0);
B = xnot;
A = 0.5*bom/omega*xnot;
}
public void update(double dt){
// ma = -kx - bv
double a = -position*kom - bom*velocity;
// v_n+1 = v_n + a
velocity = velocity + a*dt;
position = position + velocity*dt;
time+=dt;
}
public double exactPosition(){
return Math.exp(-0.5*bom*time)*(A*Math.sin(omega*time) + B*Math.cos(omega*time));
}
public double exactVelocity(){
return -Math.exp(-0.5*bom*time)*(0.5*bom*A+omega*B)*Math.sin(omega*time);
}
public static void main(String[] args){
SimulatedSpring spring = new SimulatedSpring(1, 0.1, 1);
SimulatedSpring s2 = new SimulatedSpring(1, 0.1, 1);
double dt =0.5;
double time = 0;
int sub_divisions = 32;
for(int j = 0; j<100; j++){
System.out.printf("%f\t%f\t%f\t%f\t%f\t%f\t%f",
time, spring.position, s2.position, spring.exactPosition(),
spring.velocity, s2.velocity, spring.exactVelocity()
);
spring.update(dt);
for(int i = 0; i<sub_divisions; i++){
s2.update(dt/sub_divisions);
}
time+=dt;
}
}
}
The class contains an update method that updates the spring and the exact solutions. The test is to show that the update method improves when a smaller timestep is used.
package org.javachannel;
import org.junit.Test;
import org.junit.Assert;
public class SimulatedSpringTest{
@Test
public void updateTest(){
SimulatedSpring s1 = new SimulatedSpring(1, 1, 1);
SimulatedSpring s2 = new SimulatedSpring(1,1,1);
double dt = 0.5;
int sub = 2;
double delta_s1 = 0;
double delta_s2 = 0;
for(int j = 0; j<10; j++){
s1.update(dt);
for(int i=0; i<sub; i++){
s2.update(dt/sub);
}
delta_s1 += Math.abs(s1.position - s1.exactPosition()) + Math.abs(s1.velocity - s1.exactVelocity());
delta_s2 += Math.abs(s2.position - s2.exactPosition()) + Math.abs(s2.velocity - s2.exactVelocity());
}
Assert.assertTrue(delta_s2<delta_s1 || (delta_s2==0 && delta_s1==0));
}
}
I have two ways to build and test these classes, the first method is using just a bash script:
#!/bin/bash if [ ! -d "../out" ]; then mkdir ../out fi if [ ! -d "../out/classes" ]; then mkdir ../out/classes fi if [ ! -d "../out/tests" ]; then mkdir ../out/tests fi CLASSPATH="-cp ../out/classes:../out/tests:../lib/hamcrest-core-1.3.jar:../lib/junit-4.11.jar" javac -sourcepath ../src -d ../out/classes ../src/org/javachannel/SimulatedSpring.java javac -sourcepath ../test $CLASSPATH -d ../out/tests ../test/org/javachannel/SimulatedSpringTest.java java $CLASSPATH org.junit.runner.JUnitCore org.javachannel.SimulatedSpringTest
The second way consists of using an ant build.xml file.
<project> <property name="lib.dir"Â Â Â Â value="../lib"/> <property name="src.dir" value="../src"/> <property name="test.dir" value="../test"/> <property name="out.dir" value="../out"/> <property name="class.dir" value="classes"/> <target name="clean"> <delete dir="${out.dir}"/> </target> <target name="compile"> <mkdir dir="${out.dir}/${class.dir}"/> <javac srcdir="${src.dir}" destdir="${out.dir}/${class.dir}"/> </target> <target name="compile.tests" depends="compile"> <mkdir dir="${out.dir}/${test.dir}"/> <javac srcdir="${test.dir}" destdir="${out.dir}/${test.dir}"> <classpath> <pathelement path="${out.dir}/${class.dir}"/> </classpath> </javac> <junit> <classpath> <pathelement path="${out.dir}/${class.dir}"/> <pathelement path="${out.dir}/${test.dir}"/> </classpath> <test name="org.javachannel.SimulatedSpringTest"/> </junit> </target> </project>
Turns out my version of ant comes with junit 4 and I did not have to use the jar files I included in libs.
To use the build script navigate to the build folder and run (you would have to make it executable):
./build.sh
To use the ant build.xml navigate to the build folder and run:
ant compile.tests
Voila, maybe this could be improved by having a maven example. Also, when the test passes nothing is displayed.