Unit test and JUnit
June 2010
Contents
What is unit test ?
What is and How to use JUnit.
Using Junit together with Mock objects.
Using Junit together with Djunit.
Using Junit together with Maven.
Using Junit together with Continuous
integration.
What is unit test ?
Unit testing is a software verification and
validation method in which a programmer
tests if individual units of source code are
fit for use. A unit is the smallest testable
part of an application (usually a method or
function)- Wikipedia
Typically a programmer will write the unit
test code will establish some sort of
artificial environment and then invoke
methods or functions in the module being
tested.
The benefit of unit test
1. Find problems early.
2. Safely re-factor code at a later date.
3. Integration testing becomes much easier.
4. Living documentation of the system.
What is JUnit ?
JUnit is just a general testing framework.
You can use it to do unit testing:
Testing a single class in isolation.
You can use it to do integration testing:
Testing the interactions of a class with real
collaborator classes.
Almost a de-facto standard in the Java
field.
Why use JUnit ?
JUnit help increasing quality.
JUnit is simple, and has a short learning curve .
JUnit is supported by popular IDEs.
Junit can be used together with other
development tools : test coverage, continuous
integration.
JUnit is free.
How to write Junit
To write a test case, follow these steps:
1. Define a subclass of TestCase: XXXTest.
2. Override the setUp() method to initialize object(s)
under test.
3. Define one or more testXXX() methods that exercise the
object(s) under test.
4. Override the tearDown() method to release object(s)
under test.
Code sample
package testing;
import junit.framework.TestCase;
public class FirstTest extends TestCase {
protected void setUp() throws Exception {
super.setUp();
}
protected void tearDown() throws Exception {
super.tearDown();
}
public void testCompareSucceed() {
assertEquals(0, 0); //this assertion will succeed
}
public void testCompareFail() {
assertEquals(0, 1); //this assertion will fail
}
}
Set Up Conditions
Set up the data required by the method:
declaring a few variables, creating a
number of records in the database.
Should always create their own test data
to execute against.
Call the method
being tested
Call the method directly
<example here>
Verify the results are
correct
Verifying that your code works as you expect it
to work is the most important part of unit
testing. The following assert functions can be
used to verify.
assertEqual(x,y)
assertFalse(boolean)
assertTrue(boolean)
assertNull(object)
assertNotNull(object)
assetSame(firstObject, secondObject)
assertNotSame(firstObject, secondObject)
Clean up
Rollback changes to database
What to Test
Testing Normal Conditions: write a test
that will exercise the code in the most
basic way
Testing Unexpected Conditions: to make
sure that the code will still handle these
unexpected scenarios appropriately.
Bad Input Values
Boundary Conditions
Regression Tests
Add tests to your test suite every time
you find a bug in your code
Well-Written Unit
Tests
Your unit tests thoroughly verify that your code
works as we expect it to work
Your unit tests should be able to be run
repeatedly and continue to produce the same
results, regardless of the environment in which
the tests are being run.
Each of your unit tests must be independent
from your other unit tests. Unit tests do not
alter the state of the database.
Your unit tests should only test one aspect of
your code at a time, so that it is easy to
understand the purpose of each unit test.
What are Mock
Objects?
Most software units do not work alone,
but collaborate with other units. To test
a unit in isolation, the collaborators
must be simulated
Mock objects have the same interfaces
of the objects they mimic
A mock is configured to simulate the object
behavior that it replaces
A mock object also verifies whether it is
used as expected
Why are Mocks
useful?
Isolate modules for unit testing.
Depend on an interface and not on an
implementation (which couldn't exist
yet)
Mock Object
frameworks
Frameworks: JMock, EasyMock, Mockito
Benefits:
Generate mocks for interfaces
Hand writing mocks is not needed
Supports compiler check and refactoring
Supports method return values and exceptions
How to use Mock
objects ?
1. Create a Mock Object for the interface
to simulate
2. Record/Create the expected behavior
3. Perform the method call to the class
under test that is supposed to interact
with the mock object
4. Verify the mock has been used
correctly
Djunit
Djunit (http://works.dgic.co.jp/djunit/) is an
Eclipse plug-in that generates test coverage
reports.
There are four types of coverage:
Method coverage: how many of your methods have
been called by your test cases?
Statement coverage: how many of your statements
have been run by your test cases?
Decision/Branch coverage: how many decision
points (if statements) have evaluated both true and
false?
Condition coverage: how many Boolean sub-
expressions have been evaluated both true and false
at a decision point?
How to run Djunit
Install the Eclipse plug-in
Run in the similar way as running Junit
Right click on the test case class or test suite
class and select Run As > djUnit Test.
djUnit Coverage
Report
DjUnit example
<example here>
What is Maven ?
Maven is a popular open source build tool
for enterprise Java projects.
Maven uses a declarative approach, where
the project structure and contents are
described, rather then the task-based
approach used in Ant or in traditional
Make files.
Apply best practices in development
standards and reduces the time needed to
write and maintain build scripts.
Maven lifecyle phases
Run Unit test in
Maven
Test everything:
mvn test
Test single test case:
mvn -Dtest=MyTestCase test
Test multiple test cases:
mvn -Dtest=MyTestCase,MyOtherTestCase test
What is Continuous
integration ?
Continuous Integration is a software
development practice where members of
a team integrate their work frequently,
usually each person integrates at least
daily - leading to multiple integrations
per day. Each integration is verified by an
automated build (including test) to
detect integration errors as quickly as
possible. - Martin Fowler-
CI working scenarios
How to apply CI
These steps can be applied on a project.
Identify: Identify a process that requires automation.
The process may be in the areas of compilation, test,
inspection, deployment, database integration and so
on.
Build: Creating a build script makes the automation
repeatable and consistent.
Share: By using a version-control system such as
Subversion, you make it possible for others to use these
scripts/programs. Now the value is being spread
consistently across the project.
Make it continuous: Make sure that the automated
process is run with every change applied, using a CI
server.
CI Components
CI server
CruiseControl, Hudson, Luntbuild
Version control
Subversion, Git, SourceSafe, Mercurial
Build Tool
Maven, Ant
Test Frameworks
JUnit, EasyMock,
Test Coverage
DjUnit, Emma
Code Analysis
CheckStyle, Findbugs
Summary
Unit test execution best when part of an
automated build system.
Good set of automated tests allow for
incremental creation of code quality.
Unit Test starts with immature codebase
while other automation requires mature
codebase and design
Unit test limitation
It is impossible to evaluate every
execution path.
Unit test must be done together with
other testing activities.
There are problems which can be
tested.
Design considerations
Crossing such unit boundaries turns unit
tests into integration tests, and when
test cases fail, makes it less clear which
component is causing the failure.
Separate the interface from the
implementation of a class allows unit test
to be done via mock objects.