JUnit Tutorial

farrightSoftware and s/w Development

Aug 15, 2012 (5 years and 4 days ago)

547 views

JUnit Tutorial

ECE453/SE465/CS447/CS647

Presented and Edited by: Abdel Tawakol


By: Mehdi Amoui

Introduction

Introduction to the JUnit framework.


Hopefully, after this tutorial you will
have a
basic understanding of JUnit to:


implement test classes in JUnit 4.


test exceptions using JUnit.


use the
JUnit

Netbeans

plug
-
in.

What is JUnit


Open source Java testing framework that helps in the
automation of unit tests for Java classes.



Used to write and run repeatable automated test cases.



JUnit can be used as stand alone Java programs (from
the command line) or within common Java IDEs such as
Eclipse and
Netbeans



By Kent Beck and Erich Gamma.


Check:
junit.org


Current stable version:
junit
-
4.10.jar

Steps to perform unit tests
(Junit)

1.
Prepare

(or set up) environment conditions that must be met,
according to the test plan. At this stage, define and set prefix
values. E.g. instantiate objects, initialize fields, turn on logging, etc.


2.
Execute

the test case. This means, executing (exercising) the part
of the code to be tested. For that we use some test inputs (test
case values), according to the test plan.


3.
Evaluate

the results, or side effects generated by the execution of
the test case, against an expected value as defined in the test
plan.


4.
Clean up
(or tear down) the test environment if needed so that
further testing activities can be done, without being influenced by
the previous test cases. We deal here with postfix values.

Step 1: Unit Testing with JUnit 4

1.
Prepare (or set up) the test environment:

-

Annotate with @Before: Those methods are
executed before each test case (test method).


@Before

public void
setUp
() {


s = new Sample();

}


Step 2&3: Unit Testing with JUnit 4

2. Execute the test case.

3. Evaluate the results (or side effects).


This is done by exercising the code under test with the
appropriate test values. Each method is:


Annotated with @Test


Evaluation of the expected results (or side effects) is done in the
same method using assertions


@Test

public
void

testAddition
( ) {


int

a=3 , b=6;


int

expectedOutput

= (
a+b
);


int res = s.Addition(a, b);


assertEquals(expectedOutput, res);

}

Step 4: Unit Testing with JUnit 4

4. Clean up (or tear down) the test environment is done
in one or several methods that are run after execution
of each test method.


A method has to be annotated with @After.


If you allocate external resources in a @
Before

method,
you need to release them after the test runs.


Annotating a public void method with @After causes that
method to be run after the @
Test

method.


All @After methods are guaranteed to run even if a
@
Before

or @
Test

method throws an exception.


@After

public void
tearDown
() {


s = null;

}

@BeforeClass and @AfterClass


@
BeforeClass

uses:


Sometimes several tests need to share computationally expensive setup
(like logging into a database).



This can compromise the independence of tests! But sometimes it is a
necessary optimization.



@
BeforeClass

causes a method to be run once before any of the test
methods in the class.



@
AfterClass

uses:


A method with @
AfterClass

causes that method to be run after all the
tests in the class have been run.



The @
BeforeClass

and @
AfterClass

methods of
superclasses

will be run
before those the current class.

An Example

import org.junit.*;

import static org.junit.Assert.*;


public class TestM {



private M m;



public TestM() {


}



@Before


public void setup() {


m = new M();


}



@After


public void tearDown() {


m = null;


}



@Test


public void testDummyMethod() {


int expected = 0;


int res = m.dummyMethod();


assertTrue( (expected == res) );


}

}

Asserting Desired Results


The mechanism by which JUnit determines the success
or failure of a test is via an assertion statement.


An
assert
is simply a comparison between an expected
value and an actual value.


There are variants of the assert methods for each
primitive datatype and for
java.lang.String

and
java.lang.Object
, each with the following signatures:


assertEquals(expected, actual)


assertEquals(String message, expected, actual)


The second signature for each datatype allows a
message to be inserted into the results, which makes
clear identification of which assertion failed.

JUnit Assertion API


