JUnit Testing Framework

Sang Shin, sang.shin@sun.com, Sun Microsystems, www.javapassion.com/javaintro


This hands-on lab takes you through the basics of using JUnit testing framework.


Expected duration: 60 minutes


Software Needed

Before you begin, you need to install the following software on your computer. 


Change Log


Lab Exercises


Note: The lab document is created using NetBeans 5.5.1.  But the instruction should work with NetBeans 6.0 as well.

Exercise 1: Write a simple JUnit application without using NetBeans JUnit wizard


In this exercise, you are going to learn how to write a simple JUnit test application without using JUnit wizard from the NetBeans IDE and without having a target test class.  The goal of this exercise is to understand the structure of the JUnit testing code.
  1. Write a very simple JUnit test application
  2. Force a failure

(1.1) Write a very simple JUnit test application


0. Start NetBeans IDE if you have not done so yet.
1. Create a new NetBeans project


Figure-1.10: Create a new project
2. Modify the IDE generated VerySimpleJUnitTest.java as shown in Code-1.11 below.  Study the code by paying special attention to the bold fonted parts. 

import junit.framework.TestCase;

// Extend the TestCase class
public class VerySimpleJUnitTest extends TestCase {
   
    public VerySimpleJUnitTest(String name) {
        super(name);
    }
   
    // Test method
    public void testSomething1() {
        System.out.println("In testSomething1() method...");
        assertTrue("Tesing if  4 == (2 * 2)", 4 == (2 * 2));
    }
   
    // Test method
    public void testSomething2() {
        System.out.println("In testSomething2() method...");
        String s1 = "test1";
        String s2 = "test1";
        String s3 = new String(s1);
        assertTrue("Testing if two String instancesa are equal", s1.equals(s2));
        assertTrue(!(s1==s3));
    }
   
    // main method to allow standalone execution
    public static void main(String[] args){
        junit.textui.TestRunner.run(VerySimpleJUnitTest.class);
    }
}
Code-1.11: VerySimpleJUnitTest.java

3. Observe the compile errors as shown Figure-1.12.  This is because the JUnit jar file is not in the classpath.


Figure-1.12: Compile errors

4. Add JUnit jar file to the class path.

Figure-1.14: Select Properties of the project

Figure-1.15: Get ready to add JUnit jar file.

Figure-1.16: Add junit-3.8.1.jar file to the classpath

Figure-1.17: junit-3.8.1.jar file is now in the classpath


Note: Another way of adding JUnit jar file to the classpath to the application is shown below.







5. Build and run the project
.In testSomething1() method...
.In testSomething2() method...

Time: 0

OK (2 tests)

Figure-1.13: Result of running VerySimpleJUnitTest application



Solution: This exercise up to this point is provided as a ready-to-open-and-run NetBeans project as part of hands-on lab zip file. You can find it as <LAB_UNZIPPED_DIRECTORY>/javajunit/samples/VerySimpleJUnitTestYou can just open it and run it. 

6. For your own exercise, modify VerySimpleJUnitTest.java as following. Build and run the application.
                                                                                                             return to top of the exercise

(1.2) Force a failure


1. Modify the VerySimpleJUnitTest.java as shown in Code-1.21 below. The code fragments that need to be added are highlighted in bold and blue-colored font.

import junit.framework.TestCase;

// Extend the TestCase class
public class VerySimpleJUnitTest extends TestCase {
   
    public VerySimpleJUnitTest(String name) {
        super(name);
    }
   
    // Test method
    public void testSomething1() {
        System.out.println("In testSomething1() method...");
        assertTrue("Tesing if 4 == (2 * 2)", 4 == (2 * 2));
    }
   
    // Test method
    public void testSomething2() {
        System.out.println("In testSomething2() method...");
        String s1 = "test1";
        String s2 = "test1";
        String s3 = new String(s1);
        assertTrue("Testing if two String instancesa are equal", s1.equals(s2));
        assertTrue(!(s1==s3));
    }
   
