CS 149 Fall 2018 - Instructor: Molloy Sections: 10 and 11

Home
Calendar
Syllabus
Resources
Linux Install

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.

Computer bug image

The first computer bug (see Grace Hopper)

 

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

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.)

Test Class - JUnit 4 tests


import org.junit.Assert; 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);       Assert.assertEquals(expected, actual, .00001);      }      @Test public void testSubtract() {          double expected;          double actual;          expected = 2.2;          actual = BasicMath.subtract(3.5, 1.3);          Assert.assertEquals(expected, actual, .00001);      } }

Note in the above example:

Configuring jGRASP to use JUnit

  1. Download the junit5 jar file.
  1. Start jGRASP and select "Tools -> JUnit -> Configure". For "JUnit Home" select the directory where you stored the .jar file.

If all went well the "Create JUnit test file" button JUnit Test 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

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


public class BasicMathTest {


   /** Fixture initialization (common initialization
    *  for all tests). **/
   @Before public void setUp() {
   }


   /** A test that always fails. **/
   @Test public void defaultTest() {
      Assert.assertEquals("Default test added by jGRASP. Delete "
            + "this test once you have added your own.", 0, 1);
   }
}

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.

To pass all tests in Autolab for Coverage you may need to write a test for main like this:

/** 
 * Main test.
 */
    @Test public void testBasicMath() {
        new BasicMath();
    }

[OPTIONAL] Part 3 not graded: 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 'm':
                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:
    Assert.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.

Acknowledgements: This lab was oringinally rewritten for JGrasp by Nathan Sprague.