Goal
In this activity, we will be using a single class problem to introduce you to the basics of writing test cases. The goal is for you to introduce you (or refresh your memory about) JUnit style test cases.
Learning Objectives
- Familiarity with the basic form of JUnit-style test cases for Java classes
- Familiarity with generating JUnit test cases using Eclipse
- Familiarity with writing simple JUnit test cases for a simple Java class
- Exposure to simple test case assertions
- Exposure to the
setUp()
method - Exposure to using test cases in clarifying assignment specifications
Prelude: Start Up Eclipse
This example is written in Java and we will be using Eclipse.
-
Open Eclipse
Start Eclipse and select the workspace you want to work in.
-
Create a New Project
Use the File->New->Project… command to create a new Java project called Calculator.
-
Download the Calculator.java
Download the source file for this example, Calculator.java, and place it in the Calculator project folder within your Eclipse workspace. Right-click on your Calculator project in Eclipse’s package explorer and choose Refresh so that Eclipse will see the newly added source files. Expand the
Calculator
project, if needed, so that you can see its contents. The Package Explorer should look like this:
Writing Test Cases
Let’s create some test cases for this calculator class.
Procedure
-
Open the Calculator.java file
Double-click the
Calculator.java
file to open it in an edit window. This class provides a simple calculator that contains a single integer accumulator. It provides basic methods to set/get/clear the accumulator’s value, as well as to add, subtract, multiply, and divide. All operations leave their results in the accumulator for further manipulation. Look through the code to familiarize yourself with it; all of the methods are very simple.- Create a test class
Right-click on the
Calculator.java
file in the Package Explorer (on the left) and select New->JUnit Test Case. This will activate a wizard in Eclipse to help you create your test case class for theCalculator
class. Use the default values for all fields (e.g. Source folder: Calculator, Name: , Superclass: junit.framework.). Also, check the box next tosetUp()
to generate a stub for that method. Then clickNext >
. Note: if you already have some experience with JUnit but have not started using JUnit 4 yet, you may wish to check the radio button to create a JUnit 4 test case at the top of the dialog.
- Create a test class
Right-click on the
-
Add some test cases
In the next step of the wizard, you will see a tree view showing the methods provided by the
Calculator
class. For each method you check in this view, the wizard will create a test case stub. For this example, turn onsetValue
,add
, anddivideBy
. This will generate empty test cases for these methods. Click Finish. This will generate a newCalculatorTest.java
file in your project. It will also open this new file in the editor. -
Add JUnit to your project’s build path
Your test cases will have a number of errors, all of them caused by the fact that the JUnit library is not in the build path for your project yet. Look at the
CalculatorTest.java
file in the editor. Click on the lightbulb icon next to theimport
statement at the top of the file. Eclipse will pop up a window with several potential ways to fix this problem. Select the choice to “Add JUnit 3.8.1 to the build path”: -
Run your tests
Now select the
CalculatorTest.java
file in the Package Explorer view (the left pane). From the Run menu, select Run As->JUnit Test. This will run all of the test cases in your new test class (remember, the tests are just stubs at this point!). You can see the results in the JUnit tab to the right of to the Package Explorer tab. The test case stubs that were generated by the wizard have all failed. Return to yourCalculatorTest.java
file in the editor and look at the code. You will see that each test case is apublic void
method taking no arguments, with a name that begins with the prefix “test”. Each generated test case stub contains just a single line in its body:
fail("Not yet implemented.");
Now, you need to write the bodies for these test case methods.
-
Create a test fixture in the
setUp()
methodBefore we fill out the first test case method, let’s set up a test fixture for this test class. A test fixture is really the common set of “initial conditions” under which a collection of tests are executed. Often, a test fixture includes a predefined set of one or more objects, initialized into a particular configuration. In JUnit, all of the test case methods in one test class use the same test fixture–that is, they all execute using exactly the same starting conditions. Here, we don’t need a fancy test fixture for our tests. Instead, we’ll start with something very basic–just a single
Calculator
object that has been freshly created. So that you don’t have to repeatedly write the same code to set up the objects in your test fixture in many test methods, JUnit provides the idea of asetUp()
method–a place where you can put common initialization actions that you want to have executed just before each and every test case method in the test class is executed.setUp()
is an ideal place to set up the initial conditions for all your test case methods. To describe our initial conditions, begin by adding an instance variable to the[Calculator Test](../CalculatorTest.html)
class to hold aCalculator
object:
protected Calculator calc;
Next, add code to the `setUp()` method to initialize the `calc` instance variable. The `setUp()` method is invoked once before each test case method in this class. This guarantees that your test cases will start with a clean copy of your object(s).
public void setUp()
throws Exception
{
calc = new Calculator();
}
-
Implement your first test case
Now that you’ve defined the initial conditions for all your tests, you can fill out the first test case:
public void testSetValue()
{
calc.setValue(5);
assertEquals(5, calc.getValue());
}
The first line in this method sets the value of the accumulator in the `Calculator` object.
The second line is where we define our _expected behavior_. In this case, we are calling the `getValue()` accessor, and our expected result is the integer 5.
In JUnit, we always phrase the "expected output" of a test case in terms of one or more _assertions_. One of the most common assertions is `assertEquals()`, which takes an expected value followed by a test expression, and asserts that the two are equivalent (that is, the values test positive using the `equals()` method, in Java). If you are interested, you can view the [full list of assertions](../http://www.junit.org/junit/javadoc/3.8.1/junit/framework/Assert.html) supported in JUnit test classes.
-
Run your new test case
Save the modified
CalculatorTest.java
file. Select theCalculatorTest.java
file in the Package Explorer (left pane). Expand the class in that pane by clicking on the “+” icon in front of it, and you will see the list of methods contained in the class. Right-click on yourtestSetValue()
method and select Run As->JUnit Test. This will run just one test (if you right-click on the class as a whole, you can run all tests in the class as before). You can see the result of your test case in the JUnit tab, as before. Click on the JUnit tab if it does not automatically jump to the foreground. Now, your test case passes. Now, rerun all the tests in your class and look at the results. You will note that running your test cases now had a different result. Before, all three test cases failed. Now,testSetValue()
passes. The results in the JUnit tab should be similar to the following: -
Implement the two remaining test cases
Based on the first test case as an example, implement
testAdd()
inCalculatorTest.java
. Choose numbers of your own and write your own assertion. Also, implement the last test case stub:testDivideBy()
. This test case should set a value in the calculator and test the results of dividing by some number. Trying setting the calculator to 10 and dividing by 5. Assert that the calculator’s accumulator is 2 after the operation. Rerun your test cases as before to make sure things are working. -
Add a fourth test case
Add a new test case of your own called
testDivideByZero()
that asserts that tests what happens when you divide by zero. Without looking at theCalculator
code, what do you expect this operation (division by 0) to do? Should it return an error code? Should it throw an exception? Should it simply be ignored? For this example, let’s assume that the code in the calculator class responds to division by zero by simply resetting the accumulator to zero without attempting to carry out the division. Implement your new test case to check for this behavior.
public void testDivideByZero()
{
calc.setValue(10);
calc.divideBy(0);
assertEquals(0, calc.getValue());
}
Rerun all the test cases to make sure things are working. Unfortunately, this new test case fails. Examine how the results are displayed in the JUnit pane. If you click on the failed test case in the JUnit pane, the pane will show a failure trace indicating how the test case failed.
In this example, the test case fails due to an arithmetic exception in the `Calculator`'s `divideBy()` method. It reflects a bug in the `Calculator` class. The `divideBy` does not handle division by zero as it is supposed to.
<img href="img/Eclipse006.png"/>
-
Fix the simple bug
If you have time, feel free to fix the bug in the
divideBy()
method of theCalculator
class by adding a conditional. Rerun your test cases to make sure you are correct.