    // Test method
    public void testSomething3() {
        System.out.println("In testSomething2() method...");
        fail("I want to force failure on this test");
    }
   
    // main method to allow standalone execution
    public static void main(String[] args){
        junit.textui.TestRunner.run(VerySimpleJUnitTest.class);
    }
}
Code-1.21: Modified VerySimpleJUnitTest.java

2. Build and run the project
.In testSomething1() method...
.In testSomething2() method...
.In testSomething2() method...
F
Time: 0
There was 1 failure:
1) testSomething3(VerySimpleJUnitTest)junit.framework.AssertionFailedError: I want to force failure on this test
        at VerySimpleJUnitTest.testSomething3(VerySimpleJUnitTest.java:29)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at VerySimpleJUnitTest.main(VerySimpleJUnitTest.java:34)

FAILURES!!!
Tests run: 3,  Failures: 1,  Errors: 0
Figure-1.16: Result



Solution: This exercise up to this point is provided as a ready-to-open-and-run NetBeans project as part of hands-on lab zip file. You can find it as <LAB_UNZIPPED_DIRECTORY>/javajunit/samples/ExtendThreadClassTestFailYou can just open it and run it. 

                                                                                                              return to top of the exercise


Summary


In this exercise, you have learned how to write a JUnit test application without using JUnit wizard.


                                                                                                                  return to the top


Exercise 2: Test the test target class

In this exercise, you are going to write JUnit test application that tests the methods of a test target class. You are going to do this exercise still without using the JUnit wizard of the NetBeans IDE.

  1. Test a target class called ComputeClass using JUnit
  2. Detect a broken code using JUnit
  3. Create common test data through setUp() and tearDown()
  4. Use TestSuite
  5. Use runTest() method

(2.1) Test a target class called ComputeClass using JUnit


1. Create a new NetBeans project
2. Modify the IDE generated TestComputeClass.java as shown in Code-2.11 below.  Study the code by paying special attention to the bold fonted parts. 

import junit.framework.*;

public class TestComputeClass extends TestCase {
  
    public TestComputeClass(String name) {
        super(name);
    }
   
     /**
     * Test of add method, of class ComputeClass.
     */
    public void testAdd() {
        System.out.println("add");
       
        int x = 7;
        int y = 5;
        ComputeClass instance = new ComputeClass();
       
        int expResult = 12;
        int result = instance.add(x, y);
        assertEquals(expResult, result);
       
    }

    /**
     * Test of multiply method, of class ComputeClass.
     */
    public void testMultiply() {
        System.out.println("multiply");
       
        int x = 7;
        int y = 5;
        ComputeClass instance = new ComputeClass();
       
        int expResult = 35;
        int result = instance.multiply(x, y);
        assertEquals(expResult, result);
       
    }

    /**
     * Test of subtract method, of class ComputeClass.
     */
    public void testSubtract() {
        System.out.println("subtract");
       
        int x = 7;
        int y = 5;
        ComputeClass instance = new ComputeClass();
       
        int expResult = 2;
        int result = instance.subtract(x, y);
        assertEquals(expResult, result);
       
    }
   
    public static void main(String[] args){
       
        System.out.println("Running the test using junit.textui.TestRunner.run() method...");
        junit.textui.TestRunner.run(TestComputeClass.class);
       
    }
}
Code-2.11: TestComputeClass.java

3. Write ComputeClass.java as shown in Code-2.12 below.


// This is the target class we want to test.
public class ComputeClass {
   
    int add (int x, int y){
        return (x + y );
    }
   
    int multiply (int x, int y){
        return (x*y);
    }
   
    int subtract (int x, int y){
        return (x-y);
    }
   
}
Code-2.12: ComputeClass.java

4. Add JUnit jar file to the class path as described above.

5. Build and run the project
Running the test using junit.textui.TestRunner.run() method...
.add
.multiply
.subtract

Time: 0

OK (3 tests)

Figure-2.13: Result of running TestComputeClass application



