Testing Complex Packages with GrandTestAuto

In Getting Started with GrandTestAuto we saw how our test classes must relate to our production code in order to be run by GrandTestAuto (GTA), as well as how to invoke the tool. We saw that GTA requires tests for all public classes and for all public and protected methods in those classes. This tutorial answers the following questions:

To see some real-life use of GTA, have a look at the unit tests for GTA itself (these, and the rest of the source code, are in the download).

Testing protected methods and classes with protected constructors

By the design motivation for GTA, protected methods and constructors will need to be invoked from outside the package in which they are defined. There is a little trick to doing this. Suppose that X is a public class in a package p that we are developing:


package p;

public class X {
    protected X( String str ) {
        //Constructor body ...
    }

    protected String a() {
        //Method body ...
    }
}

The trick is to have an extension of X along with our class XTest:


package p.test;

public class XTest {
    public boolean constructorTest() {
        X x = new XExt( "a string" );
        //Test state of x ...
    }

    public boolean aTest() {
        XExt x = new XExt( "a string" );
        String str = x.a();
        //Test str ...
    }
}

class XExt  extends X {
    protected XExt( String str ) {
        super( str );
    }

    protected String a() {
        return super.a();
    }
}

This trick will work so long as the class or method under test is not final. Classes that are final and have a protected constructor are exempt from being tested, and so are methods that are protected and final.

Naming tests for overloaded method names

As we saw in the first tutorial, test methods take no parameters. How then is it possible to have separate tests for methods that have the same name. Suppose that a class has testable methods as follows:

  public boolean meth() ...
   public void meth( String str ) ...
    protected String meth( char[] c )...

GTA uses a naming pattern to differentiate the tests for these methods. The pattern works by incorporating the parameter types for a method into the test name. So the names of the test methods for the methods above would be:

  public boolean methTest() ...
   public boolean meth_String_Test() ...
    public boolean meth_charArray_Test() ...

The naming pattern for test methods is:

As an example of this naming pattern, suppose that class X includes the testable methods m(), m( String ), m( int ) and m( String[], int[][] ). Then the names of the corresponding test methods would be m_Test(), m_String_Test(), m_int_Test(), and m_StringArray_intArray2_Test().

Testing of inherited methods

In this section we look in detail at the way that GTA ensures that all accessible methods in a package are tested. As usual, we'll work with an example. Consider a package with public classes:

The test sub-package must contain test classes for B and C. The test for B must contain tests for its implementation of b and c. The test for C must contain tests for e and its implementation of c. The method a defined in A must be tested in either BTest or CTest. The method b defined in A is inherited only by C so must be tested in CTest.