UNIT TESTING J2EE APPLICATIONS

Document Sample
UNIT TESTING J2EE APPLICATIONS Powered By Docstoc
					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 “&gt;” and
“&lt;” 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 &lt;.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 &lt; 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=„&lt;‟;
 Private   static   final   char   GREATER_THAN_SCRUB=„&gt;‟;

 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