Solution: This exercise up to this point is provided as a ready-to-open-and-run NetBeans project as part of hands-on lab zip file. You can find it as <LAB_UNZIPPED_DIRECTORY>/javajunit/samples/TestComputeClassYou can just open it and run it. 

                                                                                                              return to top of the exercise


(2.2) Detect a broken code through testing


1. Modify the IDE generated ComputeClass.java as shown in Code-2.21 below.  The change is to simulare a business logic error you want to detect as part of the JUnit testing.

// This is the target class we want to test.
public class ComputeClass {
   
    int add (int x, int y){
        // return (x + y);
        // Simulate a business logic error.
        return (x + y + 1);
    }
   
    int multiply (int x, int y){
        return (x*y);
    }
   
    int subtract (int x, int y){
        return (x-y);
    }
   
}
Code-2.21: TestComputeClass.java with business logic error

2. Build and run the project
Running the test using junit.textui.TestRunner.run() method...
.add
F.multiply
.subtract

Time: 0
There was 1 failure:
1) testAdd(TestComputeClass)junit.framework.AssertionFailedError: expected:<12> but was:<13>
        at TestComputeClass.testAdd(TestComputeClass.java:22)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at TestComputeClass.main(TestComputeClass.java:61)

FAILURES!!!
Tests run: 3,  Failures: 1,  Errors: 0

Figure-2.32: Result of running TestComputeClass application



Solution: This exercise up to this point is provided as a ready-to-open-and-run NetBeans project as part of hands-on lab zip file. You can find it as <LAB_UNZIPPED_DIRECTORY>/javajunit/samples/TestComputeClassFailYou can just open it and run it. 

                                                                                                              return to top of the exercise

(2.3) Use setUp() and tearDown() methods


0. Remove the change you made in the step (2.2) above so that the test works correctly.
1. Modify the IDE generated TestComputeClass.java as shown in Code-2.31 below.  The code fragments that need to be added are highlighted in bold font. 

import junit.framework.*;

public class TestComputeClass extends TestCase {
   
    public TestComputeClass(String name) {
        super(name);
    }
   
    // Initialize common test data
    int x;
    int y;
   
    protected void setUp() {
        System.out.println("setUp - Intialize common test data");
        x = 7;
        y = 5;
    }
   
    protected void tearDown(){
        System.out.println("tearDown - Clean up");
    }
   
    /**
     * Test of add method, of class ComputeClass.
     */
    public void testAdd() {
        System.out.println("add");
       
        ComputeClass instance = new ComputeClass();
       
        int expResult = 12;
        int result = instance.add(x, y);
        assertEquals(expResult, result);
       
    }
   
    /**
     * Test of multiply method, of class ComputeClass.
     */
    public void testMultiply() {
        System.out.println("multiply");
       
        ComputeClass instance = new ComputeClass();
       
        int expResult = 35;
        int result = instance.multiply(x, y);
        assertEquals(expResult, result);
       
    }
   
    /**
     * Test of subtract method, of class ComputeClass.
     */
    public void testSubtract() {
        System.out.println("subtract");
       
        ComputeClass instance = new ComputeClass();
       
        int expResult = 2;
        int result = instance.subtract(x, y);
        assertEquals(expResult, result);
       
    }
   
    public static void main(String[] args){
       
        System.out.println("Running the test using junit.textui.TestRunner.run() method...");
        junit.textui.TestRunner.run(TestComputeClass.class);
       
    }
}
Code-2.31: TestComputeClass.java

2. Build and run the project
Running the test using junit.textui.TestRunner.run() method...
.setUp - Intialize common test data
add
tearDown - Clean up
.setUp - Intialize common test data
multiply
tearDown - Clean up
.setUp - Intialize common test data
subtract
tearDown - Clean up

Time: 0

OK (3 tests)
Figure-2.32: Result of running TestComputeClass application

