My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
HowToWriteJunitTestCases  
In this wiki we show how to write a unit test cases in JUnit, using correct syntax as needed in eConference 4.
Phase-Implementation, Howto
Updated Apr 29, 2011 by calefato.uniba@gmail.com

Index

How to write a test using JUnit

JUnit framework is an open source project developed by Kent Beck; you can download the last version at http://github.com/KentBeck/junit/downloads. As of this writing (Jan. 2011) the last stable version released is 4.8.2.

Why use JUnit?

When a developer need to test functioning of a class, he must write another class that, by convention, it's called with the same name of the class followed by suffix “Test”. Suppose that we have a class named MathOp that carry out operation of addition and subtraction; suppose that we want write a unit test for this class.

public class MathOp {
    public MathOp() {
    }
 
    public int add(int a, int b) {
        return a + b;
    }
 
    public int sub(int a, int b) {
        return a – b;
    }
}

First, we must create another class that we call, by convention, MathOpTest. To use JUnit library is necessary to add it to the build path of the project. (You can do it adding library from the preference of the Eclipse project).

Import JUnit class

To use the constructs of JUnit to do assertion on method's result, it's necessary to import, first of all, the library and import statically the class of package org.junit.Assert:

import org.junit.*;
import static org.junit.Assert.*;

Test class

Now we are ready to write the test class. To indicate to JUnit which are methods that make tests it’s necessary to mark them with annotation @Test. In this way, JUnit will recognize methods that contain assertion.

	import org.junit.*;
	import static org.junit.Assert.*;
	 
	public class MathOpTest {
	    @Test
	    public void testAdd(){
	        MathOp a = new MathOp();
	        assertEquals(4, a.add(3, 1));	    }
	 
	    @Test
	    public void testSub(){
	        MathOp a = new MathOp();
	        assertEquals(-4, a.sub(-3, 1));
	    }
	}

The assertions