assertEquals(expected, actual)


This assertion states that the test expected.equals(actual) returns true, or both objects are null. The equality
test for a double also lets you specify a range, to cope with floating point errors better. There are overloaded
versions of this method for all Java

s primitive types.



assertNull(Object object),


This asserts that an object reference equals null.




assertNotNull(Object object),


This asserts that an object reference is not null.



assertSame(Object expected, Object actual),


Asserts that the two objects are the same. This is a stricter condition than simple equality, as it compares
the object identities using expected == actual.



assertTrue(boolean condition),


This assertion fails if the condition is false, printing a message string if supplied.



fail()


This forces a failure (manually). This is useful to close off paths through the code that should not be
reached.

Note: All of the methods return void.

Assertion Example

public class Calc

{


static public long add (int a, int b)


{


return a + b;


}

}

import org.junit.Test

import static org.junit.Assert.*;


public class CalcTest

{


@Test public void testAdd()


{ // Calc().add() returns long,


// so we must cast 5


assertEquals((long) 5, new Calc().add(2,3));


}

}

Testing Exceptions in JUnit 4


We can use @Test with the attribute
expected:


@Test (expected=ArithmeticException.class)

public void testDivideByZero( ) {


s.divideByZero( );

}

Manually Checking Exceptions


You can also use fail() to manually trigger failure of a test.


@Test

public void testAnotherException ( ) {


try{


s.anotherException(0);


// With the method fail, we can notify


// the framework that the test is failed.


fail("MyException was not thrown!

);


}


catch (MyException e ) {


//Here we have access to more info


assertNotNull(e.getMessage());


}

}

Assume API


A set of methods useful for stating assumptions about the conditions in
which a test is meaningful.


A failed assumption does not mean the code is broken, but that the test
provides no useful information.


The default JUnit runner treats tests with failing assumptions as ignored.


// only provides information if database is reachable.

@Test public void
calculateTotalSalary
() {


DBConnection

dbc

=
Database.connect
();


assumeNotNull
(
dbc
);


// ...

}


These methods can be used directly:
Assume.assumeTrue
(...), however, they
read better if they are referenced through static import:

import static
org.junit.Assume
.*;


...
assumeTrue
(...);

How to Run Test Cases


TestRunner classes provided by JUnit are used to execute all tests
prefixed by the word

test.






or you can write a self
-
executable test class:






In JUnit 3 (deprecated):


text
-
based one: junit.textui.TestRunner


Swing
-
based one: junit.swingui.TestRunner



From the command line:




java org.junit.runner.JUnitCore org.example.antbook.junit.SimpleTest

public static void main(String args[]) {


org.junit.runner.JUnitCore.main(LoadTester.class.getName());

}

java junit.textui.TestRunner org.example.antbook.junit.SimpleTest

.

Time: 0.01

OK (1 tests)

JUnit version compatibility


You may occasionally see old versions of JUnit tests


Major change in syntax and features in JUnit 4.0


Backwards compatible (JUnit 3.X tests still work)


In JUnit 3.X

1.
import junit.framework.*

2.
extend TestCase

3.
name the test methods with a prefix of

test


4.
validate conditions using one of the several assert methods


In JUnit 4.0 and later:


Do not extend from Junit.framework.TestCase


Do not prefix the test method with

test



Use one of the assert methods


Run the test using JUnit4TestAdapter


@NAME syntax introduced (Java annotations)

JUnit Test Fixtures


A test fixture is the
state

of the test


Objects and variables that are used by more than one test


Initializations (
prefix

values)


Reset values (
postfix

values)



Different tests can use the objects without sharing the state.



Objects used in test fixtures should be declared as instance
variables.



They should be initialized in a @Before method.



Can be free or reset in an @After method.



You must prevent one test from affecting the
behavior

of another.



Tests should never make assumptions about the order in which they
are called.

Writing a TestSuite


Tests can be grouped into a
suite
by using
the TestSuite class.


Test suites let you build several individual
test cases for a particular subsystem and
write an all
-
inclusive TestSuite that runs
them all.


