Unit Testing For Java
Unit Testing For Java
Page 1
Introduction
What is JUnit?
JUnit Structure
Page 2
What is JUnit?
Open source Java testing framework used to write and run repeatable automated tests
JUnit can be used as stand alone Java programs (from the command line) or within an
IDE such as Eclipse
JUnit’s web site: http://junit.org/index.htm.
Page 3
JUnit Structure
Test Case - Related set of tests.
Test Suite – Collection of related test cases.
Test Result - Collects any errors or failures that occur during a test.
Test Runner — A launcher of test suites.
Page 4
JUnit Usage
Subclass TestCase Assert <<interface>
*
Create Test methods Test
Page 5
Assertions
Method Description
assertEquals(Object, Object) Asserts that two objects are equal.
assertNotSame(Object, Object) Asserts that two references do not refer to the same object
assertSame(Object, Object) Asserts that two references refer to the same object
fail(String) Asserts that a test fails, and prints the given message
Page 6
Test Case
TestCase is usually a group of tests for methods in a single Java class.
Page 7
Test Suite
TestSuite object groups and runs any number of test cases together.
• JUnit extracts a suite from a TestCase by passing your TestCase class to the
TestSuite constructor:
TestSuite suite= new TestSuite(StringTest.class);
TestResult result= suite.run();
Page 8
Test Runners
Test Runners run the tests/suites and display results.
Page 9
JUnit: Short Explanation 1
Let start with simple program to test.
Page 10
JUnit: Short Explanation 2
First start testing by using the conventional way
/** A class to test the class IMath. */
public class IMathTestNoJUnit {
/** Runs the tests. */
public static void main(String[] args) {
printTestResult(0);
printTestResult(1);
printTestResult(2);
printTestResult(3);
printTestResult(4);
printTestResult(7);
printTestResult(9);
printTestResult(100);
}
private static void printTestResult(int arg) {
System.out.print(“isqrt(“ + arg + “) ==> “);
System.out.println(IMath.isqrt(arg));
}
}
Page 11
JUnit: Short Explanation 3
We will have the following Test Output
Isqrt(0) ==> 1
Isqrt(1) ==> 1
Isqrt(2) ==> 2
Isqrt(3) ==> 2
Isqrt(4) ==> 2
Isqrt(7) ==> 3
Isqrt(9) ==> 3
Isqrt(100) ==> 10 •What does this say about the code? Is it right?
•What’s the problem with this kind of test output?
POSSIBLE SOLUTION:
Automatic verification by using e.g. Junit testing tool!
Page 12
JUnit: Short Explanation 4
Testing with JUnit
import junit.framework.*;
Page 13
JUnit: Short Explanation 5
Compilation and Output
$ javac IMath.java IMathTest.java
$ java IMathTest
.F
Time: 0.02
There was 1 failure:
testIsqrt(IMathTest)junit.framework.AssertionFailedError: expected:<0> but was:<1>
at IMathTest.testIsqrt(IMathTest.java:23)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMeth...
at sun.reflect.Delegating...
at IMathTest.main(IMathTest.java:17)
FAILURES!!!
Tests run: 1, Failures: 1, Errors: 0
Page 15
JUnit: Basic Usage of JUnit (Cont.)
2. Compile T.java and TTest.java
$ javac T.java TTest.java
or
Naming Convention
Test methods start with “test” Test classes end with “Test”
e.g., testIsqrt, testMin e.g., IMathTest, ForYouTest
Page 16
JUnit 3.8 vs. 4.x
Typical JUnit 3.8 Test Case
import junit.framework.TestCase;
Typical JUnit 4.x Test Case. Note: JUnit 4.x requires Java 5 or higher.
Don't Have to Extend TestCase
import org.junit.Assert; //TestCase contains no longer the assert methods
public class AdditionTest {
private int x = 1;
private int y = 1;
@Test public void addition() { //no longer need a naming convention for test method name
int z = x + y;
Assert.assertEquals(2, z); //the asserts are static yet
}
}
Page 17
JUnit 3.8 vs. 4.x
Static Imports can be Used
import static org.junit.Assert.*;
import org.junit.Test;
Timeouts - It is a parameter in @Test annotation and specifies maximum time test may take.
Test that fails if it takes longer than half a second to find all the elements in a document:
@Test(timeout=500)
public void retrieveAllElementsInDocument() {
doc.query("//*");
}
Page 19
JUnit 3.8 vs. 4.x
Testing Exceptions
Old Way : try - catch New Way: @Test(expected=class)
public void testDivisionByZero() {
@Test(expected=ArithmeticException.class)
try {
int n = 2 / 0; public void divideByZero() {
}
int n = 2 / 0;
catch (ArithmeticException success) {
assertNotNull(success.getMessage()); }
}
}
Compatible
Forwards compatible: old test suites can be run in JUnit 4
Backwards compatible: old test runners can run the new test suites
To enable JUnit 4 tests to run in JUnit 3 environments, wrap them in a JUnit4TestAdapter
public static junit.framework.Test suite() {
return new JUnit4TestAdapter(TestClassName.class);
}
Page 20
JUnit Integration with Eclipse
1. Create a new project
Page 21
JUnit Integration with Eclipse
2. Add JUnit reference
Page 22
JUnit Integration with Eclipse
3. Create a test
Page 23
JUnit Integration with Eclipse
4. Run the first test
1.Right-click on AccountManagerTest.java
2.Select Run-as-> JUnit Test
3.JUnit tab appears on the left side
4.The green line shows that the test was
successful.
Page 24
JUnit Integration with Eclipse
5. Add class to test
Page 25
JUnit Integration with Eclipse
6. Add additional data (if any) for
class under test.
Page 26
JUnit Integration with Eclipse
7. Create the method to test.
Page 27
JUnit Integration with Eclipse
8. Create the instance to test.
Page 28
JUnit Integration with Eclipse
9. Run the test again.
Page 29
JUnit Integration with Eclipse
10. Add implementation for the method under test.
Page 30
JUnit Integration with Eclipse
11. Run the test again
1.After running the test again with implemented depositMoney() method, we get the green line !!!
Page 31
Mock Objects: JMock
JMock makes it quick and easy to define mock objects programming.
Works well with the auto-completion and refactoring features of your IDE
Page 32
JMock Components
Mockery - represents the context of the object under test: the objects that it communicates with.
Expectations – represents blocks that define what behavior is expected for the method under test.
invocation-count (mock-object).method(argument-constraints);
inSequence(sequence-name);
when(state-machine.is(state-name));
will(action);
then(state-machine.is(new-state-name));
Note: Except for the invocation count and the mock object, all clauses are optional.
Invocation Count
Invocation Count Description
one The invocation is expected once and once only.
exactly(n).of The invocation is expected exactly n times.
atLeast(n).of The invocation is expected at least n.
allowing The invocation is allowed any number of times but does not have to happen.
between(min, max).of The invocation is expected at least min times and at most max times.
Examples:
one (calculator).add(1, 1); will(returnValue(2));
allowing (calculator).add(with(any(int.class)), with(any(int.class)));
Page 33
JMock : Example 1.1
This Example use JUnit 4.3.1 and JMock 2.2.
First we need to compose following packages into classpath: junit-4.3.1.jar, jmock-
2.2.-.jar, jmock-junit4-2.2.0.jar, hamcrest-core-1.1.jar and hamcrest-library-1.1.jar.
We are going to create a small application which can say greetings to the client according
to time. For example, it outputs “Good morning, ***” in the morning, and outputs “Good
evening, ***” in the evening. So, we firstly create a test case.
//import some necessary classes from the package of JUnit4
import org.junit.Test;
import static org.junit.Assert.asserEquals;
Page 35
JMock : Example 1.3
In order to compile successfully, we also need to create the class of GreetingTime. But
now, our focus is not on the GreetingTime class, so we decide to use mock object and
therefore we have to define it as an interface, which is a prerequisite for the mock object.
Therefore, we have to use the setter method to inject the instance of GreetingTime to
Greeting.
Then, we have to make some changes to the test class we created before, because we are
going to mock the GreetingTime.
Page 36
JMock : Example 1.4
//import some necessary classes from the package of JUnit4
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.assertEquals;
//import some necessary classes from the package of JMock2.2
import org.jmock.Mockery;
import org.jmock.integration.junit4.JMock;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.jmock.Expectations;
@RunWith(JMock.class)
public class TestJMockCaseUsingJMock{
//create the context for the mock object
Mockery context = new JUnit4Mockery();
@Test
public void testSayHello()
{//..->
Page 37
JMock : Example 1.5
//Mock the GreetingTime class using the technology of reflection
//we have to define it as a final variable since it is going to be used in a inner
class
final GreetingTime gt = context.mock(GreetingTime.class);
Greeting g = new Greeting();
g.setGreetingTime(gt);
Page 39
JMock : Another Example 2.1
A Publisher sends messages to 0 or more Subscribers. We want to test the Publisher, which
involves testing its interactions with Subscribers.
Page 40
JMock : Another Example 2.2
Set up dependencies:
jmock-2.4.0.jar
hamcrest-core-1.1.jar
hamcrest-library-1.1.jar
Page 41
JMock : Another Example 2.3
Import JMock dependencies
Define expectations on
the mock Subscriber that
specify methods that are
expected to be called
during the test run.
Page 42
EasyMock: Example
Create the mock and link to
the object under test
Page 43
Java Source Code Coverage tools
Describes the degree to which the source code of the program has been tested.
Cobertura
Page 44
EMMA for Eclipse : Download
EclEmma ships as a small set of Eclipse plug-ins under the Eclipse Public License.
Prerequisites:
EclEmma requires Eclipse 3.1 or higher
Has no dependencies on a particular operating system.
Installation:
The update site for EclEmma is http://update.eclemma.org/.
1. From your Eclipse menu select Help → Software Updates → Find and Install...
2. Check Search for new features and press Next.
3. Press New Remote Site... and enter http://update.eclemma.org/ for the update site URL:
4. Press Finish.
5. Follow the steps in the installation wizard.
Page 45
EMMA for Eclipse : Features
Emma for Eclipse (EclEmma) is a free Java code
Page 46
EMMA for Eclipse : Coverage Mode
EclEmma adds a new launch mode
Coverage which is available from the Run
menu and the toolbar.
Page 47
EMMA for Eclipse: Coverage Results
Use Coverage command
to run coverage analysis.
Page 48
EMMA for Eclipse: Coverage Results
Coverage results are displayed in Coverage Tab, which shows:
Classes which were selected for coverage analysis
For each class coverage % by run tests
Number of covered lines
Number of total lines
The Coverage results can be exported to plain text, html or xml reports.
Page 49
Cobertura: Features
What is Cobertura?
Cobertura is a free Java tool that calculates the percentage of code accessed by tests.
It can be used to identify which parts of your Java program are lacking test coverage.
Where I can download this tool from?:
URL - http://cobertura.sourceforge.net/
Prerequisites:
Cobertura requires jdk 1.4 or higher
Designed for use with JUnit and Ant.
Has no dependencies on a particular operating system.
Features:
Can be executed from ant or from the command line.
Instruments Java bytecode after it has been compiled.
Can generate reports in HTML or XML.
Shows the percentage of lines and branches covered for each class, each package, and
for the overall project.
Shows the McCabe cyclomatic code complexity of each class, and the average
cyclomatic code complexity for each package, and for the overall product.
Can sort HTML results by class name, percent of lines covered, percent of branches
covered, etc. And can sort in ascending or decending order.
Page 50
Cobertura: Coverage Report
Page 51
Cobertura: Unit Test Results
Unit Test Results are shows:
Tests – Number of tests
Failures –Number of failures
Errors - Number of errors
Success rate – Coverage % by
run tests
Time – Tests’ running time in
seconds
Page 52
Thank you for your
participation!!!
Page 53