0% found this document useful (0 votes)
306 views

Unit Testing For Java

JUnit is an open source unit testing framework for Java that allows automated testing of Java code. It allows writing and running repeatable tests and includes features like assertions, test organization into test cases and test suites, and test runners for displaying results. Tests using JUnit make assertions about expected results and outputs to verify code is working as intended.

Uploaded by

hakobhn
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
306 views

Unit Testing For Java

JUnit is an open source unit testing framework for Java that allows automated testing of Java code. It allows writing and running repeatable tests and includes features like assertions, test organization into test cases and test suites, and test runners for displaying results. Tests using JUnit make assertions about expected results and outputs to verify code is working as intended.

Uploaded by

hakobhn
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 53

JUnit

Unit Testing Framework for Java

Page 1
Introduction
 What is JUnit?

 JUnit Structure

 Junit Short Explanation

 JUnit 3.8 vs. JUnit 4.x

 JUnit Integration with Eclipse

 Mock Objects: JMock & EasyMock

 Java Code Coverage Tools: EclEmma, Cobertura

Page 2
What is JUnit?
 Open source Java testing framework used to write and run repeatable automated tests

 Conforms to xUnit Architecture

 JUnit features include:


– Assertions for testing expected results

– Test features for sharing common test data

– Test suites for easily organizing and running tests

– Graphical and textual test runners

 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.

 Download JUnit: http://www.junit.org or as Eclipse plug-in.

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

 public void testXXX()

 assertions per method

 Implement main to run from TestCase TestSuite


command-line, but not necessary
 Optionally add setUp/tearDown methods
if any shared data is needed in tests YourTest

Page 5
Assertions
Method Description
assertEquals(Object, Object) Asserts that two objects are equal.

assertFalse(boolean) Asserts that the condition is false.

assertTrue(boolean) Asserts that the condition is true

assertNotNull(Object) Asserts that an object is not null.

assertNull(Object) Asserts that an object is null

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.

Simple Test Case creation:


public class StringTest extends TestCase {

public void testSimpleEquality() {


String s1 = new String(“abcd”);
String s2 = new String(“abcd”);
assertTrue(“Strings not equal”, s1.equals(s2));
}
}

Page 7
Test Suite
TestSuite object groups and runs any number of test cases together.

 TestSuite groups together test cases in the following ways:


• Create a new TestSuite object and add each test method to the suite

TestSuite suite= new TestSuite();


suite.addTest(new StringTest(“testSimpleEquality”));

TestResult result= suite.run();

• 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.

 The textual runner - junit.textui.TestRunner


 Displays "OK" if all the tests passed
 Failure messages if any of the tests failed.
java StringTest
.......
Time: 0.05
Tests run: 1, Failures: 0, Errors: 0

The graphical runner - junit.swingui.TestRunner


 Displays Swing window with a green progress bar if all the
tests passed.
 Displays a red progress bar if any of the tests failed.

Page 9
JUnit: Short Explanation 1
Let start with simple program to test.

public final class IMath {


/**
* Returns an integer approximation to the square root of x.
*/
public static int isqrt(int x) {
int guess = 1;
while (guess * guess < x) {
guess++;
}
return guess;
}
}

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.*;

/** A JUnit test class to test the class IMath. */


public class IMathTest extends TestCase {

/** Tests isqrt. */


public void testIsqrt() {
assertEquals(0, IMath.isqrt(0)); /** Returns the test suite for this test class. */
assertEquals(1, IMath.isqrt(1)); public static Test suite() {
assertEquals(1, IMath.isqrt(2)); return new TestSuite(IMathTest.class);
assertEquals(1, IMath.isqrt(3)); }
assertEquals(2, IMath.isqrt(4));
assertEquals(2, IMath.isqrt(7)); /** Run the tests. */
assertEquals(3, IMath.isqrt(9)); public static void main(String[] args) {
assertEquals(10, IMath.isqrt(100)); junit.textui.TestRunner.run(suite());
} // junit.swingui.TestRunner.run(suite());
}
}

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

•Question: Is this better? Why?


