Unit Test Cookbooks


From the XpMailingList, by request, with some minor corrections, and reformatted for Wiki:

>How do you invoke the unit tests?...

It depends on your environment:

  1. Java using JDK/emacs/bash/make
  2. Java using VisualAge
  3. Python
  4. C++ using DesignByContract
  5. CommonLisp
  6. ApacheAnt

1. Java using JDK/emacs/bash/make

I use JavaUnit for my unit tests. For a class Foo, its source is in Foo.java. Its unit test lives in a separate class, with the source in TestFoo.java. A command line invokes the unit test, in either console mode or with a GUI. I use the console mode tester:

    java junit.textui.TestRunner TestFoo

I build an "all-in-one" test suite for a package, which runs all of the unit tests in the package. It's called TestAll. This is usually the test I run when working on the package.

I add a rule like this to my makefile:

    test: TestAll.class
        java junit.textui.TestRunner TestAll

when I run "make test", Test'All.class gets built (through another rule) and then junit is run with the standard command-line.

Now I have Emacs up for editing, and a command window (bash) open for compiling and testing. The cycle is: edit, switch to command window, enter "make test" (or control-p and enter, the bash keys for "execute previous command"), and see what happens. When using JikesCompiler to compile this is a very fast cycle -- As fast as a few seconds. I work hard to achieve this velocity for coding and testing because my experience shows that very fast test cycles encourage me to make very small edits, which makes all problems smaller.

2. Java using VisualAge

I use JavaUnit as above, but no emacs, make, or bash (VisualAge substitutes its own ponderous bureauracracy for the productivity of my beloved tools). Because I have no make file, I add a main to TestAll which does exactly what the command line for invoking junit does (except that in this environment I use the GUI test runner, not the console one):

    public static void main (String[] args)
      {
      junit.ui.TestRunner.main (new String[] {"TestAll"} );
      }

This lets me run the test by clicking on the silly little "running man" button on the toolbar (just what is he running from?).

3. Python

I use PythonUnit. If I have a file "foo.py," then I have a "test_foo.py" which contains the unit tests. I mark test_foo.py as executable and put the python hash-bang at the top of the first line so I can invoke the test by just entering the filename at the command-line:

    test_foo.py

I get test turnaround cycle times even faster than with my command-line Java environment because I don't need to compile first.

I have yet to try making the PythonUnit equivalent of my java "Test'All" which invokes all unit tests, but I don't expect it to be very hard.

4. C++ using DesignByContract

I haven't done this for a few years. It was a fairly successful environment for me, but very high discipline was required due to the rigors of design-by-contract. I also never liked having all those asserts -- I routinely ended up with small methods that had 14 lines of asserts and 3 lines of code.

DesignByContract involves lots of asserts splattered throughout the code to check preconditions, postconditions, and invariants. If I had a class Foo, it would live in a file Foo.cpp. The unit test would be in the same file, but between #ifndef statements to make the unit test go away when the program was compiled for production:

    #ifndef NDEBUG
      void testFoo() {...}
    #endif

class Foo {...}

There was a master test unit (Test.cpp) which contained a single method called "selfTest" which invoked ALL of the unit tests in all of the files in the program. Finally, the main method of my program would invoke that master unit test as the first thing that the program did:

    int main (int argv, char * argv[]  )
      {
      #ifndef NDEBUG
        selfTest();
      #endif
      ...
      }

This caused the self test to run every time the program run (unless it were compiled with NDEBUG defined to produce a production version). I never decided if this was a good thing or not. It sure made me keep the test time short, which is a good thing. In any case, I have put design-by-contract aside for now to study less strenuous methods.

I could have used CppUnit, but it didn't exist at the time and I wasn't smart enough to invent it.

    -- WayneConrad

See UnitTestsDefined for the recipe to keep the test code out of the production code, without extra goodies like *Unit.

5. CommonLisp

I wrote a file unit.lisp with support functions (they do little other than removing a few small elements which were common to every test file; it's not strictly necessary), and the units I was testing were .lisp files. For each file to be tested, foo.lisp, I wrote a file foo-test.lisp. foo-test.lisp started by ensuring that unit.lisp was loaded, then loaded foo.lisp, defined and ran all the tests, printed their success status, and deleted the packages created by foo.lisp and foo-test.lisp. Thus, using CmuCommonLisp?, I could type '(load "foo-test")' to the listener, and the tests would run.

-- DanielKnapp

6. ApacheAnt

    <target name="test" depends="prepare,compile">
        <junit printsummary="yes" haltonerror="yes" haltonfailure="yes">
        <formatter type="plain" />
        <classpath refid="app.classpath"/>
        <batchtest fork="no" todir="${reports.tests}">
            <fileset dir="${src}">
                <include name="**/tests/*Test*.java" />
            </fileset>
        </batchtest>
        </junit>
    </target>

See also JavaUnitAndAnt


CategoryTesting


EditText of this page (last edited January 5, 2005) or FindPage with title or text search