Test Report using test class annotation information

I am migrating an ant build to a gradle build.

Currently we use annotated test methods and a custom Junit formatter to out the annotation information into the xml junit output. Then using a customised xslt file we can generate a HTML report that includes information from the annotations in the test classes.

As there is no way to add the equivalent in gradle, I have been looking into using the testListener interface to output the same information (but it does not need to be a HTML report equivalent, I am happy to start with creating a simple text file).

So in the test.afterTest closure I can get the test class name from testDescriptor.parent.name, but Class.forName will throws a ClassNotFound exception.

The source sets api does not supply access to the classes so this appears to be a dead end.

How can I get this code to work:

test.afterTest { TestDescriptor testDescriptor, TestResult result ->
    def testClass = Class.forName(testDescriptor.parent.name)     // throws ClassNotFoundException!!!
    def testMethod = testClass.getMethods().find{it.equals(testDescriptor.name)}
    testMethod.declaredAnnotations.each {
       // do something with the annotation here to output information.....
    }
}

The error is a result of the fact that your test code is not on the build script classpath. If you want to load these classes you’ll have to do so via a custom classloader prior to inspecting them for their annotations. You’ll be able to reference your test classes via sourceSets.test.output.

Thanks for those pointers, I have decided to go for creating a plugin to achieve what I wanted, but for reference here is a solution to the above problem, which can be pretty much cut and pasted into a plugin…

test.afterTest { TestDescriptor testDescriptor, TestResult result ->
     List<URL> urls = project.configurations.getByName('testCompile').files.collect {
            it.toURI().toURL()
     }
     // you need to include the main source output because tests 
     // usually test something in the main source....
     urls.add(sourceSets.main.output.classesDir.toURI().toURL())
     urls.add(sourceSets.test.output.classesDir.toURI().toURL())
    
     URL[] urlArray = urls.toArray()
     URLClassLoader loader = new URLClassLoader(urlArray)
     def clazz = Class.forName(testDescriptor.parent.name, false, loader)
     
     Method[] methods = clazz.getDeclaredMethods()
     // perform normal java reflection to introspec annotations etc.
}