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.

Updating a JProgressBar

This is a “simple” example of how to update a progress bar in a Swing application.

package org.javachannel;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
 * Created by odinsbane on 9/22/14.
 *
 * This is a quick example of a progress bar that updates.
 *
 * This code is distributed as is; without warranty; or guarantee. It can
 * be freely used, modified and distributed without attribution.
 */
public class ProgressBarExample {
  ExecutorService service = Executors.newSingleThreadExecutor();
  /**
   * Sets up the gui, which is just a JFrame, JButton and a JProgressBar.
   */
  private void buildGui() {
    JFrame frame = new JFrame("progress bar example");
    final JButton start = new JButton("start");
    final JProgressBar progress = new JProgressBar();
    start.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent evt) {
            start.setEnabled(false);
            //starts long running task off of EDT.
            service.submit(new Runnable() {
              public void run() {
                for (int i = 0; i < 100; i++) {
                  //the portion of work.
                  try {
                    Thread.sleep(10);
                  } catch (InterruptedException e1) {
                    //this might be a good spot to quit working.
                    e1.printStackTrace();
                  }
                  //update the progress bar on the EDT.
                  final int j = i;
                  EventQueue.invokeLater(new Runnable() {
                    public void run() {
                      progress.setValue(j);
                    }
                  });
                }
                //work finished.
                EventQueue.invokeLater(new Runnable() {
                  public void run() {
                    progress.setValue(100);
                    start.setEnabled(true);
                  }
                });
              }
            });
          }
        }
    );
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setLayout(new FlowLayout());
    frame.add(start);
    frame.add(progress);
    frame.pack();
    frame.setVisible(true);
  }
  public static void main(String[] args) {
    ProgressBarExample example = new ProgressBarExample();
    //ALL gui work should be managed on the EDT.
    EventQueue.invokeLater(new Runnable() {
      public void run() {
        example.buildGui();
      }
    });
  }
}

In this example, the ‘start’ button begins a ‘long-running’ task. The task is started using an ActionListener, which starts the task on the Event Dispatch Thread (EDT). So the first thing to do is to ‘send’ the task to another thread, this is done by creating a Runnable and submitting the Runnable to the ExecutorService service.
As the task runs the progress bar needs to be updated; this should be performed on the EDT. By creating a new Runnable and submitting via EventQueue.invokeLater(), the task will be executed when Swing gets a chance, and the working thread will continue without waiting.
A small caveat is that the ‘start’ button is disabled during execution, and enabled when the task is completed. This is because when we fire the task on another thread, the EDT is not blocked and you could press the button again rather than waiting.
These concepts can still be applied to JavaFX type applications, although the environment’s obviously different and will involve some important changes – for example, you’d use Platform.runLater() instead of EventQueue.invokeLater().
Here’s an example of an equivalent program, using JavaFX instead. The layout isn’t an exact match, even with the equivalence of controls, thanks to the Scene not being packed like the JFrame is.
This example code relies on Java 8 and the use of lambdas, which shortens the code but remains equivalent:

package org.javachannel;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class JavaFXProgressBarExample extends Application {
  ExecutorService service = Executors.newSingleThreadExecutor();
  public static void main(String[] args) {
    launch(args);
  }
  @Override
  public void start(Stage primaryStage) throws Exception {
    primaryStage.setTitle("progress bar example");
    ProgressBar progress = new ProgressBar();
    progress.setProgress(0.0);
    Button start = new Button();
    start.setText("start");
    start.setOnAction(event -> {
      service.submit(() -> {
        Platform.runLater(() -> start.setDisable(true));
        for (int i = 0; i < 100; i++) {
          //the portion of work.
          try {
            Thread.sleep(10);
          } catch (InterruptedException e1) {
            //this might be a good spot to quit working.
            e1.printStackTrace();
          }
          final double j = i / 100.0;
          Platform.runLater(() -> progress.setProgress(j));
        }
        Platform.runLater(() -> progress.setProgress(1.0));
        Platform.runLater(() -> start.setDisable(false));
      });
    });
    FlowPane root = new FlowPane();
    root.getChildren().add(start);
    root.getChildren().add(progress);
    primaryStage.setScene(new Scene(root, 250, 40));
    primaryStage.show();
  }
}