JUnit Testing with drJava


As homework for the 2008 AP Workshop with Barbara Ericson, we were asked to create several teacher resources. I decided to focus on programming assignments and "doing them right" (whatever that means!) In my case this meant creating pre-built tests to check the programs (using JUnit), and self-documenting code using Javadoc. Both of these are new topics for me, but I think will be invaluable in the classroom. I have included 4 different programming folders to meet the requirements of 4 assessments. WhileAndIf teaches how to use JUnit to test code. WhileAndIf-BadCode is the same code with a logic error, showing how JUnit reports the problem. ArrayExample assesses processing arrays AND how to properly document using Javadoc (see below). A JUnit testclass is supplied called TestArrayExample. BankAccount creates a BankAccount object and allows deposits and withdrawals to the account. A JUnit test called TestBankAccount exercises a few methods.

Introduction

Setting up JUnit in drJava

Walk through JUnit with working program

Walk through JUnit with broken program

Creating JUnit tests from scratch

Three JUnit Methods

More Info on JUnit

Javadoc

Introduction

For closed ended programs, JUnit can be used to easily test student programs for correct results. The process is as follows:

  1. Teacher gives careful instructions that include all relevant class names, method names, parameters, and returns.
  2. Teacher writes a JUnit Test program that checks the behavior. New objects are instantiated and exercised using the class calls. The results are then checked so that each test will either pass or fail.
  3. Student writes code.
  4. Student validates their code using the JUnit Test program. Teacher validates code using the JUnit Test program.
  5. This methodology includes great benefits:

    Each folder contains one assignment. The files include a Readme.htm file explaining the assignment, a sample solution, and a sample JUnit Test that will exercise the code.

    Setting up JUnit classes in drJava

    JUnit is not a standard Java library, so it may or may not already by available in your environment. If it is not, download it from http://www.junit.org/ --> select [Download JUnit] --> pick a jar file such as junit-4.1.jar. Store it in a known location.

    In drJava, select [Edit] --> [Preferences] --> [Resource Locations] --> [Add] --> and pick the file you download with a name similar to junit-4.1.jar.

    Walk through of a working program

    1. Open folder WhileAndIf\Readme.txt to see a description of the programming assignment.
    2. In drJava, open the file Salary.java for a working solution.
    3. In drJava, open the file named TestSalary.java (JUnit test will always be named TestXxxxxx.java)
    4. Click the button [Test] on the top toolbar (answer “Yes” for all programs to be compiled). This will execute each of the tests one at a time. A graphical result will be displayed in the lower right panel there is a bar called “Test Progress” that will display green or red depending on success or failure of the tests. 
    For more detailed results, look in the lower left panel and select the tab [Test Output]. This lists each test one-by-one and whether it succeeded (green) or failed (red). For any test that failed, detailed results are shown below. I have created an error message for any failed test that will help identify the problem. In addition, for failed tests JUnit display both the EXPECTED result (which I hardcoded) and the ACTUAL result that the program produced. Notice how Salary.java passes all the tests. If you look at the code in TestSalary, you’ll see it creates situations where no parameters are passed, different numbers of years are entered, etc.

    Walk through of a broken program

    To see what might happen if a student wrote incorrect code, Close All to close the current classes. Open the two files in WhileAndIf-Broken Code: Salary.java and TestSalary.java. In Salary’s calculateSalary method, I incorrectly calculated the new salary. Test it by pressing the [Test] button and you will see red results at the bottom of your window showing the problem. In this case, a 10% raise on a salary of $30000 should produce a Year 2 salary of $33,000, but it produces $3000 instead. This is because of a wrong calculation in the calculateSalary method. To fix it, change the following:
    multiplier = inc/100;
    to
    multiplier = 1 + inc/100;
    Now run the tests again and they all should pass.

    How to create your own JUnit tests

    1. Figure out what different scenarios you want to test and create a method for each. Each method name begins with test such as testNullData, testYear2006, testBigSalary.
    2. Typically, the first thing you want to do in a test is instantiate a new object of the class, feeding it the necessary parameters to initialize it (or depending on a default constructor to do so).
    3. Now call a method and see if produces the expected return. The next section explains the 3 different ways that JUnit tests.

    Three different methods that produce JUnit test results

    JUnit gives feedback according to the results of three methods. In each case, the first parameter is a String message that is produced if the test fails

    assertEquals


    assertEquals(“What to print to console if test fails”, expected_Object, actual_Object); 

    The first argument is the failure message (printed to the console if the test fails). The second argument is the expected value (can be an int or an Object). The third argument is the actual value received from the method calls.

    Example:
    //What if teacher works 2 years at 10%?
    
    public void test_2YearTeacher() {
    
    int startSal=30000;
    
    Salary s = new Salary(startSal,10,2); 
    
    assertEquals(
    
    "Failed if teacher works 2 years @ 10%",
    
    33000, s.calculateSalary());
    
    }
    
    

    The assertEquals command checks to see if s.calculateSalary() returns a 33000. If it does, the test succeeds. If it returns something else, the failure message is displayed.

    assertTrue

    assertTrue(“failure message”, boolean_expression); In this case, if the boolean expression returns a true, the test passes. The same assert as above could read:

    assertTrue(
    
    "Failed if teacher works 2 years @ 10%",
    
    s.calculateSalary() == 33000);

    fail

    fail(“failure message”); This could follow other logic in your code and simply submits a failure on the test. The same assert as above could read:


    if (s.calculateSalary() != 33000) 
    
    fail(“Failed if teacher works 2 years @ 10%");
    
    

    For more information on JUnit

    Using JUnit with drJava - http://cnx.org/content/m11707/latest/

     Using JUnit with BlueJ - http://cnx.org/content/m11707/latest/

      Using JUnit with Eclipse - http://open.ncsu.edu/se/tutorials/junit/

                http://www.tutorialized.com/view/tutorial/Junit-testing-in-Eclipse/10643

     

    Javadoc

    Since it is imperative that programmers document code, it only makes sense to teach students how to incorporate good documentation into their code (even though this is not tested explicitly on the exam). The built-in Javadoc formatting is what is used in the standard Java API so would have the extra benefit of helping students understand how to read the API.

     

    For my “model” of using Javadoc, open up the Statistics folder. The class Statistics.java has well-formed Javadoc comments and can be used as a template for other projects. Following is a list of required items:

    Above whole class:

    /** Short description of class

      * @author Barbara Fox

      * @version  2008.07.25

    **/


    Above each method:

    /** Short description of method

    * @param x description of parameter x

    * @param sum description of parameter sum

    * @return description of what method will return

    **/

     

    The AP materials focus heavily on stating Preconditions and Postconditions, so I researched recommended methods of incorporating these into the Javadoc. It’s a little kludgy, but I think worth the effort. Basically you force the tab and bold using HTML tags and attributes.  Here is one from Statistics.java:

     

        /**

        * Calculate the average of an array of integers

        * @param a integer array

        * @return the average (i.e. mean)

        * <dt><b>Precondition:</b></dt>

        *    <dd> a[] contains 10 integers</dd>

        **/

     

    To create the Javadoc in drJava, simply press the button [Javadoc] in the upper right of the window. The API will look something like this:

     

    Javadoc-whole class

     

    If you click on the method average(), you will get additional info looking like this:

     

    Javadoc-one method