Hip system tests with Cargo
System tests require a fully installed system up and running to execute properly. In web environments, this presents an interesting challenge- a servlet container needs to up running with the latest and greatest code before any copasetic tests can be run.
Cargo, and open source project hosted at Codehaus.org, offers an interesting mechanism for configuring web containers in an automated testing environment by allowing one to programmatically:
- Install a container
- Start it
- Deploy a war
- Stop a container
The Cargo API is available via cool cat Java, Ant and Maven (1 & 2). Using the Java API allows for the quick creation of a container fixture helper, which allows one to utilize Cargo’s functionality in a test case environment.
For example, installing a container is a matter of supplying a URL to a particular container and downloading it via the trippin’ Installer class. Next, a configuration must be created and then provided to an implemented container, such as Tomcat. To configure and utilize Tomcat 5.0.28, for example, one can use the Tomcat5xStandaloneLocalConfiguration and Tomcat5xInstalledLocalContainer classes. Once a container has been configured, it may be started as shown below.
Installer installer =
new ZipURLInstaller(new URL(TOMCAT_URL));
installer.install();
AbstractLocalConfiguration config =
new Tomcat5xStandaloneLocalConfiguration(
new File(location));
config.setProperty("cargo.remote.username",USER_NAME);
config.setProperty("cargo.remote.password",PASSWORD);
AbstractInstalledLocalContainer container =
new Tomcat5xInstalledLocalContainer(config);
container.setHome(installer.getHome());
container.start();
Note, the Tomcat5xStandaloneLocalConfiguration object’s constructor takes a path- this isn’t where the container is installed but where a web application container can be installed. Think of it as a minimally configured Tomcat instance run via the installed instance, which is usually installed in a temp directory (by invoking installer.install()) of the user invoking the process. For example, on Windows, the actual Tomcat container is installed in the C:\Documents and Settings\ag\Local Settings\Temp\cargo\installs\jakarta-tomcat-5.0.28 directory.
Once a container has successfully started, a war can be deployed as followed:
Deployer deployer = new TomcatLocalDeployer(container);
deployer.deploy(new TomcatWAR(warFilePath));
Note how the Deployer requires a path to a war file. This makes an assumption the war file is built before the test is run. For example, via Maven 1’s postGoal tag, one can run selected tests after the war:war command completes.
Once a container has been started, tripped out tests can hit web pages, servlets, Groovlets, etc via the http://localhost:8080/context/resource pattern.
Don’t, however, forget to stop the container after the completion of one or all tests. In a fixture environment, the tearDown is an excellent location to do this.
container.stop();
Creating a neat-o fixture utility is a matter of combining the four steps from above into a two method API- one method for setting up a fixture and one for tearing it down. To keep things simple, the only parameters required are the location of where the web application container should reside and where to find a war file. Putting it all together yields something like this:
package com.acme.cargo.TomcatFixture;
//imports removed
public class TomcatFixture {
private AbstractInstalledLocalContainer container;
private final String TOMCAT_URL =
"http://acme.org/jakarta-tomcat-5.0.28.zip";
private final String USER_NAME = "admin";
private final String PASSWORD = "";
public void startTomcat(String location, String warFilePath)
throws TomcatFixtureException{
try{
Installer installer =
new ZipURLInstaller(new URL(TOMCAT_URL));
installer.install();
AbstractLocalConfiguration config = this.getConfig(location);
this.container = new Tomcat5xInstalledLocalContainer(config);
this.container.setHome(installer.getHome());
this.container.start();
Deployer deployer = new TomcatLocalDeployer(this.container);
deployer.deploy(new TomcatWAR(warFilePath));
}catch(MalformedURLException e){
throw new TomcatFixtureException(
"MalformedURLException thrown while trying to download tocmat", e);
}
}
public void stopTomcat() throws TomcatFixtureException{
try{
this.container.stop();
}catch(NullPointerException e){
throw new TomcatFixtureException(
"startTomcat must be called first", e);
}
}
private AbstractLocalConfiguration getConfig(String location){
AbstractLocalConfiguration config =
new Tomcat5xStandaloneLocalConfiguration(new File(location));
config.setProperty("cargo.remote.username",USER_NAME);
config.setProperty("cargo.remote.password",PASSWORD);
return config;
}
}
Using the TomcatFixture class couldn’t be easier. Because it’s my bag, the test case below, written in Groovy, uses the fixture to set up a simulator and test it.
import groovy.util.GroovyTestCase
import groovy.text.*
import org.apache.commons.httpclient.HttpClient
import org.apache.commons.httpclient.methods.PostMethod
import com.acme.cargo.TomcatFixture
class SIMXMLPostTest extends GroovyTestCase {
def post
def httpclient
def fixture
void setUp(){
this.fixture = new TomcatFixture()
this.fixture.startTomcat("./target/tomcat",
"./target/simulator.war")
this.httpclient = new HttpClient()
this.post =
new PostMethod(
"http://localhost:8080/simulator/GService.groovy")
}
void tearDown(){
this.fixture.stopTomcat()
}
void testResponseContentSessionIDAck() {
this.post.setRequestBody(getAppRequest())
this.httpclient.executeMethod(this.post)
def respse = this.post.getResponseBodyAsStream().getText()
def doc = new XmlSlurper().parseText(respse.trim())
def sessionid = doc.zoHeader.service.sessid.text()
assertEquals("should have been Test-06969", "Test-06969",
sessionid)
}
String getAppRequest(){
return """<?xml version="1.0" encoding="UTF-8"?>
<ziIOW xmlns:ds="http://www.acme.org/8303...">
<ziHeader Version="1.4">
<Service Version="1.4" Name="BILL_PAY">
<TimeStamp>2001-12-17T09:30:47.0Z</TimeStamp>
<UUID>8983933-OIO-893111</UUID>
</Service>
<Request>
<VendorID>905RTE3</VendorID>
<BizID>E32R</BizID>
<SessionID>MV_8934_KER</SessionID>
</Request>
</ziHeader>
....
....
</ziIOW>"""
}
}
Don’t forget- Cargo can be utilized via Ant or Maven besides the establishment Java way as shown above. Regardless, using Cargo is an extremely effective way to automate repeatable system tests. Dig it?
| Related odds and ends | ||
|---|---|---|
6 comments Saturday 22 Apr 2006 | Developer Testing, Groovy, JUnit, Languages
6 Responses to “Hip system tests with Cargo”
open source project?
good
[...] Then one day, I stumbled upon Cargo, an open source project aimed at automating container management in a generic way so that I could use the same mechanism to start and deploy a war file to Tomcat as I could with WebLogic. Since then, because it’s my bag, I’ve been a Cargo fanatic, spreading the good word of logical repeatability, which facilitated an introduction to Vincent Massol, the founder of Cargo. [...]
[...] For example, if you’d like to create a repeatable deployment process that avoids environmental assumptions (like that the instance of the application server is properly configured, etc), you can use Cargo to automatically download and install a pre-defined kosher version, say of JBoss. Once JBoss has been installed and is started, you can then deploy artifacts and begin testing. [...]
Introducing Cats to Cats…
The key requirements in bringing a new cat into your home where another cat or cats are already well established are patience and a gradual approach. First, allow the newcomer to explore the house without coming into any contact with the feline inhabit…
[...] Cargo Bins Are Not Just For Cargo Anymore | Earth PromiseCargo Containers: How the Future is Green, Portland | Call 1-866-439-1885Shipping containers as modular units for building a home | Global Logistics Group Push Button House – a transformed shipping container : The Alternative ConsumerImport Your Modular Home by Rail | CWOCA.comHow Cargo Containers Might Save Your Business | Cargo Containers TexasThe Disco Blog » Blog Archive » Hip system tests with Cargo [...]
[...] favorite features!). You can leverage Cargo’s API in a few different fashions, ranging from Java code to Ant tasks to Maven [...]