JUnit
Archived Posts from this Category
Archived Posts from this Category
TestNG’s flexible fixtures, parametric testing, and hip grouping facilities make higher level testing a breeze, yet, sometimes I find myself still writing basic unit tests with JUnit (old habits never die, I suppose). But, as I’ve stated before, there’s nothing wrong with using the two smokin’ frameworks in concert– in fact, many code bases already have an extensive collection of JUnit tests; consequently, TestNG can run JUnit tests.
Using TestNG’s testng.xml suite file, you can specify a collection of JUnit tests by creating a new test entry and setting the junit attribute to true. For example, the following suite file runs a series of TestNG tests as well as all the JUnit tests found in the test.com.acme.pdp and test.com.acme.pdp.gsap packages.
<!DOCTYPE suite SYSTEM "http://beust.com/testng/testng-1.0.dtd">
<suite name="all unit tests suite">
<test name="all unit tests">
<groups>
<run>
<include name="unit"/>
</run>
</groups>
<packages>
<package name="test.com.acme.pdp.ng"/>
</packages>
</test>
<test name="junits" junit="true">
<packages>
<package name="test.com.acme.pdp"/>
<package name="test.com.acme.pdp.gsap"/>
</packages>
</test>
</suite>
As you can see, this suite file defines a group of TestNG tests that focus on unit tests and another group of JUnit tests found in two different packages.
TestNG isn’t an all-or-nothing choice when it comes to using a testing framework. If you already have an existing suite of copasetic JUnit tests, you can still run them via an Ant task; however, running them via TestNG provides one single report for test results.
2 comments Wednesday 04 Oct 2006 | Andy | Developer Testing, JUnit, TestNG
I tend to categorize Afferent and Efferent coupling as Maintenance metrics, meaning that these two copasetic metrics, in collaboration with Instability, Abstractness and coverage facilitate understanding how change will affect aspects of an architecture. One thing about metrics, though, is that they are only marginally useful as one time measurements. Real value comes from watching metrics over time and noticing trends. Once a baseline has been established (say for code coverage), then you can set goals and work to achieve them (like ensuring coverage doesn’t precipitously drop).
JDepend, a hip Java framework for determining Maintenance metrics, offers an interesting API that allows for proactive monitoring of its reported metrics. For example, imagine there is a particular package within an architecture that has become somewhat of maintenance issue due to its high responsibly. Because it has become heavily relied on (more so than originally intended), changes to classes within this package create a ripple effect throughout those classes which import it. By combining JDepend with JUnit (or even TestNG), a proactive monitor can be put into place that fails a test case should the Afferent coupling of a high risk package grow beyond a desired threshold.
Using JDepend’s smokin’ API is simple– just point JDepend at a project’s binaries and invoke the analyze method and voila– every metric gathered by JDepend is available for all analyzed packages. For example, becuase it’s my bag, the test case below analyzes a code base and asserts a bound for a particular metric.
package test.org.acme.bcg.metrics;
import jdepend.framework.JDepend;
import jdepend.framework.JavaPackage;
import junit.framework.TestCase;
public class AfferentCouplingTest extends TestCase {
private JDepend analyzer;
protected void setUp() throws Exception {
this.analyzer = new JDepend();
this.analyzer.addDirectory("./target/classes");
this.analyzer.addDirectory("./target/lib");
this.analyzer.analyze();
}
public void testAfferentness() throws Exception{
JavaPackage pck =
this.analyzer.getPackage("org.acme.bcg.impl.spring");
int afferentValue = pck.afferentCoupling();
assertTrue("package's afferent coupling has increased to "
+ afferentValue, afferentValue <= 27);
}
}
As you can see, the testAfferentness method ensures that if org.acme.bcg.impl.spring’s Afferent coupling grows beyond 27 the test case will fail.
Of course, this is a canary in a coal mine strategy, man– with this test case in place and your disco desire to limit the Afferent coupling of this package, it may be an opportune time to begin evaluating how to properly refactor the package so as to limit Afferent-ness. Dig it?
2 comments Friday 22 Sep 2006 | Andy | Code Metrics, JUnit
With its hip annotations and free-wheeling syntax, JUnit 4 has embraced some of the best features of TestNG, but does that mean it’s rendered TestNG obsolete like shiny clinging Lycra stretch disco pants and copasetic disco moves? Obviously, the answer is no because:
IBM devWork’s JUnit 4 vs. TestNG considers what’s unique about each framework and discusses three high-level features you’ll still find only in TestNG. Dig it?
0 comments Friday 01 Sep 2006 | Andy | Articles, Developer Testing, JUnit, TestNG
Verifying application performance is almost always a secondary concern during application development. Mind you, I’m stressing the verification of application performance, man. An application’s performance is always a chief concern from day one, but rarely is it verified until much, much later.
There are a number of copasetic reasons why performance testing is put off until it later cycles; however, in my experience, it seems most businesses don’t truly take application performance testing seriously because they don’t know what to expect. Of course, numbers are thrown out in the beginning stages; however, reality is almost always different– either the application performs much lower than expected or things take off like wild fire.
Performance testing usually becomes a primary concern once two square things happen:
There is an easy way; however, to ascertain basic low level performance numbers using existing JUnit assets. Via the JUnitPerf framework, existing JUnit tests can be quickly turned into simple load tests and even stress tests.
JUnitPerf can create two types of hip tests using the decorator pattern– TimedTests and LoadTests using JUnit’s suite mechanism. TimedTests create a top level bound for a test case– if this time is surpassed then the test fails. LoadTests work in cooperation with timers and create an artificial load on a particular test case by running it a desired amount of times separated by the configured timer.
For example, the TimedTest below will run the testToXML test case once and if this test case takes longer than 170 milliseconds the test case will fail.
public static Test suite() {
long maxElapsedTime = 170; //170 milliseconds
Test testCase = new BatchDepXMLReportPerfTest("testToXML");
//passing false to this constructor would fail the
//test immediately if test exceeded 170ms
//otherwise this test finishes and is failed if > 170ms
Test timedTest = new TimedTest(testCase, maxElapsedTime);
return timedTest;
}
In the suite method below, a LoadTest is defined, which will run the testFindVerifyDefinition test case 10 times, each thread launching every 100 milliseconds.
public static Test suite() {
int users = 10;
Timer timer = new ConstantTimer(100);
return new LoadTest(
new WordDAOImplLoadTest("testFindVerifyDefinition"),
users, timer);
}
Using this keen framework, basic performance measures can be put into place, which can give a baseline breaking limit on low level application code, such as:
executeTrade method to completePlus, this framework can reuse your existing JUnit tests that already verify the executeTrade method! What a trip!
4 comments Sunday 27 Aug 2006 | Andy | Developer Testing, JUnit
As I’ve mentioned before, JUnit tests written in Groovy (against a Java application) are sometimes easier to write than in plain-Jane Java because of Groovy’s relaxed syntax. And fewer imports, fewer type declarations, and no semi-colons are just the tip of the iceberg too, man.
Running Groovy JUnit tests through an existing build process managed by Ant or Maven is simple too- especially when a project already has existing hip Java JUnit tests. Ideally, in this scenario, the difference between a Java test and a Groovy one should be seamless- having two different tasks that run each platform’s tests seems like overkill- why not run the Groovy ones with the Java ones?
Groovy bundles a TestSuite type dubbed AllTestSuite, which facilitates running Groovy JUnit scripts from within an IDE and of course, a build process that already runs normal Java JUnit tests. The copasetic class works by looking for System properties which delineate where Groovy tests reside and a naming pattern (such as tests/groovy and **/*Test.groovy).
What I find most effective; however, is to create my own dynomite TestSuite type, set the System properties in a static block and then override the suite method and call AllTestSuite’s suite like so:
package test.com.acme.sda;
import groovy.util.AllTestSuite;
import junit.framework.Test;
import junit.framework.TestSuite;
public class AllGroovySuite extends TestSuite {
static {
System.setProperty(AllTestSuite.SYSPROP_TEST_DIR, "./test/groovy");
System.setProperty(AllTestSuite.SYSPROP_TEST_PATTERN, "**/*Test.groovy");
}
public static void main(String[] args) {
junit.textui.TestRunner.run(AllTestSuite.suite());
}
public static Test suite() {
return AllTestSuite.suite();
}
}
Note how AllGroovySuite is written in normal Java and provides values for Groovy’s AllTestSuite’s SYSPROP_TEST_DIR and SYSPROP_TEST_PATTERN. When this class is run via a JUnit runner, the SYSPROP_TEST_DIR directory is scanned and any file matching the SYSPROP_TEST_PATTERN pattern is loaded by AllTestSuite and run.
By adopting this technique, I can run Groovy test scripts in an IDE, like Eclipse (and of course, see the green bar); furthermore, existing test tasks in Ant or goals in Maven can pick this class up and run it (which then runs all Groovy tests). Pretty groovy, eh?
1 comment Sunday 06 Aug 2006 | Andy | Developer Testing, Dynamic Languages, Groovy, JUnit
If you:
then you’ll have a hip time listening to these two podcasts:
In the Age of Aquarius disco never dies man. Dig it?
2 comments Tuesday 01 Aug 2006 | Andy | Continuous Integration, Developer Testing, JUnit, NUnit, TestNG
Believe it or not, there are numerous Struts applications alive today. They may not be the hippest things going, but they have business value so they’re in no hurry to go anywhere, at least until the cost to maintain them supersedes the cost to rewrite them. Until that point, it makes copasetic sense then to roll up your sleeves and test those applications so as to reduce the risk of introducing defects as modifications are made, right?
“Testing Struts legacy apps” is the latest article in IBM developerWork’s series “In pursuit of code quality”, which focuses on using the StrutsTestCase framework, in concert with DbUnit, to facilitate testing those omniscient Struts Action classes. As always, feel free to let it all hang out at the “Improve Your Java Code Quality” forum!
For additional resources on testing Struts applications see:
For additional resources on using DbUnit see:
0 comments Monday 31 Jul 2006 | Andy | Articles, Developer Testing, JUnit
Answering the question: “how is data stored in a copasetic database after an application processes it?” usually involves some sort of comparison testing. Using a known dataset, the database is queried and the results compared- if there is a difference, then one can infer that the application layer is some how doing something wrong.
Because it’s my bag, I’ve found that DbUnit’s Query API is quite handy for this sort of purpose. Even though employing this functionality does require some additional XML files– the maintenance cost occurs, in large part, up front. Once the files are in place, it’s smooth sailing (until the database structure changes, man!). If you are new to DbUnit, I recommend reading “Effective Unit Testing with DbUnit” before reading further.
As an example, I’ll use my favorite tripped out database model- three highly complicated tables relating to a dictionary.

