Lab 6: Junit Testing
This lab introduces you to testing with JUnit, a standard testing framework for Java (and one used in upper-level CS courses). This lab will help you learn JUnit and think about testing in the presence of mutation.
Note: the current release of DrJava supports testing with JUnit 3. There is a newer version of JUnit (JUnit 4) that uses a slightly different syntax. This lab describes how to set up tests using JUnit 3.
1 Problem to Test: A Vending Machine
Start from this simple implementation of a vending machine. The vending machine offers two items: "Candy" and "Gum". The vending machine operations allow someone to deposit money, purchase items, see the current balance in the machine, and restock items. Your job will be to design tests for the vending machine and express them in JUnit.
2 Introduction to JUnit
JUnit is a framework for writing test cases, similar in spirit to Tester, but with some significant differences. Both DrJava and Eclipse have built-in support for creating JUnit test cases (directly under the file menu for DrJava; under the File->New menu for Eclipse). The configuration options (especially under Eclipse) will make more sense if you first write a test suite manually.
To use JUnit, you first need to include the following line:
import junit.framework.TestCase; |
public class VendingTest extends TestCase { |
} |
The contents of this class are a series of test methods (similar in spirit to those we have done with Tester). All test methods must start with the letters test:
public class VendingTest extends TestCase { |
|
public void test1() { |
... |
} |
} |
All that remains is to learn the contents of the test methods. Here are five common test operations you can use (the full list is in the JUnit documentation) :
assertTrue(boolean) // passes if the expression is true
assertFalse(boolean) // passes if expression is false
assertSame(Object, Object) // passes if the two objects are in the same location in memory
assertNotSame(Object, Object) // passes if the two objects are not in the same location in memory
assertEquals(Object, Object) // passes if the two objects are identical according to their equals method.
(Note that the order of the arguments for assertEquals is the reverse of what we are used to with checkExpect: the expected value should be listed first, and the actual value is second.)
So for example, I could write the following (uninteresting) test suite:
public class VendingTest extends TestCase { |
|
public void test1() { |
assertEquals(3,3); |
} |
} |
Let’s have you write some tests before we cover additional JUnit features.
3 Problems, Part 1
Set up a JUnit test case to make sure that you can add money to a Vending Machine.
Set up a JUnit test to make sure that when you buy Candy from a Vending Machine, the balance in the machine is adjusted appropriately.
Did you notice that these two tests had some common infrastructure? Namely, both had to start with creating a vending machine and adding some money to the machine. Rather than repeat that code, it would be nice to tell JUnit to always set up that infrastructure before running our tests.
4 JUnit, part 2
Imagine that we had a method to create and initialize our vending machine:
Vending v; |
|
public void setUp() { |
v = new Vending(5,10); |
v.addMoney(3); |
} |
Each TestCase class can have its own setUp and tearDown methods. So if you have two sets of tests that need different setup and teardown operations, put them in two separate TestCase classes.
5 Problems, part 2
Consider the following TestCase:
public class VendTest extends TestCase { |
static Vending v = new Vending(5,5); |
|
public void setUp() { |
v.addMoney(1.5); |
} |
|
public void test2() { |
v.select("Gum"); |
assertEquals(1.0, v.getBalance()); |
} |
|
public void test3() { |
v.select("Candy"); |
assertEquals(0.25, v.getBalance()); |
} |
} |
Run these tests. Comment out test2 and run them again. Now uncomment test2 and remove the static from the definition of v.
What do you infer about the behavior of JUnit from these experiments? Write down a sentence or two to explain your reasoning clearly.
If you had to leave v as static, how could you make this test suite work without commenting out any of the given code?
Continue developing a test suite for the vending machine. Develop more sophisticated tests that check the interactions between operations in the vending machine.
6 What to Turn In
Turn in your .java files for this assignment.