Search code examples
javamavenjunitannotationssurefire

Hook custom annotation to the JUnit Tester in Maven


Currently when running a maven build all my tests are run and a surefire-report is created as an XML log (called TEST-my.project.TestApp).

I have created my own custom annotation, @Trace(RQ = "requirement it tests") in order to link my tests to a certain requirement which it is verifying.

What I want is that when a test is run with Maven during a build, inside the XML Log that is generated in surefire-reports instead of:

<testcase time="0.113" classname="my.project.TestApp" name="FirstTest"/>

I should get:

<testcase time="0.113" classname="my.project.TestApp" name="FirstTest">
  <traceability>requirement it tests</traceability>
</testcase>

My problem is:

How do I hook my annotation and implementation of the handling of the said annotation to the JUnit class runner used by Maven when it builds? Or how to hook it to the surefire plugin which creates the report?


Solution

  • Ok, I managed to do something which works pretty well for me:

    First I do my custom annotation:

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD) //can use in method only.
    public @interface Trace {
        public String[] RQ() default "";
    }
    

    Then I do a listener:

    public class TestLogger extends RunListener {
    private static Map<String[], String[]> requirementsMap = new LinkedHashMap<String[], String[]>();
    
    public void testFinished(Description description) {
        if (description.getAnnotation(Trace.class) != null){
            String[] testDescription = { description.getClassName(), description.getMethodName() };
            requirementsMap.put(testDescription, description.getAnnotation(Trace.class).RQ());
        }
    }
    
    @Override
    public void testRunFinished(Result result) throws Exception {
    
        XMLRequirementsReporter writer = new XMLRequirementsReporter();
        writer.writeXMLReport(requirementsMap);
        super.testRunFinished(result);
        }
    }
    

    Then I make my own Junit test runner in which I add my listener:

    public class TestRunner extends BlockJUnit4ClassRunner
    {
        public TestRunner(Class<?> klass) throws InitializationError
        {
             super(klass);
        }
    
        @Override
        public void run(RunNotifier notifier)
        {
            notifier.addListener(new TestLogger()); 
            super.run(notifier);
        }
    }
    

    Lastly I add to the pom XML the following:

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>
    
    <build>
        <resources>
            <resource>
                <directory></directory>
                <targetPath>${project.build.directory}/surefire-reports</targetPath>
                <includes>
                    <include>TEST-Traceability.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    <build>
    

    This will generate my own xml report at maven build in which I have a correlation between requirements and tests and which i can further use to generate a HTML report or anything really.