CIT 590 Unit Testing in Java
Spring 2015, David Matuszek

Why JUnit?

JUnit is the original testing framework, since copied by every other major programming language.

In a sense, the purpose of JUnit testing is to reduce the number of bugs in the final code. Even more importantly, however, extensive use of JUnit, particularly in combination with Test Driven Development, results in substantially better code quality.

JUnit versions

There are two versions of JUnit currently available: JUnit 3 and JUnit 4. Python's unittest is slightly out of date, as it is based on JUnit 3. The most important difference is that JUnit 4 uses annotations (words beginning with @). You should use JUnit 4 for your assignments.

JUnit 4

import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;

Your class can extend any other class you like (Object is the default).
You can annotate a method with @Before, like this:
@Before
public void setUp() throws Exception

and it will be executed before every test. The method can have any name (but it's commonly still named setUp).

You can create as many test methods as you like, but:

  • The method must be annotated with @Test ,
  • The method must take no parameters, and
  • The method must return void.
You can specify that a test method should get an exception with the annotation
@Test(expected = ArithmeticException.class)
(or whatever kind of Exception you are expecting).
You can set a limit on how many milliseconds a test method is allowed to take with the annotation
@Test(timeout = 1000)
To execute a JUnit method after each test method, annotate it with
@After.
(This is rarely used.)

There about 40 tests that you can use in your test methods; see http://junit.org/javadoc/latest/org/junit/Assert.html. Here are the ones that I have found to be the most useful.

assertEquals(expected, actual)
Asserts that the actual value equals the expected value. Both expected and actual must be the same type (for example, you cannot test an int against a double). If the two parameters are objects of a class that you have created, the test will use your public boolean equals(Object o) method (or == if you haven't defined equals, which is almost certainly not what you want!).
assertArrayEquals(expectedArray, actualArray)
Like assertEquals, but for arrays. If the elements of the arrays are objects of a class that you have created, the test will use the equals method for that class.
assertEquals(expected, actual, delta)
Asserts that two doubles or floats are equal to within a positive delta.
assertTrue(booleanCondition)
Asserts that the booleanCondition evaluates to true.
assertFalse(booleanCondition)
Asserts that the booleanCondition evaluates to false.
assertNull(object)
Asserts that the object is null.
assertNotNull(object)
Asserts that the object isn't null.
assertSame(expected, actual)
Asserts that the actual argument is another reference to the expected object.
assertNotSame(unexpected, actual)
Asserts that the actual argument is not another reference to the unexpected object.
fail(message)
Causes the test to fail.

Very brief example

BalancedTernary.java BalancedTernaryTest.java
package balancedTernary;

public class BalancedTernary {

    // Declare instance variables here
    private String bt;
    
    // Define a constructor or two
    public BalancedTernary(String bt) {
        this.bt = bt;
    }
    
    // Write some methods
    public BalancedTernary add(BalancedTernary bt2) {
        return null;
    }
}
The add method above is a stub--it's enough to start creating
the test, but it's certainly returning the wrong answer. The method
should compute and return a BalancedTernary.
package balancedTernary;

import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;

public class BalancedTernaryTest {

    @Before
    public void setUp() throws Exception {
        // Stuff to do before every test
    }

    @Test
    public final void testBalancedTernary() {
        fail("Not yet implemented"); // TODO
    }

    @Test
    public final void testAdd() {
        fail("Not yet implemented"); // TODO
    }
}