Breaking News
Home / ServerSide / Automated Functional Testing

Automated Functional Testing

Testing BEA Portal Applications: Open-Source Automated Unit and Functional Testing
By Mario Ciabarra
Abstract
Testing is often a last-thought, last-minute process at the end of a project life-cycle. However, designing tests first, and automating them will leave your code bug free, and your boss smiling.

I want this functionality done by Monday.Unfortunately, Monday (formerly PwC Consulting) was bought out by IBM Global Services. So, the Monday isn’t who’s doing it.. it’s when the code is due! Faced with that deadline, the first thing a developer has in mind is getting code done as quickly as possible. What they might miss, however, is that the most effective task they could do first is creating a test plan. Even better, an automated one.

Often with a rapidly approaching deadline, developers are very focused on delivering specific pieces of functionality. As such, the greater picture is sometimes lost. Developing a test plan before coding helps lay out complete functionality needs and system responses to the designated requirements. Creating automated test plans offer an even greater pay back: they not only offer the benefit of helping a developer think through the design, but also ensure that each build has working code. With automated testing in place, developers can focus on developing individual components, ensuring they meet the test parameters, and ultimately integrate these classes to meet the functional requirements. As a developer thinks through application design via an upfront test plan design, the developer will have a head start on meeting the code deadline.

Automated testing offers a number of advantages to manual, repetitive testing. Not only do automated test plans help test new requirements, they also help ensure old ones continue to be met. Manual testing is tedious, and many mistakes are made as testers re-run the same scripts over and over. Automated testing frees up resources, allowing testers to ensure new functionality matches its specifications, while allowing developers the freedom to continue product enhancements. As new releases bring new functionality and new developers, previous code implementation design may have been forgotten/lost. Automated testing ensures that previous functionality continues to work, despite code changes, allowing for a robust, rapid response environment.

Many developers are unsure of the test phases and their purposes, as there several stages of testing. Listed below are typical stages that many software development firms follow:
Test Stage Name What does it Mean
Unit – Testing individual methods/classes.

  • System – Testing group of classes which interface with a particular system (usually with the system stubbed out).
  • Integration (End-To-End) – Testing system integration, ensuring data integrity and expected responses between systems.
  • Functional – Testing that an application meets all functional specifications given, including positive and negative cases.
  • Load – Testing systems to ensure they can handle expected volumes while still meeting response times.
  • Stress – Testing systems to see where their limits are and identify bottlenecks.
  • User Acceptance Testing (UAT) – Final testing by the business user community.

The foundation of each stage is based on two components, performing an action or actions and assertion of the result. With this simplistic approach, automated tests can be used to run an action and evaluate the systems response.

Unit Testing
Automated Unit Testing
Methods (public) are to be concise, decoupled working blocks for effective programming. As such, public methods can be tested to ensure that they process (and sometimes return) correctly. Unit tests ensure the behavior of these components are correct prior to system integration, both with correct and incorrect/invalid inputs. During the lifecycle of classes, methods are added, changed, renamed, and removed constantly. At the end of the day, regardless of functional changes, new requirements, etc, these classes and methods should continue to function. Automated Unit Testing can ensure this component functionality without tedious/repetitive testing! Quite often, developer’s changes to add new functionality causes errors to show up in previous code! With automated testing in place, if a specific development efforts missed the big picture, developers will know quickly, as the automated tests can run with nightly builds. Managing additions and changes now becomes much clearer and easier.

