More about JUnit

Improving the output

Test cases should be short and focused on testing a single fact about the class under test. It is important to document each test case with a brief statement stating what is being tested. You can see an example of this in the inline comments in BasketballExample.

When using JUnit, it is easy to make such comments part of the output produced when a test fails. In each one of the assertEquals methods we can optionally provide a string message. If the test fails, this string will be printed along with the expected and actual values. Here is an example.

    @Test
    public void testInitialDiameter()
    {
      String msg = "A newly constructed basketball should have the diameter it was constructed with";
      Basketball b = new Basketball(5);
      assertEquals(msg, 5.0, b.getDiameter(), EPSILON);
    }
Now, when the test fails, the output from the failure trace includes the message explaining what was being tested.
A newly constructed basketball should have the diameter it was constructed with expected:<5.0> but was:<0.0>

Other assertion methods

The most useful methods are the various forms of assertEquals. (The third and fourth forms are the ones used for comparing floating-point numbers.) Remember that the expected value always comes first!

Sometimes you just want to assert that some boolean expression is true or not:

And sometimes you want to simply indicate that a test should simply fail if a certain point in the code is reached.

There are a few more that you will probably use only rarely, and you can find the details in the JUnit API documentation. (Look for the class org.junit.Assert.)

Before and After

You might notice in the BasketballTests class that we had to create a new Basketball at the beginning of each test case. Almost all test cases require some sort of initialization, usually the creation of one or more objects. If the setup is the same for many of test cases, you can use the @Before annotation to designate a method that the framework should run before each test case. For the BasketballTests example, we could do something like this. The setup method will automatically run before the execution of each test case to initialize the bb variable. This can save you from writing a lot of repetitive code.
package lab3;
import org.junit.Test;
import org.junit.Before;
import static org.junit.Assert.assertEquals;

public class BasketballTests2
{
    // margin of error for floating-point comparisons
    private static final double EPSILON = 10e-07;
 
    private Basketball bb;

    @Before    
    public void setup()  // runs before every test case
    {
      bb = new Basketball(5);
    }
    
    @Test
    public void testInitial()
    {
      assertEquals(false, bb.isDribbleable());
    }

    @Test
    public void testInitialDiameter()
    {
      assertEquals(5.0, bb.getDiameter(), EPSILON);
    }

    @Test
    public void testInflate()
    {
      bb.inflate();
      assertEquals(true, bb.isDribbleable());
    }

    @Test
    public void testDiameterAfterInflation()
    {
      bb.inflate();
      assertEquals(5.0, bb.getDiameter(), EPSILON);
    }
   
  }



Note that you'll need to add an import statement for org.junit.Before. Not surprisingly there is also an annotation @After that designates a method to run after each test case, but it is not nearly as useful as @Before.