Solution: This exercise up to this point is provided as a ready-to-open-and-run NetBeans project as part of hands-on lab zip file. You can find it as <LAB_UNZIPPED_DIRECTORY>/javajunit/samples/TestComputeClasssetUptearDownYou can just open it and run it. 

                                                                                                              return to top of the exercise

(2.4) Use test suite


1. Modify the IDE generated TestComputeClass.java as shown in Code-2.31 below.  The code fragments that need to be added are highlighted in bold font.  The code fragment that needs to be removed is highlghted in bold and red-colored font.


import junit.framework.*;

public class TestComputeClass extends TestCase {
   
    public TestComputeClass(String name) {
        super(name);
    }
   
    // Initialize common test data
    int x;
    int y;
   
    protected void setUp() {
        System.out.println("setUp - Intialize common test data");
        x = 7;
        y = 5;
    }
   
    protected void tearDown(){
        System.out.println("tearDown - Clean up");
    }
   
    public void testAdd() {
        System.out.println("add");
       
        ComputeClass instance = new ComputeClass();
       
        int expResult = 12;
        int result = instance.add(x, y);
        assertEquals(expResult, result);
       
    }
   
    /**
     * Test of multiply method, of class ComputeClass.
     */
    public void testMultiply() {
        System.out.println("multiply");
       
        ComputeClass instance = new ComputeClass();
       
        int expResult = 35;
        int result = instance.multiply(x, y);
        assertEquals(expResult, result);
       
    }
   
    /**
     * Test of subtract method, of class ComputeClass.
     */
    public void testSubtract() {
        System.out.println("subtract");
       
        ComputeClass instance = new ComputeClass();
       
        int expResult = 2;
        int result = instance.subtract(x, y);
        assertEquals(expResult, result);
       
    }
   
    // Create a TestSuite
    public static Test createTestSuite() {
        TestSuite testSuite = new TestSuite("AllTests");
        testSuite.addTest(new TestComputeClass("testAdd"));
        testSuite.addTest(new TestComputeClass("testMultiply"));
        testSuite.addTest(new TestComputeClass("testSubtract"));
        return testSuite;
    }
   
    public static void main(String[] args){
       
        System.out.println("Running the test through TestSuite...");
        //junit.textui.TestRunner.run(TestComputeClass.class);
        junit.textui.TestRunner.run(createTestSuite());
       
    }
}
Code-2.31: TestComputeClass.java

2. Build and run the project
Running the test through TestSuite...
.setUp - Intialize common test data
add
tearDown - Clean up
.setUp - Intialize common test data
multiply
tearDown - Clean up
.setUp - Intialize common test data
subtract
tearDown - Clean up

Time: 0.015

OK (3 tests)

Figure-2.32: Result of running TestComputeClass application

Solution: This exercise up to this point is provided as a ready-to-open-and-run NetBeans project as part of hands-on lab zip file. You can find it as <LAB_UNZIPPED_DIRECTORY>/javajunit/samples/TestComputeClassTestSuiteYou can just open it and run it. 

                                                                                                                       return to top of the exercise


(2.5) Use runTest method


1. Modify the IDE generated TestComputeClass.java as shown in Code-2.51 below.  Study the code by paying special attention to the bold fonted parts.

import junit.framework.*;

public class TestComputeClass extends TestCase {
   
    public TestComputeClass(String name) {
        super(name);
    }
   
    // Initialize common test data
    int x;
    int y;
   
    protected void setUp() {
        System.out.println("setUp - Intialize common test data");
        x = 7;
        y = 5;
    }
   
    protected void tearDown(){
        System.out.println("tearDown - Clean up");
    }
   
    public void testAdd() {
        System.out.println("add");
       
        ComputeClass instance = new ComputeClass();
       
        int expResult = 12;
        int result = instance.add(x, y);
        assertEquals(expResult, result);
       
    }
   
    /**
     * Test of multiply method, of class ComputeClass.
     */
    public void testMultiply() {
        System.out.println("multiply");
       
        ComputeClass instance = new ComputeClass();
       
        int expResult = 35;
        int result = instance.multiply(x, y);
        assertEquals(expResult, result);
       
    }
   
