I want to generate XML report file with info of executed tests. Previously I used shown below @Rule
in JUnit4 but now I want to display comment or some short of short description instead of testName. After some research I found @DisplayName
in JUnit5 that seems to suit my needs. Now I have to update my @Rule
to display @DisplayName
content instead of testName[number].className
.
Tests are written in JUnit classes and have following structure
@Test
@DisplayName("This text should be displayed as name")
public void testy1() {...}
To display outcome and name of run test I created new rule with following scheme
@Rule
public TestRule watchman = new TestWatcher() {
@Override
public Statement apply(Statement base, Description description) {
return super.apply(base, description);
}
@Override
protected void succeeded(Description description) {
try {
junitWriter.write("\n <test>"
+ "\n <name>" + description.getDisplayName() + "</name>"
+ "\n <result>..
+ "\n <message>..
+ "\n </test>");
} catch [..]
}
@Override
protected void failed(Throwable e, Description description) {
//same scheme with error
}
}
To start tests I run
Result result = JUnitCore.runClasses(mainSuiteClassCreatingReport);
System.out.printf("Test ran: %s, Failed: %s%n", result.getRunCount(), result.getFailureCount());
In generated XML file instead of "DisplayName" annotation I keep getting methodName[number].className
. Can anybody help me to display/save it the way I want?
You cannot use @DisplayName
with JUnit 4.
If you want to use @DisplayName
, you'll need to switch to JUnit Jupiter (a.k.a., JUnit 5) and implement an Extension
.
Note that JUnit Jupiter does not yet support an extension API like the TestWatcher
rule from JUnit 4; however, such support is coming in JUnit 5.4: https://github.com/junit-team/junit5/issues/542
To customize what is returned from getDisplayName()
in Description
in JUnit 4, you would need to write your own custom Runner
. As an alternative, you could simply parse the value returned from getDisplayName()
and use that to generate your own display name.
Or, if you want to support your own custom display name annotation with JUnit 4, such as this:
package foo;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyDisplayName {
String value();
}
You could look it up in your TestWatcher
implementation using reflection like this:
package foo;
import java.lang.reflect.Method;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
public class ExampleTests {
@Rule
public TestRule watchman = new TestWatcher() {
@Override
protected void succeeded(Description description) {
System.out.println("Display name: " + getDisplayName(description));
}
private String getDisplayName(Description description) {
Class<?> testClass = description.getTestClass();
String methodName = description.getMethodName();
try {
Method method = testClass.getDeclaredMethod(methodName);
MyDisplayName myDisplayName = method.getAnnotation(MyDisplayName.class);
return myDisplayName.value();
}
catch (Exception ex) {
// do something with the exception if you want...
}
// default:
return testClass.getName() + "." + methodName + "()";
}
};
@Test
public void testWithoutCustomDisplayName() {
}
@Test
@MyDisplayName("Custom display name!")
public void testWithCustomDisplayName() {
}
}
Running that test class outputs the following:
Display name: foo.ExampleTests.testWithoutCustomDisplayName()
Display name: Custom display name!