Testing Complex Scenarios

Why do we need to test complex distributed scenarios?

Tests that verify the integrity of a small unit are useful but
limited. Experience has taught us that most bugs are found in the
integration phase. These problems range from two modules that fail
to work together, all the way to two separate applications that are
acting up. Whether it is two application servers, a client/server
environment, or even a peer-to-peer scenario, it is highly important
to test these complex scenarios because of the tricky bugs that can
be found in them. But it is nearly impossible to do so with
JUnit.

Although Java is platform-independent, it is wise to check an
application on more than one operating system. Your application may
work very well on all operating systems, but it may not function
exactly the way you expect it to work on some of them. Running the
same set of tests over and over again for every OS is time-consuming, and with JUnit you cannot perform distributed tests, so
you don't have a way to run the same series of tests simultaneously
on several JVMs each running on different OSes.

Some units of code can only be tested in a multiple-JVM
scenario. For example, testing the opening of a connection (TCP
socket or HTTP connection) and the integrity of the information
retrieved from it is not possible (or very hard) to test with only
one JVM, which is the only option that exists with JUnit.

Coordinating JUnit Tests Using Ant

It is possible to coordinate several tests running on different
JVMs using only JUnit and Ant. Ant can run tasks both serially and
in parallel (using the <parallel> tag), and can
be configured to stop if any of these tasks fail.

There are several limitations to this approach. First, using
JUnit together with Ant still limits you to one box and one
operating system. Second, as you accumulate many tests, the Ant XML
file grows ever bigger and more unmanageable. Third, we found that
in some cases the forked JVMs remained up and running even after
the Ant task had terminated.

The Pisces project came into the world because of these
limitations and in order to fully equip JUnit with the ability to
test complex and distributed scenarios. The next sections of this
article will introduce this open source project.

Taking JUnit Out of the Box with Pisces

Pisces Basics

Project Pisces is an innovative open source project that extends
the JUnit framework. Like many other extensions, Pisces adds
functionality to JUnit while keeping the way you use it exactly the
same.

At the heart of Pisces lies the ability to run JUnit tests on a
remote JVM on the same computer, or on a separate one. These remote
tests are wrapped in JUnit tests that are run locally so that the
developer or QA person performs regular (local) tests using regular
JUnit GUI tools. The wrapper object for the remote tests is called
RemoteTestCase and it extends the TestCase object.

Figure 2 shows the remote test and its wrapper.

Figure 2. The remote test and its wrapper

On every remote location we run a Pisces Agent application with
a unique agent name. That agent performs the actual JUnit test and
returns the result to the local test. Now, once we can run a remote
test wrapped in a local test, we can create a more complex scenario
that is composed of several remote tests. Figure 3 shows a test
suite composed of several remote tests.