    /**
     * Test of subtract method, of class ComputeClass.
     */
    public void testSubtract() {
        System.out.println("subtract");
       
        ComputeClass instance = new ComputeClass();
       
        int expResult = 2;
        int result = instance.subtract(x, y);
        assertEquals(expResult, result);
       
    }
   
   
    public static void main(String[] args){
       
        System.out.println("Running the test through runTest()...");
        TestCase test = new TestComputeClass("compute"){
            public void runTest() {
                testAdd();
                testMultiply();
                testSubtract();
            }
        };
        TestResult tresult = test.run();
        System.out.println("Number of failures = " + tresult.failureCount());
        java.util.Enumeration e1 = tresult.failures();
       
    }
}

Code-2.51: TestComputeClass.java

2. Build and run the project
Running the test through runTest()...
setUp - Intialize common test data
add
multiply
subtract
tearDown - Clean up
Number of failures = 0
Figure-2.52: Result of running TestComputeClass application

Solution: This exercise up to this point is provided as a ready-to-open-and-run NetBeans project as part of hands-on lab zip file. You can find it as <LAB_UNZIPPED_DIRECTORY>/javajunit/samples/TestComputeClassrunTestYou can just open it and run it. 


                                                                                                                       return to top of the exercise


Summary

In this exercise, you learned how to write JUnit test application that tests the methods of a test target class but still without using the JUnit wizard of the NetBeans IDE.

                                                                                                                        return to the top



Exercise 3: Use JUnit Wizard of the NetBeans IDE


In this exercise, you are going to learn how to use JUnit wizard of the NetBeans IDE to create the test code.  Note that you don't have to manually set the JUnit jar file to the class path.


(3.1) Generate test code using NetBeans JUnit wizard and using JUnit 3.x


1. Create a new NetBeans project

Figure-3.11: Name and Location
2. Write ComputeClass.java as shown in Code-3.12 below. 

// This is the target class we want to test.
public class ComputeClass {
   
    int add(int x, int y){
        return (x + y);
    }
   
    int multiply(int x, int y){
        return (x*y);
    }
   
    int subtract(int x, int y){
        return (x-y);
    }
   
}
Code-3.12: ComputeClass.java

3. Create Test code using JUnit 3.x.

Figure-3.13: Create JUnit Tests

Figure-3.14: Select JUnit Version

Figure-3.15: Create Tests dialog box
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

import junit.framework.TestCase;

/**
 *
 * @author sang
 */
public class ComputeClassTest extends TestCase {
   
    public ComputeClassTest(String testName) {
        super(testName);
    }           

    @Override
    protected void setUp() throws Exception {
        super.setUp();
    }

    @Override
    protected void tearDown() throws Exception {
        super.tearDown();
    }

    /**
     * Test of add method, of class ComputeClass.
     */
    public void testAdd() {
        System.out.println("add");
        int x = 7;
        int y = 5;
        ComputeClass instance = new ComputeClass();
        int expResult = 12;
        int result = instance.add(x, y);
        assertEquals(expResult, result);
        // TODO review the generated test code and remove the default call to fail.
        //fail("The test case is a prototype.");
    }

    /**
     * Test of multiply method, of class ComputeClass.
     */
    public void testMultiply() {
        System.out.println("multiply");
        int x = 7;
        int y = 5;
        ComputeClass instance = new ComputeClass();
        int expResult = 35;
        int result = instance.multiply(x, y);
        assertEquals(expResult, result);
        // TODO review the generated test code and remove the default call to fail.
        //fail("The test case is a prototype.");
    }

    /**
     * Test of subtract method, of class ComputeClass.
     */
    public void testSubtract() {
        System.out.println("subtract");
        int x = 7;
        int y = 5;
        ComputeClass instance = new ComputeClass();
        int expResult = 2;
        int result = instance.subtract(x, y);
        assertEquals(expResult, result);
        // TODO review the generated test code and remove the default call to fail.
        //fail("The test case is a prototype.");
    }

}
Code-3.16: Modified ComputeClassTest.java

