≡ Menu

Junit 4 examples

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.

Comments on this entry are closed.