September 2006

Repeating system tests system tests

Writing logically hip repeatable tests is especially tricky when testing copasetic Web applications because of the complexity associated with setting up a web environment. It’s easy to write the test– what’s challenging is reducing assumptions regarding how the test will run.

IBM developerWork’s “In pursuit of code quality: Repeatable system tests” introduces Cargo, an open source framework that automates container management in a generic fashion, so you can write logically repeatable system tests every time.

Also too, don’t forget to let it all hang out at the “Improve Your Java Code Quality” forum!

Proactive monitoring of maintenance metrics

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?

Ruby test categorization techniques

Much like pre-JUnit 4, Ruby’s copasetic Test::Unit framework lacks the easy ability to programmatically delineate a particular test’s grouping. Nevertheless, categorizing tests in Ruby is easy man– either through test case naming or directory segmentation. It also helps to use Ruby’s Rake build platform.

Because it’s my bag, I prefer the directory strategy as it is easier to put into place and maintain. Briefly, the strategy is to place unit tests in a unit test directory, component tests in a component test directory and so on. Running a particular category then becomes a simple job of defining the appropriate task in Rake.

For example, the following hip Rake file runs all unit tests defined in the tests/unit/ directory.

require “rake/testtask”

task :default => [:unit_test]

Rake::TestTask.new(:unit_test) do | tsk |
 tsk.test_files = “tests/unit/**/*Test.rb”
end

Obviously, for component and system tests, two additional dynomite tasks would be defined which reference .rb files in the tests/component and tests/system directories. It’s usually a good idea to define a dependency task which can run all the tests, which is elegantly done in Rake as follows:

task :test_all => [:unit_test, :component_test, :system_test]

For example, running all tests via the command line is as simple as typing:

 $> rake -f acme_rake testall

Applying test categorizations to a test suite will greatly reduce build times as that suite grows– especially if the test suite has a plethora of higher level tests, where the time to run a test becomes extended due to outside dependencies like databases. Dig it?

JUnit 4 versus TestNG

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:

  • Lycra stretch disco pants are still hip as ever
  • TestNG has plenty of features not available in JUnit 4
  • Disco record sales are up 600% in the year 1974

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?