Yolinux.com Tutorial

JUnit: Java unit test framework

JUnit is a Java test framework for classes. JUnit has integrated support for many Java IDEs and continuous integration systems like Jenkins.

Tutorial Table of Contents:

Related YoLinux Tutorials:

°Java Linux tutorial

°Java WAR file tutorial

°Apache Tomcat

°IBM Websphere

°Jenkins CI

°YoLinux Tutorials Index




Free Information Technology Magazines and Document Downloads
TradePub link image


JUnit Installation:

This tutorial assumes that you have Java installed on your system.
For more on installing Java and setting up your classpath see the YoLinux.com Java tutorial.

Download a prebuilt JUnit jar file: http://www.junit.org eg. junit-4.9b2.jar

Place the JUnit jar file where accessible: (examples)
  • Linux: /opt/java/lib/ or /usr/java/latest/lib/
  • MS/Windows: C:\Java\lib\ or C:\Program Files\Java\jdk1.6.0_26\lib\

Add the JUnit jar file to your Java class path (environment variable or set in ant build script).
In this tutorial we will be using an ANT build script.


Project Source Hierarchy:

The build path used in this example is as follows:

ProjectX/build.xml
        /src/com/megacorp/projx/util/Addition.java
        |                           /Multiply.java
        /test/src/com/megacorp/projx/JUnit/AllTests.java
        /test/src/com/megacorp/projx/util/Addition_Test.java
        |    |                           /Multiply_Test.java
        |    /htmlreports/index.html                           (generated by JUnit)
        |    |           /com/megacorp/projx/JUnit/            (unit test reports end up here)
        /    /data/TEST-com.megacorp.projx.JUnit.AllTests.xml  (generated by JUnit)
Notes:
  • JUnit can generate reports in various formats. HTML reports are directly viewable in a browser with links to the individual reports. XML output is often used as an iinterface with other systems like Jenkins.
  • The unit test source mimics the source tree and class names.


JUnit Example:

Example Java Class to Test:

File: src/com/megacorp/projx/util/Addition.java
package com.megacorp.projx.util;

import java.text.*;

public class Addition
{

    public static int twoValues(int x, int y)
    {
        return x + y;
    }
}

File: src/com/megacorp/projx/util/Multiply.java
package com.megacorp.projx.util;

import java.text.*;

public class Multiply
{

    public static int twoValues(int x, int y)
    {
        return x * y;
    }
}

JUnit unit test source:

  • Class to specify tests to run: AllTests.java
  • Classes to perform the unit tests:
    • Addition_Test.java
    • Multiply_Test.java
File: test/src/com/megacorp/projx/JUnit/AllTests.java
package com.megacorp.projx.JUnit;

import org.junit.runner.RunWith;
import org.junit.runners.Suite;

import com.megacorp.projx.util.Addition_Test;
import com.megacorp.projx.util.Multiply_Test;

@RunWith(Suite.class)
@Suite.SuiteClasses({Addition_Test.class,Multiply_Test.class})
public class AllTests
{
    // Empty, since the annotations include all of the necessary configuration
}

File: test/src/com/megacorp/projx/util/Addition_Test.java
package com.megacorp.projx.util;

import java.io.IOException;
import java.io.PrintWriter;
import junit.framework.TestCase;
import com.megacorp.projx.util.Addition;
import com.megacorp.projx.util.Multiply;

public class Addition_Test extends TestCase
{
    private int x = 0;
    private int y = 0;
 
    // Stuff to do before test
    protected void setUp()
    {
        x = 4;
        y = 5;
    }

    // Stuff to do after test
    protected void tearDown()
    {
        x = 0;
        y = 0;
    }

    public void testAddition()
    {
        System.out.println("Test use of Addition class");

        int z = Addition.twoValues(x,y);
        System.out.println("    Result: " + z);

        assertEquals(9,z);  // The test
    }
}

File: test/src/com/megacorp/projx/util/Multiply_Test.java
package com.megacorp.projx.util;

import java.io.IOException;
import java.io.PrintWriter;
import junit.framework.TestCase;
import com.megacorp.projx.util.Addition;
import com.megacorp.projx.util.Multiply;

public class Multiply_Test extends TestCase
{
    private int x = 0;
    private int y = 0;

    protected void setUp()
    {
        x = 4;
        y = 5;
    }

    protected void tearDown()
    {
        x = 0;
        y = 0;
    }

    public void testMultiply()
    {
        System.out.println("Test use of Multiply class");

        int z = Multiply.twoValues(x,y);
        System.out.println("    Result: " + z);

        assertEquals(20,z);
    }
}

Ant file to compile and run a JUnit test:

File: ./build.xml
<?xml version="1.0" encoding="UTF-8"?>
<project name="projx" default="all" basedir=".">
    <description>Builds, tests, and runs projx</description>
    <property name="build.dir" value="./"/>
    <property name="src.dir" location="${build.dir}/src"/>
    <property name="test.dir" location="${build.dir}/test/src"/>
    <property name="test.htmlreports.dir" location="${build.dir}/test/htmlreports"/>
    <property name="test.data.dir" location="${build.dir}/test/data"/>
    <property name="junit.class.name" value="com.megacorp.projx.JUnit.AllTests"/>

    <!-- Classpath to find java packages -->
    <path id="classpath.base">
      <pathelement location="/usr/java/latest/lib/tools.jar" />
    </path>

    <!-- Classpath for tests to find src packages -->
    <path id="classpath.src">
      <pathelement location="src" />
    </path>

    <path id="classpath.junittest">
       <path refid="classpath.base" />
       <pathelement location="/opt/java/lib/junit-4.9b2.jar" />
       <pathelement location="${test.dir}" />
    </path>

    <target name="clean" description="Remove all .class files">
      <delete includeEmptyDirs="true" failonerror="false">
        <fileset dir="${src.dir}">
          <include name="**/*.class"/>
        </fileset>
        <fileset dir="${test.dir}">
          <include name="**/*.class"/>
        </fileset>
        <fileset dir="${test.htmlreports.dir}">
          <include name="**/*.txt"/>
          <include name="**/*.xml"/>
          <include name="**/*.html"/>
        </fileset>
      </delete>
    </target>

    <target name="compile">
      <javac srcdir="${src.dir}" destdir="${src.dir}" debug="true" includeAntRuntime="false">
        <classpath refid="classpath.base"/>
        <include name="**/*.java"/>
      </javac>
    </target>

    <target name="compile-test" depends="compile">
      <javac srcdir="${test.dir}" destdir="${test.dir}" debug="true" includes="${src.dir}" includeAntRuntime="false">
        <classpath refid="classpath.base"/>
        <classpath refid="classpath.src"/>
        <classpath refid="classpath.junittest"/>
        <include name="**/*.java"/>
      </javac>
    </target>

    <target name="test" depends="compile-test">
      <mkdir dir="${test.data.dir}"/>
      <mkdir dir="${test.htmlreports.dir}"/>
      <junit fork="no" haltonfailure="no" showoutput="yes" printsummary="true">
        <test name="${junit.class.name}" todir="${test.data.dir}"/>
        <formatter type="brief" usefile="false"/>
        <formatter type="xml"/>
        <classpath refid="classpath.base" />
        <classpath refid="classpath.src" />
        <classpath refid="classpath.junittest" />
      </junit>
      <junitreport todir="${test.htmlreports.dir}">
        <fileset dir="${test.data.dir}">
          <include name="TEST-*.xml"/>
        </fileset>
        <report format="frames" todir="${test.htmlreports.dir}"/>
      </junitreport>
    </target>

    <target name="all" depends="compile-test" />

</project>

Building and running unit tests:
  • Build: ant
  • Test: ant test
[bash JUnit]$ ant clean
Buildfile: /home/user1/JUnit/build.xml

clean:

BUILD SUCCESSFUL
Total time: 0 seconds
[bash JUnit]$ ant test
Buildfile: /home/user1/JUnit/build.xml

compile:
    [javac] Compiling 2 source files to /home/user1/JUnit/src

compile-test:
    [javac] Compiling 3 source files to /home/user1/JUnit/test/src

test:
    [junit] Running com.megacorp.projx.JUnit.AllTests
    [junit] Testsuite: com.megacorp.projx.JUnit.AllTests
    [junit] Test use of Addition class
    [junit]     Result: 9
    [junit] Test use of Multiply class
    [junit]     Result: 20
    [junit] Tests run: 2, Failures: 0, Errors: 0, Time elapsed: 0.019 sec
    [junit] Tests run: 2, Failures: 0, Errors: 0, Time elapsed: 0.019 sec
    [junit] 
    [junit] ------------- Standard Output ---------------
    [junit] Test use of Addition class
    [junit]     Result: 9
    [junit] Test use of Multiply class
    [junit]     Result: 20
    [junit] ------------- ---------------- ---------------
[junitreport] Processing /home/user1/JUnit/test/htmlreports/TESTS-TestSuites.xml to /tmp/null1813236
[junitreport] Loading stylesheet jar:file:/opt/apache-ant-1.8.2/lib/ant-junit.jar ! 
 /org/apache/tools/ant/taskdefs/optional/junit/xsl/junit-frames.xsl
[junitreport] Transform time: 315ms
[junitreport] Deleting: /tmp/null1813236

BUILD SUCCESSFUL
Total time: 1 second


JUnit reporting:

JUnit HTML Results Report:
JUnit HTML report
View JUnit results with browser by opening file ./test/htmlreports/index.html


Continuous Integration with Jenkins:

Jenkins configuration to run JUnit:

Jenkins/Hudson JUnit configuration
Configuration

For more, see the YoLinux.com Jenkins tutorial


Links:


Books:

"JUnit in Action"
by Petar Tahchiev, Felipe Leme, Vincent Massol, Gary Gregory
ISBN # 1935182021, Manning Publications; Second Edition edition (August 4, 2010)

JUnit testing including J2EE. Covers JUnit framework and extensions.

Amazon.com
"Core Java 2, Volume 1: Fundamentals "
by Cay S. Horstmann, Gary Cornell
ISBN # 0132354764, Prentice Hall PTR 8th edition

The industry standard. Need I say more?

Amazon.com
"Core Java 2: Volume 2 Advanced Features "
by Cay S. Horstmann, Gary Cornell
ISBN # 0132354799, Prentice Hall PTR 8th edition

The industry standard. Need I say more?

Amazon.com

   

    Bookmark and Share


Advertisements





Copyright © 2011 -2013 by Greg Ippolito