The Agile Architect

Home » All Articles » Brief Introduction to JUnit

Brief Introduction to JUnit

Once upon a time, testing used to be an isolated step of the development process, traditionally the last stage before the release. As software development evolved through the hard lessons of delays and failures, testing has been progressively moved into earlier stages of the development process. Modern development philosophies, such as RAD, XP, and Agile, advocate the development of tests in parallel with the development of the code.

Although the quest for a software development process that works is ongoing, unit testing has been provably one of the necessary ingredients for the optimal mixture. Unit tests facilitate and encourage modular development by testing small modules (methods or classes) of code. Unit testing is ideally suited for Object Oriented Programming where objects are semi-independent functional modules.

There are two factors that set unit testing apart from other types of testing such as functional, acceptance, and integration testing. The first is that unit tests, as the name suggest, aim to test each unit of code (module or function) independently of one another and not as an integrated deployment. The second factor is that unit tests are written by developers and not by QA engineers.

Quick Overview of JUnit

JUnit is the most widespread unit-testing tool for Java. The principal value of JUnit does not lie in an extensive testing API – in fact it’s API is quite small – but in giving the development team the ability to create easily re-runnable test cases. In particular, JUnit integrates with all standard IDEs and popular building frameworks such as Ant and Maven, so it can be easily incorporated in the daily development process. Let me illustrate this point with an example.

Consider a common legacy way of testing code, which is to write a main method and print out the result:

public static void main(String[] args) {      
     System.out.println(NumberUtilities.numDecimalPlaces(-123.03993232)); 
}

This code snippet will execute the function under testing and print out the result. The developer examines the result and determines if the function does the right thing.
Here are some immediate problems with this approach:

  1. Suppose you have a hundred such tests. Can you run all the tests every time and verify each individual result?
  2. Suppose a number of months elapses since the test was written. Will you be able to remember what the desired output of this particular method was supposed to be?

Let’s contrast this with the equivalent JUnit snippet:

@Test
public class NumberUtilitiesTest {
    public void testNumDecimalPlaces() {  
         assertEquals(10,NumberUtilities.numDecimalPlaces(-123.03993232));
     }
}

The @Test annotation flags the method as a unit test. This tips your IDE, ant, or maven script to execute this as a unit test. The assert statement, rather than displaying the result, compares it against an expected value. The first thing to observe is that there is no extra effort whatsoever in writing the test case as a unit test rather than a main method. Let’s see how doing this resolves the problems we discovered:

    1. You don’t have to run the tests manually because your IDE or ant script can run all of them as a testing suite. Furthermore, you don’t need to inspect any results because they are compared against expected values.
    2. You don’t have to remember the expected output because it is part of the test.

As long as your code works as expected, JUnit does not make you do any extra work. The tests run as part of your build and if they pass JUnit remains silent. You only get a report if any test fails, in which case you are given information about the test that failed and a full stack trace. For example, suppose that someone introduced a bug in the code that truncates to 8 decimal places instead of 10. JUnit would produce the following exception in the report:

junit.framework.AssertionFailedError: expected: but was:
	at junit.framework.Assert.fail(Assert.java:47)
	at junit.framework.Assert.failNotEquals(Assert.java:282)
	at junit.framework.Assert.assertEquals(Assert.java:64)
	at junit.framework.Assert.assertEquals(Assert.java:201)
	at junit.framework.Assert.assertEquals(Assert.java:207)
	at com.adaptiveinternational.wsg.util.NumberUtilitiesTest.testNumDecimalPlaces(NumberUtilitiesTest.java:8)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Architected By:

%d bloggers like this: