Welcome!

Java Authors: Maureen O'Gara, Bruce Armstrong, Liz McMillan, Walter H. Pinson, III, Yakov Werde

Related Topics: Java

Java: Article

Java Annotations + Compiler API + Annotation Processing = Remarkable Results

Effective Development of Java Conformance Tests Meta-Programming

Then, the Filtering tool parses the passed XML file to get an instance of a TestGroup object. After that, it applies AttributeFilter to all TestCases in the TestGroup to detect which of them doesn't meet the selection criteria. Rejected TestCases are removed from the TestGroup. The whole TestGroup can be rejected if it doesn't meet the selection criteria or if all the TestCases are rejected. When AttributeFilter has been applied, the Filtering Tool returns the TestGroup to XML for further processing. Newly created (intermediate) XML necessarily contains only tests that apply to the technology.

With Internal Representation, the API development of TCK-specific filters is very simple. The following is an example of the filter that accepts tests marked with Java Architecture for XML Binding (JAXB) technology version 2.0 and compatible versions:

public class JaxbTechnologyFilter implements AttributeFilter {
    String ver = "2.0";
    public boolean accept(TestGroup tg) {
       return FilterUtil.checkTechnology(tg.getTechnologies(), "JAXB", ver);
    }
    public boolean accept(TestGroup tg, TestCase tc) {
       return FilterUtil.checkTechnology(tc.getTechnologies(), "JAXB", ver);
    }
}

It's unnecessary to list all technologies to which the test applies. A test can be selected or rejected by the class or method under test.

The following example demonstrates how to select tests that cover only the JAXB API specification (the javax.xml.bind package):

    public boolean accept(TestGroup tg) {
       String testedPackage = tg.getTestedPackage();
       return testedPackagetg.getTestedPackage().startsWith("javax.xml.bind");
}

Generation Tool: The purpose of the Generation tool is to generate test sources to include in the product. The functionality of the Test Generator tool itself is small enough. It does the preliminary work, such as parsing XML, detecting the type of test, and instantiating and invoking an appropriate test emitter. The emitter does the real work of test generation. All test generation emitters implement the JavaEmitter interface:

public interface JavaEmitter {
    public void generate(TestGroup[] testGroups);
}

The default JavaEmitter generates one HTML file for all passed TestGroups. The JavaEmitter checks all test attributes and finds all tested methods. For each method it creates combined descriptions about how it's tested and by which test cases. The JavaEmitter is also responsible for creating Test Monitor instructions based on test attributes.

The Java Emitter is also responsible for generating Java sources. The default Java Emitter generates a separate Java file for each TestGroup and does much routine work, such as determining the package, inserting necessary imports, adding copyright blocks in the correct format, and creating the main(String[] args) method. Each test case is extracted as a method. The JavaEmitter generates well-formed JavaDoc comments from test attributes.

Tests can be differentiated by extraction type, and each test type can be associated with its own emitter. So one can either introduce a new type or assign an existing type to an emitter.

A typical situation when an alternative emitter is required would be the following: on some Micro Edition Platforms a restriction is placed on available memory and consequently on class file size. For such TCKs the emitter creates one class for each separate test case. The emitter increases test execution time but makes it possible to run tests.

Known Issues
One major issue in the described approach is the difficulty of writing tests in XML, which is very good for machine processing, but not convenient for people. An IDE can't be used without installing specially designed plug-ins. Plug-ins help, but they don't allow the use of an IDE's many useful features.

But this problem can be solved! Metadata can be specified with annotations. Java SE 6 provides an excellent and powerful mechanism for processing Java sources: the Compiler API and Annotation Processing (JSR 199 and JSR 269). This processing makes it possible to keep attributes in Java and generate XML for further processing from Java. Such an approach will make test development easier and preserve existing functionality: selecting applicable tests and customizing generation (see Listing 3).

Conclusion
Disposable data that can be auto-completed increases product quality and makes product support easier. Metadata lets code be shared between products and decorates that code dynamically. XML is a good language for data representation, but it's more effective for the intermediate level of processing. Using Java Annotations in combination with the Compiler API and Annotation Processing can give you remarkable results.

Meta-programming is power.

More Stories By Dmitry Fazunenko

Dmitry Fazunenko is a lead TCK programmer at Sun Microsystems Inc. His expertise is in developing Technology Compatibility Kits for Java SE platforms. He has been working in this area for a decade and during the past six years, he has focused on developing and improving techniques for effective test development.

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.