It allows specific ordering of tests (ideally
the order of tests should not be relevant as
each should be able to stand alone).

Simple Test Suite

import org.junit.runner.RunWith;

import org.junit.runners.Suite;



@RunWith(Suite.class)

@Suite.SuiteClasses({TestSample.class, TestM.class})

public class MySuite {

}

public class AllTests extends TestSuite {


static public Test suite() {


TestSuite suite = new TestSuite();


suite.addTestSuite(SimpleTest.class);


return suite;


}

}

JUnit 3.x: (you don

t need to use this deprecated syntax!)

JUnit 4.x:

Stack Example (JUnit 4.x)

public class Stack {


public String toString()


{ // EFFECTS: Returns the String representation


// of this Stack from the top to the bottom.


StringBuffer buf = new StringBuffer ("{");


for (int i = size
-
1; i >= 0; i
--
)


{


if (i < (size
-
1))


buf.append (", ");


buf.append (elements[ i ].toString());


}


buf.append ("}");


return buf.toString();


}



public boolean repOk() {


if (elements == null) return false;


if (size != elements.length) return false;


for (int i = 0; i < size; i++) {


if (elements[i] == null) return false;


}


return true;


}

}

Test Class Setup


Classes to Import






Pre Operations:






Post Operations:


import org.junit.After;

import org.junit.Before;

import org.junit.Test;

import static org.junit.Assert.assertEquals;

import junit.framework.JUnit4TestAdapter;

private Stack stack;

// setUp method using @Before syntax

// @Before methods are run before each test

@Before public void runBeforeEachTest(){


stack = new Stack();

}

// tear
-
down method using @After

// @After methods are run after each test

@After public void runAfterEachTest(){


stack = null;

}

Test Cases

@Test public void testToString(){


stack = stack.push (new Integer (1));


stack = stack.push (new Integer (2));


assertEquals ("{2, 1}", stack.toString());

}


@Test public void testRepOk(){


boolean result = stack.repOk();


assertEquals (true, result);


stack = stack.push (new Integer (1));


result = stack.repOk();


assertEquals (true, result);


stack = stack.pop();


result = stack.repOk();


assertEquals (true, result);


stack = stack.push (new Integer (1));


stack.top();


result = stack.repOk();


assertEquals (true, result);

}

Test Cases (Splited)

@Test public void testRepOkA(){


boolean result = stack.repOk();


assertEquals (true, result);

}


@Test public void testRepOkB(){


stack = stack.push (new Integer (1));


result = stack.repOk();


assertEquals (true, result);

}


@Test public void testRepOkC(){


stack = stack.pop();


result = stack.repOk();


assertEquals (true, result);

}


@Test public void testRepOkD(){


stack = stack.push (new Integer (1));


stack.top();


result = stack.repOk();


assertEquals (true, result);

}

Test Suite

import org.junit.runner.RunWith;

import org.junit.runners.Suite;

import junit.framework.JUnit4TestAdapter;


// This section declares all of the test classes in the program.

@RunWith (Suite.class)

@Suite.SuiteClasses ({ StackTest.class }) // Add test classes here.


public class AllTests{


// Execution begins at main(). In this test class, we will execute


// a text test runner that will tell you if any of your tests fail.


public static void main (String[] args) {


junit.textui.TestRunner.run(suite());


}



// The suite() method is helpful when using JUnit 3 Test Runners or Ant.


public static junit.framework.Test suite() {


return new JUnit4TestAdapter(AllTests.class);


}

}

JUnit Resources & References


JUnit 4.x Howto
, by Blaine Simpson


Testing with JUnit
, by Erik Hatcher and Steve
Loughran


JUnit 4.0
-

A Quick Start Guide
, by J. Uwe
Pipka


JUnit: A Starter Guide
, by Diaspar software


JUnit Primer
, by Clarkware consulting


JUnit Automated Software Testing Framework
,
by Paul Ammann & Jeff Offutt


http://netbeans.org/kb/docs/java/junit
-
intro.html#Exercise_11