4. Test the project

Figure-3.17: Test Project
add
multiply
subtract
Testsuite: ComputeClassTest
Tests run: 3, Failures: 0, Errors: 0, Time elapsed: 0.063 sec

------------- Standard Output ---------------
add
multiply
subtract
------------- ---------------- ---------------
test-report:
test:
Figure-3.18: Result of running TestComputeClassWizard application

Solution: This exercise up to this point is provided as a ready-to-open-and-run NetBeans project as part of hands-on lab zip file. You can find it as <LAB_UNZIPPED_DIRECTORY>/javajunit/samples/TestComputeClassWizardYou can just open it and run it.

                                                                                                              return to top of the exercise

(3.2) Use setUp() and tearDown()


1. Modify the IDE generated ComputeClassTest.java as shown in Code-3.21 below. The code fragments that need to be changed are highlighted in bold and blue-colored font.

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

import junit.framework.TestCase;

/**
 *
 * @author sang
 */
public class ComputeClassTest extends TestCase {
   
    public ComputeClassTest(String testName) {
        super(testName);
    }           

    int x;
    int y;

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        x = 7;
        y = 5;
    }

    @Override
    protected void tearDown() throws Exception {
        super.tearDown();
    }

    /**
     * Test of add method, of class ComputeClass.
     */
    public void testAdd() {
        System.out.println("add");
        //int x = 7;
        //int y = 5;
        ComputeClass instance = new ComputeClass();
        int expResult = 12;
        int result = instance.add(x, y);
        assertEquals(expResult, result);
        // TODO review the generated test code and remove the default call to fail.
        //fail("The test case is a prototype.");
    }

    /**
     * Test of multiply method, of class ComputeClass.
     */
    public void testMultiply() {
        System.out.println("multiply");
        //int x = 7;
        //int y = 5;
        ComputeClass instance = new ComputeClass();
        int expResult = 35;
        int result = instance.multiply(x, y);
        assertEquals(expResult, result);
        // TODO review the generated test code and remove the default call to fail.
        //fail("The test case is a prototype.");
    }

    /**
     * Test of subtract method, of class ComputeClass.
     */
    public void testSubtract() {
        System.out.println("subtract");
        //int x = 7;
        //int y = 5;
        ComputeClass instance = new ComputeClass();
        int expResult = 2;
        int result = instance.subtract(x, y);
        assertEquals(expResult, result);
        // TODO review the generated test code and remove the default call to fail.
        //fail("The test case is a prototype.");
    }

}
Code-3.21: ComputeClassTest.java

2. Test the project.
add
multiply
subtract
Testsuite: ComputeClassTest
Tests run: 3, Failures: 0, Errors: 0, Time elapsed: 0.063 sec

------------- Standard Output ---------------
add
multiply
subtract
------------- ---------------- ---------------
test-report:
test:
Figure-3.22: Result of running TestComputeClassWizard application

Solution: This exercise up to this point is provided as a ready-to-open-and-run NetBeans project as part of hands-on lab zip file. You can find it as <LAB_UNZIPPED_DIRECTORY>/javajunit/samples/TestComputeClassWizardsetUptearDownYou can just open it and run it.

                                                                                                              return to top of the exercise


Summary


In this exercise, you learned how to use JUnit wizard of the NetBeans IDE to create the test code. 


                                                                                                                    return to the top



Homework exercise (for people who are taking Sang Shin's "Java Programming online course")


1. The homework is to modify TestComputeClassWizard project above as following.  (You might want to create a new project by copying the TestComputeClassWizard project.  You can name the homework project in any way you want but here I am going to call it MyTestComputeClassWizard.)
    int addAndMultiplyBy3(int x, int y){
        return (x + y) * 3;
    }

2. Send the following files to javaintro1homework@sun.com with Subject as JavaIntro-javajunit.