Wednesday, November 15, 2017

JUnit4 - Getting started

This small example shows you how to write a unit test. You need to have a JDK installed and a text editor. (In general it is recommended to use a build tool (Maven, Gradle, Ant...) for building your software and running the tests.)

Preparation

Create a new folder junit-example and download the current junit-4.XX.jar from JUnit's release page and Hamcrest to this folder. Change to the folder junit-example. All files are created within this folder and all commands are executed there, too.

Create the class under test

Create a new file Calculator.java and copy the following code to this file.
public class Calculator {
  public int evaluate(String expression) {
    int sum = 0;
    for (String summand: expression.split("\\+"))
      sum += Integer.valueOf(summand);
    return sum;
  }
}
Now compile this class:
javac Calculator.java
The Java compiler creates a file Calculator.class.

Create a test

Create the file CalculatorTest.java and copy the following code to this file.
import static org.junit.Assert.assertEquals;
import org.junit.Test;

public class CalculatorTest {
  @Test
  public void evaluatesExpression() {
    Calculator calculator = new Calculator();
    int sum = calculator.evaluate("1+2+3");
    assertEquals(6, sum);
  }
}
Compile the test. On Linux or MacOS
javac -cp .:junit-4.XX.jar:hamcrest-core-1.3.jar CalculatorTest.java
and on Windows
javac -cp .;junit-4.XX.jar;hamcrest-core-1.3.jar CalculatorTest.java
The Java compiler creates a file CalculatorTest.class.

Run the test

Run the test from the command line. On Linux or MacOS
java -cp .:junit-4.XX.jar:hamcrest-core-1.3.jar org.junit.runner.JUnitCore CalculatorTest
and on Windows
java -cp .;junit-4.XX.jar;hamcrest-core-1.3.jar org.junit.runner.JUnitCore CalculatorTest
The output is
JUnit version 4.12
.
Time: 0,006

OK (1 test)
The single . means that one test has been run and the OK in the last line tells you that your test is successful.

Let the test fail

Modify Calculator.java in order to get a failing test. Replace the line
sum += Integer.valueOf(summand);
with
sum -= Integer.valueOf(summand);
and recompile the class.
javac Calculator.java
Run the test again. On Linux or MacOS
java -cp .:junit-4.XX.jar:hamcrest-core-1.3.jar org.junit.runner.JUnitCore CalculatorTest
and on Windows
java -cp .;junit-4.XX.jar;hamcrest-core-1.3.jar org.junit.runner.JUnitCore CalculatorTest
Now the test fails and the output is
JUnit version 4.12
.E
Time: 0,007
There was 1 failure:
1) evaluatesExpression(CalculatorTest)
java.lang.AssertionError: expected:<6> but was:<-6>
  at org.junit.Assert.fail(Assert.java:88)
  ...

FAILURES!!!
Tests run: 1,  Failures: 1
JUnit tells you which test failed (evaluatesExpression(CalculatorTest)) and what went wrong:
java.lang.AssertionError: expected:<6> but was:<-6>

JUnit

JUnit is a unit testing framework for the Java programming language. JUnit has been important in the development of test-driven development, and is one of a family of unit testing frameworks which is collectively known as xUnit that originated with SUnit.
JUnit is linked as a JAR at compile-time; the framework resides under package junit.framework for JUnit 3.8 and earlier, and under package org.junit for JUnit 4 and later.
A research survey performed in 2013 across 10,000 Java projects hosted on GitHub found that JUnit, (in a tie with slf4j-api), was the most commonly included external library. Each library was used by 30.7% of projects. [3]

Contents

Example of JUnit test fixture

A JUnit test fixture is a Java object. With older versions of JUnit, fixtures had to inherit from junit.framework.TestCase, but the new tests using JUnit 4 should not do this.[4] Test methods must be annotated by the @Test annotation. If the situation requires it,[5] it is also possible to define a method to execute before (or after) each (or all) of the test methods with the @Before (or @After) and @BeforeClass (or @AfterClass) annotations.[4]
import org.junit.*;

public class FoobarTest {
    @BeforeClass
    public static void setUpClass() throws Exception {
        // Code executed before the first test method
    }

    @Before
    public void setUp() throws Exception {
        // Code executed before each test
    }
 
    @Test
    public void testOneThing() {
        // Code that tests one thing
    }

    @Test
    public void testAnotherThing() {
        // Code that tests another thing
    }

    @Test
    public void testSomethingElse() {
        // Code that tests something else
    }

    @After
    public void tearDown() throws Exception {
        // Code executed after each test 
    }
 
    @AfterClass
    public static void tearDownClass() throws Exception {
        // Code executed after the last test method 
    }
}

Unit Testing