Page 14
JUnit: Basic Usage of JUnit
To test a type T: import junit.framework.*;
1. Write a class like:
/** A JUnit test class for the class T. */
public class TTest extends TestCase {
/** Runs the tests. */
public static void main(String[] args) {
junit.textui.TestRunner.run(suite());
}

/** Returns the test suite for this test class. */


public static Test suite() {
return new TestSuite(TTest.class);
}

<test methods go here>


}

Page 15
JUnit: Basic Usage of JUnit (Cont.)
2. Compile T.java and TTest.java
$ javac T.java TTest.java

3. Run the JUnit graphical user interface on TTest


$ java junit.swingui.TestRunner TTest

or

Run the text interface (good from makefiles)


$ java TTest

4. Look at the failures and errors

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;

public class AdditionTest extends TestCase {


private int x = 1;
private int y = 1;
public void testAddition() {
int z = x + y;
assertEquals(2, z);
}
}

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;

public class AdditionTest {


private int x = 1;
private int y = 1;
@Test public void addition() {
int z = x + y;
assertEquals(2, z);
}
}
 Parameterized Test Cases (current sample is working in early version of JUnit 4.x only)
import org.junit.*;
import static org.junit.Assert.*;
public class AdditionTest {
@Parameters public static int[][] data = new int[][] { {0, 0, 0}, {1, 1, 0}, {2, 1, 1}, {3, 2, 1}, {6, 8, -2} };
@Parameter(0) public int expected;
@Parameter(1) public int input1;
@Parameter(2) public int input2;

@Test public void testAddition() {


assertEquals(expected, add(input1, input2));
}
private int add(int m, int n) { return m+n; }
}
Page 18
JUnit 3.8 vs. 4.x
 @Before - @Before annotation identifies a method to run before each test:

@Before protected void initialize() {


System.setErr(new PrintStream(new ByteArrayOutputStream()));
inputDir = new File(inputDir, "input");
}

 @After - @After annotation identifies a method to run after each test:

@After protected void disposeDocument() {


doc = null;
System.gc();
}

 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

1. Create a new project – AccountManagement.


2. Create src folder for placing source.
3. Create test folder for placing tests.
4. Create accountmgmt package under src.
5. Create accountmgmt package under test.

Page 21
JUnit Integration with Eclipse
2. Add JUnit reference

1.Select properties of the project.


2.Select Java Build Path – Libraries
3.Add junit.jar to the libraries.

Page 22
JUnit Integration with Eclipse
3. Create a test

1.Create a test class: AccountManagerTest.java


2.Import junit.framework.TestCase
3.Create the first test method testDepositMoney()

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

1.The AccountManagerTest should test the instance of class AccountManager.


2.Create a new class AccountManager in the src/accountmgmt package.
3.Declare the AccountManager class variable in the test class
4.If you run the test again, you will get the green line.

Page 25
JUnit Integration with Eclipse
6. Add additional data (if any) for
class under test.

1.Create an Account class to hold account


information.
1.Create accountID and balance properties
for Account.

Page 26
JUnit Integration with Eclipse
7. Create the method to test.

1.Create depositMoney() method in AccountManager class.


2.This method will have Account and money parameters, in order to add money to the given
Account.
3.For the first run, leave the method without implementation.

Page 27
JUnit Integration with Eclipse
8. Create the instance to test.

1.Create a new instance of AccountManager class in order to test.


2.Create setUp() method, which will contain initialization of the AccountManager class.
3.Create implementation for testDepositMoney() method.
• Create a new account with accountID=“1”
and balance = 100.
• Define amount of money to deposit: money = 50.
• Define expected balance after deposit: 150.
• Get the actual balance after running
testDepositMoney() method.

4.In order to test the expected and actual results,


add assert – assertEquals method.

Page 28
JUnit Integration with Eclipse
9. Run the test again.

1.Run the test, in order to compare expected and actual values.


2.A red line will appear, indicating that the expected and actual values are different.

Page 29
JUnit Integration with Eclipse
10. Add implementation for the method under test.

