/**
 * CS139 - Programming Fundamentals
 * Department of Computer Science
 * James Madison University
 * @version Spring 2016
 */

Program testing with JUnit

Background

One thing we've learned through decades of software engineering is that developing correct software is difficult! The best way to ensure correctness is to test thoroughly while software is being developed. JUnit is a framework that automates testing by providing a standard format for tests and an easy way to execute them (see JUnit FAQ). In today's lab, you will design and implement your own JUnit tests cases.

Collaboration: You are encouraged to work with another student to complete this lab.

Objectives

Key Terms

test class
A class that has the purpose of testing some other class, but is not part of the final application.
test method
A method that has the purpose of testing another method, but is not part of the final application.
assertion
A statement that should always be true. Assertions make claims about the expecte behavior of programs.

Part 0: Preparation

Watch this video on unit testing before proceeding with the rest of the lab. (Sorry about the sound quality.)

Part 1: Using JUnit for Testing

The basic JUnit pattern is simple:

Class Being Developed Test Class
public class BasicMath {

   public static double add(double x, double y) {
      double sum;
      sum = x + y;
      return sum;
   }

   public static double subtract(double x, double y) {
      double diff;
      diff = x - y;
      return diff;
   }

}
(Note: Javadoc comments have been omitted for compactness.)
import org.junit.Assert;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;

public class BasicMathTest {
     
   @Test public void testAdd() {
      double expected;
      double actual;
   
      expected = 15.5;
      actual = BasicMath.add(7.2, 8.3);
      assertEquals(expected, actual, .00001);
   }

   @Test public void testSubtract() {
      double expected;
      double actual;
   
      expected = 2.2;
      actual = BasicMath.subtract(3.5, 1.3);
      assertEquals(expected, actual, .00001);
   }
  
}

Note in the above example:

Configuring jGRASP to use JUnit

  1. Download the following two files:
  2. Start jGRASP and select "Tools -> JUnit -> Configure". For "JUnit Home" select the directory where you stored the two .jar files.

If all went well the "Create JUnit test file" button should now appear whenever you open a Java file in jGRASP. Clicking that button will auto-generate a starter test class with the appropriate imports.

Running JUnit in jGRASP

Part 2: Writing Basic Test Methods

It's generally not enough to test a method just once. To be sure that the method is correct, we need to test multiple times with multiple values.

Part 3: A More Complex Example (If Time)

Add the following code to the end of your BasicMath class, but don't look too carefully at the code itself. Your goal is to find the mistakes in calculateTax by writing test cases based on its documentation.

    /**
     * Calculate the tax on the given amount based on the following rules:
     *   If the taxType is 'X' or 'x' (exempt), then tax amount is zero.
     *   If the taxType is 'M' or 'm', then tax is 11% of the amount.
     *   If the taxType is 'F' or 'f', then tax is 2% of the amount.
     *   If the taxType is anything else, then tax is 5% of the amount.
     *
     * @param amount the amount of the sale
     * @param taxType type of items purchased
     * @return amount of tax
     */
    public static double calculateTax(double amount, char taxType) {
        double tax;
        switch (taxType) {
            case 'X':
            case 'x':
                tax = 0.0;
            case 'M':
            case 'n':
                tax = 0.11 * amount;
            case 'F':
            case 'f':
                tax = 0.2 * amount;
            default:
                tax = 0.5 * amount;
        }
        return tax;
    }
  1. Rather than write over a dozen test cases in a single method, create the following test methods:

    • testTypeX should test cases 'X' and 'x'
    • testTypeM should test cases 'M' and 'm'
    • testTypeF should test cases 'F' and 'f'
    • testOther should test "anything else"
  2. For each of the calculateTax test methods, write at least four test cases using assertEquals. Note that you can implement many of these assertions in one line of code, for example:

    assertEquals(0.0, BasicMath.calculateTax(1.99, 'X'));
  3. Run your test cases. If all your test methods are correct, all four of them should fail.

  4. OPTIONAL: Can you figure out how to fix calculateTax and get your test methods to pass? You may need to learn about The switch Statement in the Java tutorials.