Unit Testing and JUnit

Work on this exercise by yourself, but ask questions of your instructor, student assistants and classmates as desired.

Goals

The goals of this exercise are to:

The Exercise

Background

Unit testing is simply testing each class or method of a class in isolation before combining it with the rest of a project. We will apply it to toy examples today, but recognize that we really see the benefits of unit testing when we have large projects that are maintained over a long period of time. Today, we are building a habit of mind and focus primarily on process, not code.

Instructions

  1. You will download some code that converts a String to Pig Latin (possibly with errors!). Pig Latin is translated "igPay atinLay". Words starting with a vowel get "way" appended to them, as in "excellentway".
  2. Brainstorm some words that you would want to test to catch errors (see the tips below). Discuss these with your instructor.
  3. Create a PigLatiner project and copy the PigLatiner.java file from Angel into your project.
  4. Write unit tests with JUnit. JUnit is built into Eclipse (and BlueJ).
    1. First, note that you do not need to write main(). Unit tests don't need main().
    2. Select the class for which you want to write tests. Then choose New → JUnit Test Case. If it asks about adding JUnit to the path, do so. Then select Next, select PigLatin's transform() method (the one you want to test), and select Finish.
    3. Now you have the stubs of a PigLatinTest class. You can run the test class by right-clicking, and choosing Run as → JUnit Test.
    4. It should bring up a screen with a red bar, showing that it failed. (Why?)
    5. Fill in the body of your method as follows. The static assertEquals() method from the Assert class takes two arguments that you want to check for equality. What should you pass to it? (ask if you need help)
    6. Answer to previous question: assertEquals("edfray", PigLatiner.transform("fred")). The first argument is the expected result; the second uses the method under test to try to obtain that result (Hint: It's not an error to swap the order of the arguments, but JUnit's output only makes sense if you give them in this order.)
    7. Run it to ensure the test is doing what it's supposed to. Then copy and paste to create as many new unit tests as you need.
    8. Try to use the output in the Failure Trace (bottom left-hand window) to determine the errors in the code.
    9. Keep fixing code and re-running tests until you get the code to pass all the tests.

Tips on writing unit tests

  1. Test as many types of cases you can think of.
  2. Test boundary cases (such as when a string only contains a single character)
  3. Test cases your program should reject or give special treatment (division by zero, empty strings, null pointers)
  4. Once your code is written, your tests should exercise all branches in the code tested.
  5. Use cases for which you can compute the desired result by hand, or via a simple inverse method (for example, to test a square root method, you can easily square the answer and compare it to the original).

Why are we learning unit testing?

Discuss this with your instructor!

Note, Weiss doesn't focus on testing. These ideas were taken from Horstmann’s BigJava and various other sources.