Ervin Varga
Sourceforge user name: evarga
This is a last installment from a series of articles about the JXUnit framework [1]. This article continues where the previous one [3] stopped. In order to avoid repetition, this paper will not talk about general topics pertaining to the JXUnit framework, nor about terms defined in part 1 [2] (for example, what is a JXU command, what is a JXUC command, etc.). It is highly advisable to read the first part, if you are not comfortable with concepts used in the JXUnit framework, before continuing reading this article, though. This document describes the process of reworking the framework, i.e. how to alter its behavior in a way not originally envisioned by creators of the JXUnit framework. Also, directions are given how to introduce new editors, something more related to the method of extending the Quick framework [4 and 5].
This paper assumes that 'directory' and 'folder' are synonyms, hence, they are used interchangeably in a text.
I dedicate this last part of a primer to my girlfriend Zorica, who has a great understanding (and especially patience) regarding my commitment to computer science.
Since, we are going to tackle some more advanced techniques of the JXUnit framework's usage, knowledge of the Quick framework is mandatory, and especially an acquaintance with QJML is compulsory. The other preconditions for successfully understanding the materials presented here are listed in the first part titled "Overview of the JXUnit Framework". After reading this paper (and the whole series), you should gain enough experience how to customize the JXUnit framework to better serve your particular needs. Of course, for causal usage patterns, the current set of features and commands are absolutely satisfactory.
As a good rule of thumb, before venturing into the implementation of your own enhancements, first look around on the Internet, maybe there is a suitable extension already available. See a description of a generic JXU command [6], for an example how to "upgrade" the JXUnit framework to make it plausible even for functional testing.
First, let us recall the way the JUnit [7]
framework handles test cases. In a JUnit framework a test case
basically defines a fixture "used by" different tests.
Each test runs in its own fixture initialized and cleaned-up by
the methods setUp and tearDown, respectively (see the
documentation of a TestCase
class). Usually, a fixture comprises various instance variables
storing its state. However, a fixture could equally mean some
special condition, which should be met for successfully running a
test. In this latter case, I prefer to talk about session instead
of fixture, though (maybe this terminology is not so fortunate).
For example, before running a test a network connection must be
opened, and after finishing a test a connection has to be closed.
If the same fixture can be utilized by many tests (to eschew
unnecessary initialization and clean-up cycles), a test case can
be decorated by an instance of a TestSetup
class's derivative, and the logic of initialization/clean-up of a
fixture would move to that subclass of TestSetup.
Although, wrapping the test suite containing all your tests in a
subclass of TestSetup
is a viable technique, you
should be cautious, as this can be a warning sign that excessive
coupling exists in your design (for more tips about how to write
effective unit tests consult [8]). Nevertheless, if you are
dealing with a shared session, most of the time, you can rest
assured that nothing wrong has been done in your system, though.
I frequently reuse test suites for testing a system in ON-LINE
and TRAINING modes, respectively; I just wrap them with different
subclasses of TestSetup (OnLineTestSetup and TrainingTestSetup).
The current 3.1.3 version of the JXUnit framework does not have direct support for this kind of fixture "manipulation". For example, consider the following folder structure representing a test suite:
tests/ test_A/... test_B/... test_B_1/... test_B_2/...
If you start a jxtest script from the root 'tests' folder, the folder tree will be traversed, and all subordinate tests will be run. Now, suppose you want to execute 'test_B_1' and 'test_B_2' under a particular session. Only repeating the session initialization/clean-up procedures inside each aforementioned test can do this. A mechanism to mimic the functionality of a TestSetup decorator is, thus, highly desirable in the JXUnit framework, too.
NOTE: The aforesaid functionality can not be "implemented" barely by fiddling with directories, especially if you want to parameterize the initialization/clean-up procedures!
The idea is quite simple. A new JXU file will be introduced called 'tearDown.jxu' (except its name, this JXU file is absolutely equivalent with a 'test.jxu' one). This file must reside in the same directory where the matching 'test.jxu' file is situated (folders containing only a 'tearDown.jxu' file will treated in the same way as folders without a 'test.jxu' file). So, if a folder contains a 'tearDown.jxu' file it means that a 'test.jxu' file holds steps for initializing a session, while a 'tearDown.jxu' file for cleaning it up. Of course, the course taken by the reworked JXUnit framework's engine in this case will be different from a normal one (when a folder does not contain a 'tearDown.jxu' file).
Both tests (denoted by a 'test.jxu' & 'tearDown.jxu' files, respectively) will be parameterized with the same XML data file, if any. This is useful for "synchronizing" these processes, i.e. initialization & clean up. Moreover, the names of the tests will be adorned by " - Setup" and " - Tear Down" postfixes, correspondingly, in order to easily distinguish them from casual tests.
Since, the source code (see the next section) is thoroughly commented, and by now you are pretty acquainted with a JXUnit framework (presuming that you've read the previous articles), no more explanations are given pertaining to the implementation.
Please, unpack the following Part3SourceCode.zip archive into some folder on your hard drive. Let us call this folder as PART3_HOME. The following directory structure will be created:
<PART3_HOME>\src \tests
NOTE: To keep the source code lean, and focused only on issues mentioned in this paper, enhancements introduced in part 2 are not contained in a bundle! You will have to manually merge the stuff from part 3 into part 2, if you want to have a unified code base, though.
In the 'src' folder you will find the source code for a rework of the JXUnit framework. The rework comprises classes implementing a new editor, and a new "version" of the JXTestCase class. The 'tests' folder contains various unit tests, compliant with the JXUnit framework's self-testing principle. The '<PART3_HOME>' folder holds a 'build.xml' file, as well. This is an ANT build file (something, which is missing a lot from the 3.1.3 version of the JXUnit framework). Therefore, you will need to install and configure ANT (the 'build.xml' is tested against ANT 1.4.1) on your machine (please, go to the next link in order to download a latest stable version of ANT). ANT is essentially a Java build tool; it is kind of like the make utility. You are not obligated to download the optional bundle for ANT (containing implementations for optional tasks) in order to successfully use the shipped source code of this article.
To see what targets are available for a build, issue the following command from a '<PART3_HOME>' folder:
ant -projecthelp
Now, here are the steps you need to perform in order to install & configure the source code (it is assumed, that you have had already configured the JXUnit framework as described in [2]):
To browse the generated documentation open the 'index.html' file located in the 'docs\api' directory.
At the end, you will have to edit the appropriate jxtest script file (depending what platform you are using). The script will be copied into '<PART3_HOME>\bin' folder as part of the installation process; you'll need to manually attach this directory to your PATH environment variable (assure that a '<PART3_HOME>\bin' folder is placed before the '<JXUNIT_HOME>\bin' one). The editing is straightforward:
Now, we are ready to proceed further with this paper.
The test case for unit testing the implementation of a 'session based' testing can be found in the 'tests\testSessionBasedTesting' folder. If you enter this folder, and start a jxtest script everything should execute without errors. You can notice on the output that the paired 'test.jxu' and 'tearDown.jxu' tests were parameterized with the same XML data file. Furthermore, by looking the hierarchy of tests (employing the Swing or AWT based test runner) you can observe that 'test_A_*' tests are repeated for each session.
You can exploit global properties (introduced in the previous part) during fixture "creation", as well.
Introducing a new editor will be the last thing presented in this article, and therefore in a whole primer. This topic is actually related to the process of extending the Quick framework rather than the JXUnit one. However, since the JXUnit framework intensively uses the Quick framework, the delineation between them is a bit blurred from a user's perspective. There are situations when none of the built-in editors is satisfactory, hence, new one is needed for interpreting data stored in some "witty" format.
The process is rudimentary, and decently documented in the documentation for a Quick framework. For demonstrational purposes, we will produce a new editor called ByteSequenceEditor. This editor simply reads in textual data filled with comma separated numbers (bytes), and returns a Java byte array. To integrate this editor into the JXUnit framework, you simply have to add the following definition inside a corresponding QJML file:
<targetEditor editor="jxunit.rework.ByteSequenceEditor" target="[B" />
Of course, the above construction should be embedded inside an appropriate element like text.
If you enter the 'tests\testByteSequenceEditor' folder, and start a jxtest script everything should run as anticipated. Obviously, before running a test you will have to translate a QJML file into QIML file by summoning the following command:
cfgQjml2Qiml -in test.qjml -out test.qiml
Please, look into the QJML file situated there, as an example, how to incorporate this new editor into the JXUnit framework.
I hope that you've found the primer as a valuable source of information for mastering the JXUnit framework. Now, you are ready to commence crafting the framework to sweet your demanding needs.