UNIT TESTING J2EE APPLICATIONS
Document Sample


UNIT TESTING J2EE
APPLICATIONS
Presented by:
Sudheer Sabbineni.
We will look at:
What Unit Testing is and why you should
do it.
Using the JUnit framework for unit
testing.
How to incorporate unit testing into your
development cycle.
How to unit test simple objects and
servlets.
The reality of writing code is that even the best
programmers make mistakes. As the schedule
gets more demanding, programmers become
overworked and even less likely to catch their
mistakes. The solution is to give programmers
the tools they need to catch mistakes.In this
chapter we will discuss a tool that can give all
these benefits a programmer-UNIT TESTING
The Concept of Unit Testing tells “Test First
Design”.
What is Unit Testing ?
Unit Testing is a method of White box testing
that should be an important part of the
development process
White box testing is distinguished from black
box testing in that it focuses on the
implementation details and should be
performed by someone familiar with the
implementation.
Unit testing only benefits the programmer if
used correctly.It will streamline programming
and make programmer more effective at work.
When you are doing white box testing you are
making sure your code works correctly. Black box
testing on the other hand,is concerned with testing
the system from the users prospective.The focus is
on whether the requirements have been met and
the actual implementation is not relevant.
Unit Testing focuses on small pieces of the
system,and these individual components or
units,are tested independently of other units.Unit
tests should put the component through a serious
of drills,including both valid and invalid inputs,to
determine whether the component passed or failed
each test.
In practice the best person to do Unit testing is is
the programmer.since the programmer interacts
with the code at the low level.
As with any testing, unit tests are better written
so that they are automated and easily repeated.
Given the constraints the tests should be written
by programmers.Although some try to add some
written documentation,the process works best
when the unit tests are allowed to stand alone.
This is best done within a framework and,while
you could write a framework yourself,there are a
variety of frameworks available for this
process.The premier for unit testing in java is
JUnit, written by Erich Gamma and Kent Beck.
Essentially,a unit test is a piece of code
that‟s takes a predefined unit of code and
manipulates it.
This Manipulation is a simulation of
various inputs to the unit. A unit test’s
purpose is to determine whether the unit
works as designed.
A unit test should never focus on integration
between components, we are merely
checking the specific behavior of the unit
What is a Unit ?
In Object Oriented language like java, a unit
always corresponds to a class.
First make sure you are really focusing on
testing a unit and not on integration or
interaction between those components.
These are two major cases that confuse the
issue:
1)Interface
2)Inheritance
The Best approach is to test the methods in the
class they are defined in
The tests that we write are related directly to
the methods of the class. there are some
guidelines to follow:
Don‟t need to write tests for getter and setter
methods unless they do something besides get
and set properties.
You will need to have atleast one test per
method,the key is to test a wide variety of inputs.
The various access modifiers also affect how to
write tests.Your baseline is that if another method
calls the method,it needs to be tested.
Your code needs to be tested either implicitly or
Explicitly .there is also a very important need to
document the testing and any changes made to
the code on that basis
Introduction of JUnit
Framework
Before we actually begin writing unit tests we
need to understand a little about the JUnit
framework and how it works.What's important
to understand is not the details of JUnit but the
basic idea behind what you‟re doing.
How do the methods of your program actually
test your class ? First the method manipulates
an instance of the class being tested.This might
mean calling a method or series of methods and
passing in specific inputs.Once the Object has
been manipulated, the methods of the program
issue Assertion about the expected state of the
object
An Assertion is a statement that must be true
if the code is working correctly.
We said that a test is a small program.In Java
terms this means that you are writing a class
with a main() method.The main() method when
executed involves various methods in order to
put the class you are testing into paces.
Using the JUint framework
The JUnit framework is a great framework for writing
unit tests.
Let‟s look at an example of how the JUnit framework
might be applied to a class.Let‟s assume we want to
test a class called StringUtility that has one method,
parse() which takes a string as an argument.
The test case might be called StringUtilityTest.A test
case extends the junit.framework.TestCase class
For each test you want to write within the test
case,you create a public,no arguments method
whose name starts with test.
The test case should have a main() method
that invokes the run() method on a
TestRunner.JUnit has both textual and
graphical test runners, so you can chose
whatever option you prefer.
Choosing a textual user Interface is faster
when running multiple tests very frequently
When you create a testX() method,each
method throws exception. This will allow all
unexpected exceptions to flow up to calling
environment and display as errors.
Within the testX( ) method,you have a variety of
assertions.where and assertion is a statement
about the expected state of an object.There are a
variety of assert( ) methods build in TestCase that
we can use.
The easiest one is assert(), which takes an optional
string followed by a boolean.The string will be
printed if the assertion fails.If the boolean
evaluates to true the assertion passes.If the
boolean evaluates to false, the assertion and thus
the test fails.
Ex:
assert(“Id of the product shall be 7” ,
product.getId()==7)
The idea in the above code is that the statement
product.getId()==7 should evaluate to true.If it
does, true will be passed to the assert() method
and the assertion will pass.if the expression
evaluates to false,the assertion will fail.
The other important assertions are assertEquals()
assertNotNull(), assertNull().
How to Approach unit
Testing:
Writing the tests first might seem
counterintuitive.
How do you even know what to code?
In a unit test you are defining the contract with
the object.You implicitly define the API,but you
also define all the requirements of the
component.
If you had written unit tests before the
component,you would have been forced to
consider various inputs to the component,
including null.
Steps of Unit Testing:
Determine the functionality of the component.
Design the behavior of the component.
Write the unit test to confirm the behavior of
the component.
Code the component so that all the tests will
pass.
Test the alternatives.
Refactor the code.
Write new test cases when something new
happens.
Return all tests when the code changes.
Writing Testable code:
Effective testing is to write code that is
structured in a way that makes it testable.
Things that make code testable are also the
things that make good object oriented code.
Modular methods and clearly defined object
roles make code much easier to test.
Best way to make sure that code is easily
testable is to write the test cases first.
Why Unit Test:
It is important in software process for various
reasons:
Writing unit tests before code gives you clarity
about the requirements of the object. Since you
define both the API of the object all the expected
behavior,your implementation is much easier.
Unit test document the requirements for an
object.
Since the requirements for the code are
documented in code as opposed to an elusive
Word or HTML document,the requirements stay
with the code
Unit tests give you a measurable confidence in
the quality of the code.At any time you can run
your suite of unit tests and get immediate
feedback on how much of your code meets
requirements.
Unit tests give you the freedom to learn from the
system.
Since now you have a suite of unit tests, you are
free to improve the code as you learn about the
application without having to worry about
breaking something.
A suite of comprehensive unit test makes it easy
for someone unfamiliar with the code to make
changes with confidence.
Unit tests are a great way to share knowledge
about the code in a way that is easy for
programmers to digest,as they are easier to read
and so it is easier to share code.
Unit Testing of Simple
Objects:
Two of the simple types of objects to test are
business objects and utility objects.
Utility objects carry out operations that re
largely independent of the system, normally low
level operations used by many objects.
A business object is a simple object whose main
purpose is to store some data and represent an
object in a system.
Unit Testing a Utility
Object
We have an application that retrieves data from a
database and displays onto a HTML page.The
data we retrieve from the database contains
greater than(>) and less than(<) symbols, which
can interface the display of the HTML page.To fix
this we need to write a utility class that replaces
every occurrence of “>” and “<” with “>” and
“<” respectively.
Package com.wrox.simple;
Import junit.framework;
public class HTMLScrubberTest extends TestCase{
public HTMLScrubberTest(String arg1) {
Super(arg1);
Public static void main (String[ ] args){
//invoke the run method of the textual test runner.
//pass into this method a Test created by the Suite()
method.Junit.text.ui.TestRunner.run(suite( ));
}
Public static Test suite() {
//construct a test suite using the .class property of the
TestCase
return new TestSuite(HTMLScrubberTest.class);
}
//…..
}
We will define the following test methods and add
them to the test case :
public void testAlreadyScrubbed( ) throws Exception{ }
public void testEmptyString( ) throws Exception{ }
public void testGreaterThanAndLessThanScrubing( )
throws Exception{ }
public void testGreaterThanScrubing( )throws Exception{ }
public void testLessThanScrubing( ) throws Exception{ }
public void testMultipleGreaterThanScrubing( )
throws Exception{ }
public void testMultipleLessThanScrubing( )
throws Exception{ }
Public void testNull( ) throws exception{ }
We need to compare the output of the scrub( ) method
and make sure that the less than sign is replaced
with <.our test looks like this:
Public void testLessThanScrubbing( ) Throws Exception{
//Construct an Instance of HTML Scrubber
HTMLScrubber scrub=new HTMLScrubber();
//Construct the string to pass into scrub
String before =“test < test”;
//Construct the string which is expected
String after =“test < test”;
/* asserting that after string should be equal to the results. */
assertEquals(“string should be equal ” , after ,
scrubber.scrub(before));
}
Package com.wrox.simple;
Public class HTMLScrubber {
Private static final char LESS_THAN=„<‟;
Private static final char GREATER_THAN=„>‟;
Private static final char LESS_THAN_SCRUB=„<‟;
Private static final char GREATER_THAN_SCRUB=„>‟;
Public HTMLScrubber( ) {
super( );
}
Public String scrub(String s){
StringBuffer buf=new StringBuffer();
For(int x=0; x< s.length(); x++)
{
char c=s.charAt(x);
if(c==LESS_THAN)
buf.append(LESS_THAN_SCRUB);
else(c==GREATER_THAN)
buf.append(GREATER_THAN_SCRUB);
else
buf.append(c );
}
}
Return buf.toString();
}
}
In the scrub() method we iterate through
each character and check if it is a greater
than or a less than sign,If it is we replace
with its equivalent.
Unit Testing a Business
object
A business object is one which usually have logic
in it.
Suppose as a part of our application we want to
create a User object.This object is responsible for
storing the user‟s name as well as a Vector of
Strings representing the id‟s.In addition, the user
object must be able to present the Vector of
Strings as one comma delimneted string.It must
also take in a string of this format and convert
into a vector.
package com.wrox.simple;
import junit.framework.*;
public class UserTest extends TestCase {
public UserTest(String arg1) {
super(arg1);
}
public static void main(String[ ] args) {
junit.text.ui.TestRunner.run(suite());
}
public static Test suite() {
return new TestSuite(UserTest.class);
}
//
}
Now that we know the basic format of the test
case, Let‟s think about what we need to test.We
want to make sure that when we pass in a
string its will be converted to a vector. Lets
define a test method to make sure that when
we pass in a string the same string comes out:
public void testStringPathInEqualsStringPathOut()
throws Exception {
User u = new User();
String in = "1,2,3,4,5,6,7";
u.setPathString(in);
assertEquals(in, u.getPathString());
}
Notice that in the this test,we create an instance
of user.we then pass a string in .The assumption
is that when we get the path string out via the
getPathString() method,it will be the same
regardless of the transformation it has gone
through.
Different Tests that the code need to pass are:
Public void testStringPathEmptyStringIn()
Throws Exception{
User u = new User();
u.setPathString("");
assertEquals("", u.getPathString( ) );
}
Public void testStringPathNullIn( ) throws Exception{
User u = new User();
u.setPathString(null);
assertEquals("", u.getPathString());
}
Package com.wrox.simple
Import java.util.*;
Public class User
Private String name ;
Private Vector path;
Public User(){
Super();
}
Public String getName( ){
return name;
}
Public Vector getPath( ){
return path;
}
Public void setName(String newName ){
Name= newName;
}
Public void setPath(Vector newPath ){
path= newPath;
}
Public String getPathString( ) {
Return null;
}
Public set void setPathString( ) { }
}
We Still need to give the method body for the
methods in the user class to run the tests.
Public String getPathString ( ) {
if(getPath( ) == null) {
return “ ”;
}
Public Void setPathString (String newPathString ) {
if(newPathString == null) {
setPath(null) ;
}
Unit Testing Servlets
By definition a servlet functions in a request/
response environment
Although some people advocate running the
servlet and writing HTML pages to test it, this
unnecessarily tests the development environment
and become complex.it becomes hard to isolate
the cause of the problem.
Servlets are not different from other components.
Rather than running the components in web
container where the request and response objects
are created for us,we create the objects for
ourselves and pass them into the service()
method.
The servlet gets the output stream from the
response object and write to it,If you want to
make sure that it is writing the appropriate
data,so that you could override the response to
provide on output stream that is stored in the
response object where we can examine in out
test method.
In this example we will write a servlet that takes
in one parameter ,called id which corresponds
to the id of a product we want to display.The
servlet will output the corresponding HTML
tags.Only id‟s 1,2 and 3 are valid.
We will create an instance of a request and a
response,these are the parameters passed to the
service( ) method.
package com.wrox.servlet;
import java.io.*;
import java.util.*;
import javax.servlet.*;
public class TestRequest implements ServletRequest {
HashMap paramMap = new HashMap( );
public TestRequest( ) {
super( );
}
public String getParameter(String key) {
return (String) paramMap.get(key);
}
public void setParameter(String key, String value) {
paramMap.put(key, value);
}
/* it has a lot of other methods which either returns null
or “0”. */
}
import java.io.*;
import java.util.*;
import javax.servlet.*;
public class TestResponse implements
ServletResponse {
TestWriter writer = new TestWriter();
public TestResponse() {
super();
}
public PrintWriter getWriter() throws IOException
{
return writer;
}
}
package com.wrox.servlet;
import java.io.*;
import javax.servlet.*;
public class TestWriter extends PrintWriter {
private String output=new String();
public TestWriter() {
/* We really want to have a default constructor for
TestWriter to make it easy to construct in the test case.
Unfortunately, the API dictates that PrintWriter's
constructer needs an OutputStream or Writer.
Fortunately, in a test case, we are not bound by the rules
that govern "real" IO. In order to get our default
constructor, we'll just fake out an OutputStream to
satisfy the constructor.This type of sneaky behavior can
be useful when you need a particular type of object to
satisfy typing requirements, but you want to circumvent
the API.
*/
super(new OutputStream( ) {
public void write(int b) throws IOException {
}
});
}
public String getOutput( ) {
return output;
}
public void println(String x) {
setOutput(getOutput( ) + x);
}
public void setOutput(String newOutput) {
output = newOutput;
}
}
Now that we have got the classes we need to test the
servlet,we can write the test case .There are three
basic cases to tests:
package com.wrox.servlet;
import junit.framework.*;
Public class DisplayProductInfoServletTest extends TestCase{
Public DisplayProductInfoServletTest(String arg1){
Super(arg1)
}
Public static void main(String args[ ]){
Junit.text.ui.TetRunner.run(suite( ));
}
Public static Test suite( ){
Return new TestSuite( DisplayProductInfoServletTest.class);
}
public void testInvalidId( ) Throws Exception{ }
public void testNoId( ) Throws Exception{ }
public void testValidId( ) Throws Exception{ }
}
Public void testInvalidId( ) throws Exception{
//create the request object to pass in
TestRequest req=new TestRequest();
//give the request a parameter called id with a value 7
req.setParameter(“id”,”7” );
//create the response object to pass in
TestResponce res=new TestResponce();
//create the servlet and call the service() method
DisplayProductInfoServletTest Servlet= new
DisplayProductInfoServletTest( );
Servlet.service(req,res);
//construct the expected output String
String expected =“<html><head><title>Invalid Product
</title></head>”=“<body>The product id is invalid </body>
</html>”;
assertEquals(expected,((TestWriter)res.getWriter()).getOutput()); }
Package com.wrox.servlet;
Import javax.servlet.*;
Import javax.servlet.http.*;
Import java.io.*;
Public class DisplayProductInfoServletTest extends
HttpServlet {
//calling the constructor of super class
Public DisplayProductInfoServletTest( ) {
Super();
}
Public void service(ServletRequest req, ServletResponce res);
throws ServletException,IOException{
}
}
Summary
Unit testing is a powerful tool for programmers
and can make your development faster, and of
higher quality.
The key is to focus on the objects itself rather
than the details of the implementation.
There are no hard and fast rules that dictate
unit testing must be done. Instead, there are
basic guidelines that make it more effective and
beneficial.
You will find challenges in testing the
components in your code that will require you
to use your imagination.
Thank you
Questions
References:
JUnit API
www.junit.org
Examples of JUnit
www.xprogramming.com/software.htm
Related docs
Other docs by gmp17018
Live Q A 2 From 11 17 06 09 47 AM To 11 17 06 12 14 PM Pacific From 11 17 06 11 47 AM To 11 17 06 02 14 PM C Amer From 11
Views: 17 | Downloads: 0
Get documents about "