Title: UNIT TESTING J2EE APPLICATIONS
1UNIT TESTING J2EE APPLICATIONS
- Presented by
- Sudheer Sabbineni.
2We 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.
3The 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.
4What 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.
5When 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.
6In 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.
7Essentially,a unit test is a piece of code thats
takes a predefined unit of code and manipulates
it. This Manipulation is a simulation of various
inputs to the unit. A unit tests 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
8What 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
9The tests that we write are related directly to
the methods of the class. there are some
guidelines to follow
- Dont 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
10Introduction 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 youre 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
11An 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.
12Using the JUint framework
The JUnit framework is a great framework for
writing unit tests. Lets look at an example of
how the JUnit framework might be applied to a
class.Lets 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.
13- 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.
14Within 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.
15Ex 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() assertNotN
ull(), assertNull().
16How 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.
17Steps 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.
18Writing 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.
19Why 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
20- 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.
21Unit 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.
22Unit 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(gt) and less than(lt) 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 gt and lt with
gt and lt respectively.
23- 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)
-
- //..
24- 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
25We 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 scrubnew
HTMLScrubber() //Construct the string to pass
into scrub String before test lt 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))
26Package com.wrox.simple Public class
HTMLScrubber Private static final char
LESS_THANlt Private static final char
GREATER_THANgt Private static final char
LESS_THAN_SCRUBlt Private static final
char GREATER_THAN_SCRUBgt Public
HTMLScrubber( ) super( ) Public
String scrub(String s) StringBuffer bufnew
StringBuffer() For(int x0 xlt s.length() x)
char cs.charAt(x)
27if(cLESS_THAN) buf.append(LESS_THAN_SCRU
B) else(cGREATER_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.
28Unit 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 users name as well as a Vector of
- Strings representing the ids.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.
29package 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.TestRunne
r.run(suite()) public static Test suite()
return new TestSuite(UserTest.class)
//
30Now that we know the basic format of the test
case, Lets 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())
31Notice 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())
32Package 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
33Public 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)
34Unit 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.
35- 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 ids 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.
36package 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. /
37import 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
38package com.wrox.servlet import
java.io. import javax.servlet. public class
TestWriter extends PrintWriter private String
outputnew 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. /
39super(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
40Now 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(Str
ing 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
41Public void testInvalidId( ) throws Exception
//create the request object to pass
in TestRequest reqnew TestRequest() //give the
request a parameter called id with a value
7 req.setParameter(id,7 ) //create the
response object to pass in TestResponce resnew
TestResponce() //create the servlet and call
the service() method DisplayProductInfoServletTest
Servlet new DisplayProductInfoServletTest(
) Servlet.service(req,res) //construct the
expected output String String expected
lthtmlgtltheadgtlttitlegtInvalid Product
lt/titlegtlt/headgtltbodygtThe product id is invalid
lt/bodygt lt/htmlgt assertEquals(expected,((TestWri
ter)res.getWriter()).getOutput())
42Package com.wrox.servlet Import
javax.servlet. Import javax.servlet.http. Impo
rt java.io. Public class DisplayProductInfoServ
letTest extends HttpServlet //calling the
constructor of super class Public
DisplayProductInfoServletTest( )
Super() Public void service(ServletRequest
req, ServletResponce res) throws
ServletException,IOException
43Summary
- 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.
44Thank you
45Questions
46References
- JUnit API
- www.junit.org
- Examples of JUnit
- www.xprogramming.com/software.htm