Automated Open-Source Unit Testing Software
The most widely used Java unit testing software is JUnit (http://jakarta.apache.org/junit), an open-source package from the Apache Jakarta project (http://jakarta.apache.org). Because of its simplicity and popularity, IDE’s, such as Borland JBuilder, have integrated JUnit into their IDE. JUnit is a foundation for unit testing Java software. It provides a framework for common functions required for unit testing such as asserting results, gathering success and failures from multiple tests, and reporting mechanism. JUnit is designed to test individual pieces of code, i.e., specific methods, and assert their expected results.

One limitation of JUnit is that it cannot test server-side java code (backend components in a J2EE container, i.e. EJBs, Tag Libs, Filters, etc.). Jakarta Cactus (http://jakarta.apache.org/cactus/) was developed to solve this challenge. Cactus is built on top up JUnit, and provides functionality to test in-container objects.

HttpUnit (http://jakarta.apache.org/httpunit/) is another example of a package built on top of JUnit, which provides an API to handle web conversations (stateful information such as cookies).

Like Cactus and HttpUnit, there are many other unit testing packages which are built on top of JUnit, as it provides a fertile infrastructure to create and run automated unit testing for java software. Examples can be found in the Jakarta project, as well as http://opensource.sourceforge.net.

To demonstrate its simplicity, sample JUnit and Cactus tests are included below.

Functional Testing
Automated Functional Testing
After creating Unit tests for code, a developer will note that just because methods respond correctly to unit tests, tying everything in with a web application is another story. Automated web site testing is another step toward a positive development experience, to ensure the site behaves correctly, and have it continue that way with each build.

Automated Open-Source Functional Testing Software
While HttpUnit/Cactus/JUnit offer the API’s for this testing, testing all positive and negative test cases and validations would require hundreds of tests. Building hundreds of java test classes is not a viable solution. Additionally, developers can’t be tied up in creating hundreds of these tests, as they’re the ones implementing the code! What’s needed is a highly configurable tool, that’s simple enough for non-java developers to use. One solution is to use Apache JMeter which offers an xml-based testing tool. While designed more for load/stress testing, JMeter can be integrated with JUnit to offer a simple, xml-based automated functional testing tool.

JMeter offers a GUI, where testers can easily put together HTTP, FTP, and JDBC requests, while also defining assertions for the server responses.

Below is a picture of the JMeter GUI

Figure 2 JMeter GUI

Testers can use the GUI or create the test cases via xml. JMeter also provides a simple non-GUI interface to execute JMeter tests.

To demonstrate the simplicity in using JMeter XML, an xml example of a JMeter test is below:
<HttpTestSample type=”org.apache.jmeter.protocol.http.control.HttpTestSample” name=”Login_SuccessfulTest” getImages=”false”>
<defaultUrl>
<ConfigElement type=”org.apache.jmeter.protocol.http.config.MultipartUrlConfig”>
<property name=”port”>443</property>
<property name=”PROTOCOL”>https</property>
<property name=”arguments”>
<Arguments>
<argument name=”userName”> test </argument>
<argument name=”password”>testpass</argument>
</Arguments>
</property>
<property name=”path”>/login.jsp</property>
<property name=”method”>POST</property>
</ConfigElement>
</defaultUrl>
<configElements />
<controllers />
<assertion name=”Assertion” class=”org.apache.jmeter.assertions.Assertion” testType=”2″ testField=”sampler.RESPONSE”>
<testString>Welcome Back, Mario</testString>
</assertion>
</HttpTestSample>

Figure 1: JMeter XML Test Definition Example
Note from the example above how simple it is to modify the URL or parameters. Additionally, each page can be saved as an xml, and reused, as you string together an example test case. This allows for easy testing of hundreds of variations of test data, testing your positive and multiple negative test cases: A quick and efficient way to ensure a site works after code change.

Load Testing
Automated Load Testing
Developers’ main goal is usually to get code to simple work. Without the oversight and availability of competent architects, it’s very easy to code without regard for CPU and memory resources. While the code works today, tomorrow as customer usage increases, the system may not function properly. Load testing is an excellent discovery tool for memory leaks and thread safety.

During an enterprise implementation, architects will typically analyze current and previous loads, as well as forecast future load based upon project customer base changes. With these statistics, a load test is put into place, to ensure that the system can handle the expected usage on the system. Typically, load testing is meant to ensure that the same expected results which were delivered in functional testing, remains true when the system is under load.

Automated Open-Source Load Testing Software
The same tool used for automated functional testing is a great choice for load testing, as the scripts have already been written. The only component missing is simulating multiple users at the same time. JMeter allows you to specify the number of concurrent threads which are making requests. JMeter also provides throughput analysis components which display statistical throughput performance measures. For load testing web applications, one useful parameter which can easily be added to JMeter (as it’s open-source), is to specify a wait parameter, to simulate how users interact with the system.

Stress Testing
Automated Stress Testing
Automated Stress testing is very similar to Load Testing. The main difference is that Stress Testing is used to define the maximum capacity of a system or systems. It’s an excellent tool to understand the system limits and identify system bottlenecks.
Automated Open-Source Stress Testing Software
Once again, JMeter is an excellent choice for Stress Testing, as the scripts have already been written. Simply continue to increase the number of threads for your test cases, until your server becomes backlogged. You can then determine how many concurrent requests your system can handle.

Peace of Mind
Regression Testing Late Code Changes
Often, last minute code changes impact functionality which has already been tested by a test or quality assurance department. Too often, this functionality isn�t re-tested, leading to production bugs. Automated testing after each build gives the IT department peace of mine, that a developer did not overlook core functionality, or a tester skip a test.

Server Deployment
As servers are taken into and out of clusters, for maintenance or releases, a QA department typically runs a quick test to ensure the server is functionally responding as expected. This can be tedious with a large production environment. The same automated functional checks that test your site can also serve as a sanity check when releasing servers in production. You can run the non-GUI JMeter version from a servlet, reusing your functional testing scripts to ensure a successful deployment/startup.

At the end the day, regardless of the architects, software used, or language, there will be bugs. The smarter IT shops learn from their mistakes, creating new automated tests for each bug found, ensuring no bug will be found twice!

Sample JUnit Test

package util.tests;

import java.io.InputStream;
import java.io.StringWriter;
import java.io.IOException;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import junit.framework.TestResult;

import log4j.*;

/**
* Class StringUtilTest
*/
public class StringUtilTest extends TestCase
{
private Category _log = new Category(StringUtilTest.class);

/**
* Constructor StringUtilTest
* @param name
*/
public StringUtilTest(String name)
{
super(name);
}

/**
* Method main
* @param args
*/
public static final void main(String[] args)
{

if ((args.length == 1) && args[0].equals(“-gui”))
{
junit.swingui.TestRunner.run(StringUtilTest.class);
}
else
{
junit.textui.TestRunner.run(suite());
}
}

/**
* Method suite
* @return
*/
public static Test suite()
{
return new TestSuite(StringUtilTest.class);
}

/**
* Method testBasic
*/
public void testBasic()
{
String testString = “The apostraphes will be ‘replaced'”);
String resultString = StringUtil.replaceString(testString, “‘”);
if (resultString.indexOf(“‘”) >= 0)
{
fail(“”‘” was not replaced using StringUtil.replaceString.”);
}
}

/**
* Method setUp
*/
protected void setUp()
{

_log.debug(“in setUp()”);
}

/**
* Method tearDown
*/
protected void tearDown()
{
_log.debug(“in tearDown()”);
}
}

Sample Cactus/JUnit Test

package account.ejb.tests;

import java.util.Date;
import javax.naming.NamingException;
import javax.ejb.CreateException;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import junit.framework.TestResult;

import org.apache.cactus.ServletTestCase;
import org.apache.cactus.WebRequest;
import org.apache.cactus.WebResponse;
import log4j.*;

/**
* Class accountEJBCTest
*
* @author
* @version 1.0
*/
public class accountEJBCTest extends ServletTestCase
{

private static Category __log = new Category(accountEJBCTest.class);
private static accountLocalHome __accountHome = null;
private String _idnum = “testUser”;

/**
* Constructor accountEJBCTest
* @param name
*/
public accountEJBTest(String name)
{
super(name);
}

/**
* Method main
* @param args
*/
public static final void main(String[] args)
{
if (args.length != 0)
{
if (args[0].equals(“-gui”))
{
junit.swingui.TestRunner
.run(accountEJBTest.class);
}
else if (args[0].equals(“-test”))
{
if (args[1] != null)
{
TestSuite suite = new TestSuite();

suite.addTest(
new accountEJBTest(args[1]));
junit.textui.TestRunner.run(suite);
}
else
{
System.out.println(
“Usage: accountEJBTest -test “);
}
}
}
else
{
junit.textui.TestRunner.run(suite());
}
}

/**
* Method suite
* @return
*/
public static Test suite()
{
return new TestSuite(accountEJBTest.class);
}

/**
* Method beginBasic
* @param request
*/
public void beginBasic(WebRequest request)
{
__log.debug(“- Begin Test Basic-++”);
}

/**
* Method testBasic
*/
public void testBasic()
{

__log.debug(“-++Starting Test Basic-++”);

accountLocal account = null;
accountDTO accountDTO = null;

try
{
__log.debug(“creating account home…”);
account = __accountHome.create();
}
catch (CreateException ce)
{
fail(“unable to create account local: ” + ce.getMessage());
}

try
{
__log.debug(“finding account by ID ” + _id + “…”);
accountDTO = account.findByUserID(_id);
}
catch (accountException pfe)
{
fail(“error in findByESN(): ” + pfe.getMessage());
}

__log.debug(“accountDTO = ” + accountDTO);

try
{
accountDTO = account.suspend(accountDTO);
}
catch (accountException pfe)
{
fail(“error in suspend: ” + pfe.getMessage());
}
assertEquals(“account status not SUSPENDED”, accountDTO.getStatus(), accountStatus.SUSPENDED);

__log.debug(“accountDTO = ” + accountDTO);

__log.debug(“-++Ending Test Basic-++”);
}

/**
* Method endBasic
* @param response
*/
public void endBasic(WebResponse response)
{
__log.debug(“-++End Test Basic-++”);
}

/**
* Method setUp
*/
protected void setUp()
{
if (__accountHome == null)
{
try
{
__accountHome = accountUtil.getLocalHome();
}
catch (NamingException ne)
{
throw new RuntimeException(“unable to initialize account local home:” + ne.getMessage());
}
}

__log.debug(“in setUp()”);
}

/**
* Method tearDown
*/
protected void tearDown()
{
__log.debug(“in tearDown()”);
}
}

[pb_builder]

Check Also

What webservices standards are supported by Siebel Business Applications?

The following Web services standards are supported by Siebel Business Applications:     * Web Services …

Advertisment ad adsense adlogger