Sitting on top of the database is a Hibernate and Spring driven application, which facilities creating, reading, updating and deleting words and their associated definitions.
I’d like to verify that if I attempt to create the noun “acedia” with the definition of “apathy, boredom” the word table has a new row with SPELLING set to acedia and PART_OF_SPEECH set to Noun. Moreover, a related definition row has its DEFINITION column set to apathy, boredom. Note- I don’t care about primary keys, which are application specific (i.e. Hibernate controls them). If there were dates associated with the rows too (such as create dates or modification times) I wouldn’t necessarily care about them either.
I’ll use the following hip XML file as my comparison:
<?xml version='1.0' encoding='UTF-8'?>
<dataset>
<word SPELLING="acedia" PART_OF_SPEECH="Noun"/>
<definition DEFINITION="apathy, boredom"/>
</dataset>
Using the Query API is fairly simple- DbUnit’s IDatabaseConnection interface has a createQueryTable method which takes two parameters- a query name and a query String. The query String is normal SQL; hence, you can easily filter out unneeded values. The result is an ITable type, which then can be compared against data from the above XML.
This XML file from above contains data for two tables- word and definition. DbUnit treats a whole hip file as an IDataSet; consequently, it’s possible to ask an IDataSet for a subset of data as type ITable as I’ve done below.
IDataSet expectedDataSet =
new FlatXmlDataSet(new File("test/conf/expect-words-2.xml"));
ITable defTable = expectedDataSet.getTable("DEFINITION");
Putting it all together, I have the following boss test scenario:
public void testCreate() throws Exception{
IWord word = new Word();
word.setSpelling("acedia");
word.setPartOfSpeech(PartOfSpeechEnum.NOUN.getPartOfSpeech());
Set definitions = this.getDefinitionsForWord(word);
word.setDefinitions(definitions);
try{
this.dao.createWord(word);
}catch(CreateException e){
TestCase.fail("CreateException thrown: testCreate");
}
IDataSet expectedDataSet = new FlatXmlDataSet(
new File("test/conf/expect-words-2.xml"));
validateWordTable(expectedDataSet);
validateDefinitionTable(expectedDataSet);
}
After the try/catch an IDataSet is retrieved, which will serve as the comparison to live data. With an IDataSet instance, individual table values are checked, in both the validateWordTable and validateDefinitionTable methods shown below:
private void validateDefinitionTable(IDataSet expectedDataSet)
throws DataSetException, SQLException, Exception, DatabaseUnitException {
ITable defJoinData = this.getConnection().
createQueryTable("TestResult",
"SELECT DEFINITION.DEFINITION FROM DEFINITION, WORD " +
"WHERE WORD.SPELLING="acedia" and WORD.WORD_ID = DEFINITION.WORD_ID");
ITable defTable = expectedDataSet.getTable("DEFINITION");
Assertion.assertEquals(defJoinData, defTable);
}
private void validateWordTable(IDataSet expectedDataSet)
throws DataSetException, SQLException, Exception, DatabaseUnitException {
ITable actualJoinData = this.getConnection().
createQueryTable("TestResult",
"SELECT WORD.SPELLING, WORD.PART_OF_SPEECH FROM WORD " +
"WHERE WORD.SPELLING="acedia"");
ITable actualTable = expectedDataSet.getTable("WORD");
Assertion.assertEquals(actualJoinData, actualTable);
}
Note how specific database queries are issued (in the form of normal SQL) which filter out primary keys and join two tables using the data assumed to already exist due to the test getting to this point (i.e. acedia is assumed to be in the database at this point). The Assertion class is part of DbUnit and facilitates comparing ITable instances.
Comparison testing with DbUnit is fairly easy and clearly handy in its ability to integrate easily with testing frameworks like JUnit and TestNG and hence remain repeatable and automated. Dig it?
1 comment Friday 21 Jul 2006 | Andy | Developer Testing, JUnit
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:
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?
4 comments Saturday 22 Apr 2006 | Andy | Developer Testing, Dynamic Languages, Groovy, JUnit
Most hip JUnit extension frameworks integrate easily with Groovy. For example, one can easily employ XMLUnit, DbUnit, and jWebUnit via JUnit tests written in Groovy as these frameworks expose an API that facilitates delegation. Decorator based frameworks, however, are slightly more challenging to utilize within Groovy.
JUnitPerf is an extension framework for JUnit that offers the neat-o ability to ascertain fine grained performance and scalability (i.e. at a method level). For instance, JUnitPerf enables scenarios such as “the findUsers method must return a collection of User objects within one second or the test fails (even if the test did return a valid collection of User objects).” The framework also adds scalability via threading. Using the above scenario, one can add the trippin’ requirement that under a load of 100 invocations, the findUsers method must return a collection of User objects within one second.
Understandably, there are scenarios within Groovy where this type of framework could come in quite handy:
But, because JUnitPerf is a decorator based framework that requires test cases define a suite method, integration with Groovy can cause some misleading results. Groovy’s available test runners, GroovyTestSuite and AllTestSuite create suite methods themselves, which appears to override individually defined suite methods within Groovy test cases. Therefore, when running a test case, written in Groovy, that contains a suite method it appears the method is ignored. This means that test cases themselves are run; however, they are not decorated.
To solve this issue and successfully run a test case written in Groovy, which contains a suite method, there are two steps that must be followed:
String and have that constructor call super(yourString)
For example, the following smokin’ test case, written in Groovy, utilizes JUnitPerf via a suite method to verify that invoking testOr 20 times (each thread staggered by 100 milliseconds) returns within 2300 milliseconds.
package test.com.acme.seda.impl.perf
import junit.framework.TestCase
import com.acme.seda.impl.RegexPackageFilter
import junit.framework.Test
import junit.textui.TestRunner
import com.clarkware.junitperf.ConstantTimer
import com.clarkware.junitperf.LoadTest
import com.clarkware.junitperf.TimedTest
import com.clarkware.junitperf.Timer
class RegexFilterPerfGTest extends TestCase {
RegexFilterPerfGTest(test){
super(test)
}
void testOr() {
def filr = new RegexPackageFilter("java|org")
assertTrue("value should be true",
filr.applyFilter("org.sf.String"))
}
static void main(String[] args) {
TestRunner.run(RegexFilterPerfGTest.suite())
}
static Test suite() {
def testCase = new RegexFilterPerfGTest("testOr")
//20 users for load staggered at 100 ms
def loadTest = new LoadTest(testCase, 20,
new ConstantTimer(100))
//each thread must return within 2300 ms
return new TimedTest(loadTest, 2300)
}
}
Running this test requires it first be complied into Java byte code and invoked via JUnit, which can be done quite easily with the Maven Groovy Test plug-in. By typing the groovytest:test command, the plug-in will compile any Groovy tests into byte code and then invoke the test:test command, which internally invokes the venerable junit Ant task.
For instance, below is the output from running the groovytest:test command in Maven.
test:test:
[junit] Running test.com.acme.seda.frmwrk.\
filter.impl.ClassInclusionFilterTest
[junit] Tests run: 3, Failures: 0, Errors: 0, \
Time elapsed: 0 sec
[junit] Running test.com.acme.seda.frmwrk.\
filter.impl.misc.ConcurrentFilteringTest
[junit] Tests run: 10, Failures: 0, Errors: 0, \
Time elapsed: 0.031 sec
[junit] Running test.com.acme.seda.frmwrk.\
filter.impl.perf.RegexFilterPerfGTest
TimedTest (WAITING): LoadTest (NON-ATOMIC): \
ThreadedTest: testOr(test.com.acme.seda.\
frmwrk.filter.impl.perf.RegexFilterPerfGTest): \
2015 ms
[junit] Tests run: 20, Failures: 0, Errors: 0, \
Time elapsed: 2.031 sec
[junit] Running test.com.acme.seda.frmwrk.\
filter.impl.SimpleFilterTest
[junit] Tests run: 1, Failures: 0, Errors: 0, Time \
elapsed: 0.016 sec
The next time it’s your bag to figure out the performance of some Groovy code or you want to test the performance and scalability of your hip Java application with Groovy, give JUnitPerf a try! It’s a trip!
0 comments Monday 03 Apr 2006 | Andy | Developer Testing, Dynamic Languages, Groovy, JUnit