TestAPIGenerator: an utility for creating API tests in Java

What is this?

TestAPIGenerator is an utility for creating Java test suite (JUnit-compliant) that check if a program contains certain classes and methods.

This is useful for example for validating plug-ins or add-ons. Prior the execution of functionality tests to check whether the plug-in adheres to the stablished protocol, the plug-in validation program must check whether the author has create all the needed classes and extended the concrete interfaces.

Using the Java reflection API it is possible to create all these tests. However, their creation is a tedious process. This is specially true when there are a lot of different classes and methods to check. All the tests have a similar structure and differ only in the class or method name or parameters’ type.

As an example, the needed code to ensure the existence of just a Java class like model.Board would we something like:

public class BoardTestAPI extends TestCase {

   // ...

   public void testClassExists() {
      try {
         Class c;
         c = Class.forName("model.Board");
         return c;
      } catch (ClassNotFoundException ex) {
         fail("Class model.Board not found.\n");
      }
   }

   // ...

}

APITestGenerator reads a text file with the description of the API that must be validated (files with the ‘atd’ extension, that stands for ‘API Test Description’) and creates the Java code that check the existence of all the classes and methods specified.

We have successfully used this tool for validating the Java assignments of Computer Science students prior the execution of the functionality tests. More details can be found in our paper entitled “Fighting against the ‘But it works!’ syndrome“.

How is it work?

TestAPIGenerator read a text file with the specification of the API tests that the instructor wants to create. The file includes the description of all the elements that should exist at runtime and generates the tests (.java files) that check their existence using reflection. The code is JUnit-compliant and therefore can be executed as part of a more complex suite of unit tests.

The generated code use meaningful names in the tests (such as testBoardClassExists) and, when they fail, report a user-friendly message (in spanish) like “Clase Board no encontrada.” (Class Board not found).

The list of supported tests is:

  • Enumerations: users can check whether a enumeration class exists, the number of values it has and even the concrete names of every value in the enum.
  • Interfaces: it allows to check the existence of the definition of an Java interface given its name. Users may also specify the set of methods it must have, indicating their names, arguments and return types.
  • Classes: similar to interfaces, the user may specify the existence of Java classes. Together with the set of methods, users may also indicates the set of constructors (with or without parameters) and even whether the class must implement a given interface or have a concrete superclass.

The user may also specify the folder where all the source code of the tests will be generated, together with the name of the test suite class and individual test classes. The test suite created will execute all the API tests specified in the input file.

Download

Version Source distribution Binary distribution
1.0 (Oct-2009) TestAPIGenerator-src-1.0.zip TestAPIGenerator-bin-1.0.zip

Execution

You can execute TestAPIGenerator from the command line. It just receives one parameter with the name of the file that contains the specification of the tests.

The entire order is:

> java -jar TestApiGenerator example.atd

assuming the current folder that with both the .jar and the example file)

Input File format

The input file format is almost self-descriptive. Lines beginning with ‘#’ are considered comments and empty lines are ignored.

Here is an example of an input file that may be used as reference (this file is also included in both source and binary distribution above).

# Folder where test Java files are created
baseDir ./instructorTests

# Test Suite name (java class) to be created
generateTestSuite instructortests.TestAPI

# Check the existence of the model.Disc enum
# with 3 symbols: EMPTY, WHITE and BLACK
# The test class will be the one
# set as 'parameter' to the beginTestClass keyword.
beginTestClass instructortests.model.DiscTestAPI
   beginEnum model.Disc
      numValues 3
      hasValue EMPTY
      hasValue WHITE
      hasValue BLACK
   endEnum
endTestClass	

# Check the existence of the model.Board class
# with three methods:
# model.Disc getCell(int, int);
# boolean putDisc(model.Disc, int);
# boolean fourInARow(model.Disc);
beginTestClass instructortests.model.BoardTestAPI
   beginClass model.Board
      hasMethod model.Disc getCell int int
      hasMethod boolean putDisc model.Disc int
      hasMethod boolean fourInARow model.Disc
   endClass
endTestClass

# Check the existence of the aplication.Aplication
# interface with two methods.
beginTestClass instructortests.aplicacion.AplicacionTestAPI
	beginInterface aplication.Aplication
	hasMethod boolean init
	hasMethod void run
	endInterface
endTestClass

# Check the existence of the aplication.ConsoleApp
# that must implements the previous interface and
# extends the model.Board class.
beginTestClass instructortests.aplication.ConsoleApp
	beginClass aplication.ConsoleApp
	implements aplication.Aplication
	extends model.Board
	endClass
endTestClass

# Check the existence of the Main class
beginTestClass instructortests.MainTestAPI
   beginClass Main
   endClass
endTestClass

Author

This software was developed by Marco Antonio Gómez Martín. If you have any comment or suggestion, contact me.

The software is distributed under the terms of the GNU General Public License.

Los comentarios están cerrados.