With JUnit it’s possible to do many type of test with different assertion (http://junit.sourceforge.net/javadoc_40/org/junit/Assert.html). At the execution moment, a test is passed if all conditions specified are true.

assertEquals(expected, actual), assertArrayEquals(expected, actual) : requires that the value ‘expected’ is equal to ‘actual’.
assertTrue(cond): required that ‘cond’ has value ‘true’
assertFalse(cond): required that ‘cond’ has value ‘false’
assertNull(obj): required that ‘obj’ is a null reference
assertNotNull(obj): required that ‘obj’ isn't null reference

The @Before and @After annotations

In the previous example, in all test case is instanced an object MathOp. JUnit provides developers a feature to execute instructions before they are carried out tests. setUp() method have the annotation @Before that is used to indicate to JUnit that the method is to run before the execution of other test case. In this way, the code to initialize objects and resources (for example a connection to a DBMS) is written in one point of test case. Similary to @Before, @After indicates to JUnit to execute the method after the execution of all test cases.

	import org.junit.*;
	import static org.junit.Assert.*;
	 
	public class MathOpTest {
	    private MathOp a;
	 
	    @Before
	    public void setUp(){
	        a = new MathOp();
	    }
	 
	    @Test
	    public void testAdd(){
	        assertEquals(4, a.add(3, 1));
	    }
	 
	    @Test
	    public void testSub(){
	        assertEquals(-4, a.sub(-3, 1));
	    }
	}

Launch the tests

The test can be launched from Eclipse selecting the test class and clicking on“Run as” -> “JUnit Test”. It's possible to use the command line o the junit task and junit report of Apache Ant.

Figure 1 show a screenshot of the test results in Eclipse:


Figure 1. Result of JUnit execution

The two tests have positive end. If there are errors, this are showed in the section named Errors, while the condition not verified will be counted in the section named Failured.

Setting time limit

The performance verification is one of the most difficult issues in JUnit. JUnit 4 not completely solves the problem but offers an utile help: in fact, the test method can be signed with a timeout parameter. If the tests are running in a time over, it fails. For example, in the next code the test fails if it needs more than 500 ms to be ended:

	@Test(timeout=500) public void retrieveAllElementsInDocument() {
	    doc.query("//*");
	}

Apart from simple benchmarking, timed tests are also useful for the testing of network operations. If you are trying to connect to a slow or unreachable database, you can bypass the test so as not to slow down the following tests:

	@Test(timeout=2000)
	  public void remoteBaseRelativeResolutionWithDirectory()
	   throws IOException, ParsingException {
	      builder.build("http://www.qualcosa.org/xml");
	}

Ignored Tests

@Ignore annotation allows marking the test methods that you want skip. Suppose that we have a test method that need more time to be executed: not necessary we must to speed up it, simply its work could be more complex. For example, same test that trying to connect to remote server are in this case test category. To not slowing other methods, it's possible to annotate this test to ignore it.

	@Ignore public void testUTF32BE()
	      throws ParsingException, IOException, XIncludeException {
	 
	        File input = new File(
	          "data/xinclude/input/UTF32BE.xml"
	        );
	        Document doc = builder.build(input);
	        Document result = XIncluder.resolve(doc);
	        Document expectedResult = builder.build(
	          new File(outputDir, "UTF32BE.xml")
	        );
	        assertEquals(expectedResult, result);
	}

During the execution of all test cases, this method will be ignored.

Example of a JUnit test for a procedure

When we need to test procedure, the way you create a test case is always the same. For example, consider a class that has a method that connects to a server:

public class Client{
	
        public void connect(String host, integer port){
	….
        }
        
        private boolean isConnected(){
	..............
        }

} 

If we want to test the connection, test class will look like this:

public class ConnectionTest{
    @Test
    public void testConnection(){
		Client client = new Client();
                client.connect(“host”,5566);
                assertEquals(client.isConnected(), true);
	}
}

Sintax for test cases to use in eConference4

In Econference4 project, to write a test case you must respect the classic syntax that we have reported in previous paragraph. In the actual version of eConference4 you can find different syntax in more test cases because the version of JUnit used until recently is the JUnit3. But eConference4 now implement JUnit4 that support old (JUnit3) and new syntax. Whereas the syntax of JUnit4 is more simply than syntax of JUnit 3, you have to use only JUnit4 syntax.

Test's methods

All previous versions of JUnit used coding conventions and reflection to mark a method how tests. For example, the following test verifies that 1 + 1 equals 2:

	import junit.framework.TestCase;
	 
	public class AdditionTest extends TestCase {
	 
	  private int x = 1;
	  private int y = 1;
	 
	  public void testAddition() {
	    int z = x + y;
	    assertEquals(2, z);
	  }
	}

Conversely, in JUnit4 the tests are marked by @Test annotation, as follows:

	import org.junit.Test;
	import junit.framework.TestCase;
	 
	public class AdditionTest extends TestCase {
	 
	  private int x = 1;
	  private int y = 1;
	 
	  @Test public void testAddition() {
	    int z = x + y;
	    assertEquals(2, z);
	  }
	}

In general, in this way you can use your preferred names that are properly related to your application and your programming style. The TestCase class is present but is no longer necessary to extend them. Simply you have to mark the test methods using @Test annotation and you can insert them in any class. To use assert method is necessary to import the class junit.Assert, as follow:

	import org.junit.Assert;
	 
	public class AdditionTest {
	 
	  private int x = 1;
	  private int y = 1;
	 
	  @Test public void addition() {
	    int z = x + y;
	    Assert.assertEquals(2, z);
	  }
	}

You can also use the new static import feature of JDK 5 to make this easier than the old version of JUnit:

	import static org.junit.Assert.assertEquals;
	 
	public class AdditionTest {
	 
	  private int x = 1;
	  private int y = 1;
	 
	  @Test public void addition() {
	    int z = x + y;
	    assertEquals(2, z);
	  }
	}

This approach makes the testing of protected methods much easier, because the test class can now extend the class containing the protected methods.

The setup and teardown methods

The run tools of JUnit 3 tests automatically run the method setUp() before each test method. Normally, we use setUp() to initialize the data needed to run the tests, reset any environment variables, and so on. For example, here is a setup () method:

	protected void setUp() {
	 
	    System.setErr(new PrintStream(new ByteArrayOutputStream()));
	 
	    inputDir = new File("data");
	    inputDir = new File(inputDir, "xslt");
	    inputDir = new File(inputDir, "input");
	 
	}

Also in JUnit 4 it's possible to initialize the data and configure the environment before each test method: however, the method that performs these operations do not need to be named setUp(). He just needs to mark this method with the @Before annotation:

	@Before protected void initialize() {
	 
	    System.setErr(new PrintStream(new ByteArrayOutputStream()));
	 
	    inputDir = new File("data");
	    inputDir = new File(inputDir, "xslt");
	    inputDir = new File(inputDir, "input");
	}

It is also possible to have different test methods annotated with @Before: in this case, each of these will be running before test method:

	@Before protected void findTestDataDirectory() {
	    inputDir = new File("data");
	    inputDir = new File(inputDir, "xslt");
	    inputDir = new File(inputDir, "input");
	}

	@Before protected void redirectStderr() {
	    System.setErr(new PrintStream(new ByteArrayOutputStream()));
	}

Operations of the clean-up work in a similar way. In JUnit 3, we use the method tearDown() : note, in this snippet, we call the garbage collection to force the recovery of memory.

	protected void tearDown() {
	  doc = null;
	  System.gc();
	}

In JUnit4, you can mark any method with @After annotation:

	@After protected void disposeDocument() {
	  doc = null;
	  System.gc();
	}

Similarly than the @Before annotation, you can create more clean-up methods marked with @After, each of which will running before all test methods. In addition, it's not more necessary to call explicitly the methods of initialization and clean-up of super-class. Until they are overwritten, the "test runner automatically call these methods, if necessary. @Before methods in super classes are invoked before the first @Before methods of subclasses (note that this behavior reflects the order of appearance of Manufacturers). @After methods are executed in reverse order: first those of the subclasses and then those of the super classes.

Initialization of the test classes

JUnit 4 introduces a new feature that has no equivalent in JUnit 3: an initialization method, similar to setUp(), that operates at the class level. Any method annotated @BeforeClass will be executed once, after loading the test class, and before the execution of the test methods; any method annotated with @AfterClass will be executed once, after all methods tests were performed. For example, assume that each test class uses a connection to a database, a network connection, a large data structure, or some other resource that is particularly costly to initialize or download. Rather than recreate these resources before each test, you can initialize and destroy once. This approach will make the execution of some test cases much faster.

	private PrintStream systemErr;
	 
	@BeforeClass protected void redirectStderr() {
	    systemErr = System.err; // Hold on to the original value
	    System.setErr(new PrintStream(new ByteArrayOutputStream()));
	}
	 
	@AfterClass protected void tearDown() {
	    // restore the original value
	    System.setErr(systemErr);
	}

How to test the exception

The test mechanism of the exceptions is one of the major improvements made to JUnit 4. In older versions of JUnit was used a try block that contains the code that should throw the exception, and a call to fail() in the end of the try block. For example, the following code verifies that an ArithmeticException is thrown:

	public void testDivisionByZero() {
	 
	    try {
	        int n = 2 / 0;
	        fail("Divisione per zero.");
	    }
	    catch (ArithmeticException success) {
	        assertNotNull(success.getMessage());
	    }
	}

In JUnit 4, you can explicitly write the code that generates the exception: annotation declares that it is expected that an exception is raised:

	@Test(expected=ArithmeticException.class)
	  public void divideByZero() {
	    int n = 2 / 0;
	}

If the exception is not raised or if it's different from that expected, the test will fail. Note that it may still be useful to the try-catch old-style, for instance if you want to check the error message, any exception details or other properties.

New claims

JUnit 4 adds two new methods named assert() for comparisons of arrays; follow the definitions:

  • public static void assertArrayEquals(Object expecteds, Object actuals)
  • public static void assertArrayEquals(String message, Object expecteds, Object actuals)

These two methods compare arrays in the obvious way: two arrays are equal if they are the same size and if each element is the same as in the corresponding array.

Write a test case for eConference4

To write a test case for eConference4, we could use old syntax of JUnit3 or new syntax of JUnit4. Obviously it is better for programmers to use easier syntax of version 4 for future test cases, for conform to the same syntax. Here are the steps every time you need to write a new test case.

Separate test cases from code eConference4.

To practice it is preferable to separate the program code from the code that performs tests on it. To do this, create a project, if not already present, in which you have to write the test cases related to a project. For example, as shown in the figure 2, there is a project called it.uniba.di.cdg.jabber; for this project was created another project called it.uniba.di.cdg.jabber.test in which we have write the test cases. This project must be provided inside the package with the same name as the project referred to, for example in the project there are the packages:

 it.uniba.di.cdg.jabber
 it.uniba.di.cdg.jabber.action
 it.uniba.di.cdg.jabber.internal
 it.uniba.di.cdg.jabber.ui
 it.uniba.di.cdg.smackproviders
 it.uniba.di.cdg.xcore.aspects

Because until now we have been set up test cases only for packages:

	it.uniba.di.cdg.jabber
	it.uniba.di.cdg.jabber.internal

they must be present in the project it.uniba.di.cdg.jabber.test.

You can see it in Figure 2.


Figure 2. Test case separate to source code

In this package you have to write the code of test cases to which they relate.

Add information on the new test case in the other classes for execution to various retail

When you create a new test case, we must ensure that this can be executed by calling him at package-level or at the project level and at the global level. So, once you've created the class of the test case, you must insert the link to this class in AllTests.java conteined in the same package. To add this information in class, simply add to the list of the annotation @Suite.SuiteClasses() present in relative AllTest.java, the invocation to the new class. For example, if you're creating a test class called XmppLoadTest.java in the package it.uniba.di.cdg.jabber in the project it.uniba.di.cdg.jabber.test, you have to add the new class in AllTests.java content in the same package as shown .


Figure 2. Result of JUnit execution

Instead, if you have created a new package with some class for test case, you need to create a class named AllTest.java into this package how the similar package; after, you must add the file AllTest.class created in the projectname.allpackagetest.AllTest.java. For example, if you have created the package named it.uniba.di.cgd.jabber with AllTest.java, you must insert into it.uniba.di.cgd.jabber.test.allpackagetest.AllTest.java the new class as shown in the figure below.


Figure 3. AllTest for the it.uniba.di.cgd.jabber test package

Then, if you add a new package with a new AllTest at package level, make sure you remember to add it to the AllTest at project level. The project AllTest file is it.uniba.di.cdg.econference.tests.AllTest and belongs to the project named it.uniba.di.cdg.econference-tests. Look at the code snippet below as a clarification.

package it.uniba.di.cdg.econference.tests;

import org.junit.runner.JUnitCore;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;

@RunWith(Suite.class)
@Suite.SuiteClasses({
it.uniba.di.cdg.collaborativeworkbench.boot.test.allpackagetests.AllTests.class,
it.uniba.di.cdg.jabber.test.allpackagetests.AllTests.class,
it.uniba.di.cdg.skype.test.allpackagetests.AllTests.class,
it.uniba.di.cdg.xcore.econference.test.allpackagetests.AllTests.class,
it.uniba.di.cdg.xcore.m2m.test.allpackagetests.AllTests.class,
it.uniba.di.cdg.xcore.network.test.allpackagetests.AllTests.class,
it.uniba.di.cdg.xcore.ui.test.allpackagetests.AllTests.class,
it.uniba.di.cdg.xcore.util.test.allpackagetests.AllTests.class })
		
public class AllTests {
	public static void main(String[] args) {
		JUnitCore.runClasses(new Class[] { AllTests.class });
	}
}
Comment by chid1...@gmail.com, Jul 5, 2012

kind of good for the beginner

Comment by veerahan...@gmail.com, Jul 17, 2012

It was nice. Need some more explanation on test suites, then it will be vary nice.

Comment by savingfu...@gmail.com, Aug 20, 2012

Great tutorial,something worth reading to quickly start on Junit4. By the way here is complete list of JUnit4 annotations

Comment by seattlec...@gmail.com, Sep 13, 2012

Nice xplanations.. Thank u.

Comment by atchyuta...@gmail.com, Feb 6, 2013
@Test(expected=InterruptedException?.class)
public void divideByZero() {
int n = 2 / 0;
}

If the exception is not raised or if it's different from that expected, the test will fail. According to this explanation you have given, the test has to fail but here error:1 failure:0. it is showing like this. failure must be 1

Comment by shilpa_w...@yahoo.co.in, Jul 17, 2013

thanks for such nice document, t was very useful to me

Comment by shashank...@gmail.com, Jul 27, 2013

Nice doc

Comment by veenakri...@gmail.com, May 13, 2014

very easily we can understand.


Sign in to add a comment
Powered by Google Project Hosting