1.In AccountManager class add implementation for depositMoney() method.

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.

 Lets you specify the interactions between your objects.

 Works well with the auto-completion and refactoring features of your IDE

 Plugs into your favorite test framework

 Home page: http://www.jmock.org/

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;

public class TestJMockCase{


   @Test
   public void testSayHello(){
         Greeting o = new Greeting();
         String out = o.SayHello(”Simon”);
         assertEquals(”Good afternoon, Simon”, out);
   } 
}
Page 34
JMock : Example 1.2
Because we haven’t created the class of Greeting, we will fail in compiling this test case. In
order to make it through compilation, we need to code the Greeting class. And we find the
Greeting class have to communicate with the other class named GreetingTime to get the
words of greeting.
public class Greeting{
//we have to define GreetingTime as an interface
//we are going to explain it in the later
private GreetingTime gt;
public void setGreetingTime(GreetingTime gt){
this.gt = gt;
}

public String sayHello(String name){


String greeting = gt.getGreeting();
return greeting+”, “+name;
}
}

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.

public interface GreetingTime{


public String getGreeting();
}

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);

//set the expectation for the mock object


context.checking(new Expectations(){{
//the mock object will call the getGreeting method once
//and we assume that is returns “Good afternoon”
one(gt).getGreeting(); will(returnValue(”Good afternoon”));
}});

String out = g.sayHello(”Simon”);


//compare the result and expected value
assertEquals(”Good afternoon, Simon”,out);
}
} Page 38
JMock : Example 1.6
Now, we can open the command window to test.

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.

interface Subscriber { public class Publisher {


void receive(String message); private ArrayList<Subscriber> subscribers;
}
public Publisher(){
subscribers = new ArrayList<Subscriber>();
}
public void add(Subscriber subscriber){
subscribers.add(subscriber);
}

public void publish(String message){


((Subscriber)subscribers.get(0)).receive(message);
}
}

We need to test that a Publisher sends a message to a single registered Subscriber.

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

Write the test case:


import org.jmock.Mockery;
import org.jmock.Expectations;

class PublisherTest extends TestCase {


Mockery context = new Mockery();

public void testOneSubscriberReceivesAMessage() {


...
}
}

Page 41
JMock : Another Example 2.3
Import JMock dependencies

Create Context in which


Publisher exists

Set up the context in which


the test will execute.

Define expectations on
the mock Subscriber that
specify methods that are
expected to be called
during the test run.

After the code under test


has finished our test must
verify that the mock
Subscriber was called as
expected.

Page 42
EasyMock: Example
Create the mock and link to
the object under test

Define and record the


expectations. After calling
replay() the mock object
will behave according to
defined expectations

Call the method(s) under test


and verify that everything
went as expected.

Page 43
Java Source Code Coverage tools
Describes the degree to which the source code of the program has been tested.

 EMMA for Eclipse

 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

coverage tool for Eclipse


 Based on EMMA Java code coverage tool
 On JUnit test runs the code can directly be
analyzed for code coverage.
 Coverage results are immediately summarized and
highlighted in the Java source code editor.
 Supported coverage types: class, method, line,
basic block.
Coverage stats are aggregated at method, class,
package, and "all classes" levels.
Output report types: plain text, HTML, XML.
Coverage data obtained in different instrumentation
or test runs can be merged together.
URL: http://update.eclemma.org/index.html

Page 46
EMMA for Eclipse : Coverage Mode
EclEmma adds a new launch mode
Coverage which is available from the Run
menu and the toolbar.

Existing launch configurations can be


launched directly in Coverage mode
using default settings.

 In the Coverage Configuration ->


Coverage tab the Java packages for
coverage analysis can be selected. At
least one entry must be selected to run
an application in Coverage mode.

Page 47
EMMA for Eclipse: Coverage Results
Use Coverage command
to run coverage analysis.

Green lines specify that


the code was covered by
tests run

Red lines specify that the


code was not covered by
tests run

Coverage tab shows the


coverage results.

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

Green lines specify that


the code was covered by
tests run

Red lines specify that the


code was not covered by
tests run

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

You might also like