
JUnit HTML Report: How to Generate and Use
JUnit HTML reports provide a visually appealing and comprehensive way to analyze test results from your Java test suites. While JUnit generates basic XML output by default, HTML reports make it much easier to share test results with stakeholders, identify failing tests quickly, and track testing trends over time. In this guide, you’ll learn how to generate professional HTML reports using various tools and plugins, configure them for different build systems, and leverage advanced features for better test reporting in your development workflow.
How JUnit HTML Reports Work
JUnit itself doesn’t generate HTML reports natively – it produces XML output that contains all the test execution data. HTML report generation happens through additional tools that parse this XML and transform it into readable HTML format. The most common approaches include:
- Maven Surefire Report Plugin for Maven projects
- Gradle Test Report task for Gradle builds
- Third-party tools like ExtentReports or Allure Framework
- CI/CD platforms with built-in report generation
The XML output contains detailed information about test execution including test names, execution times, failure messages, stack traces, and system properties. HTML report generators parse this data and create interactive dashboards showing test statistics, trends, and detailed failure analysis.
Setting Up HTML Reports with Maven
Maven’s Surefire Report Plugin is the most straightforward way to generate HTML reports for Maven projects. Here’s the complete setup:
<project>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<junit.version>5.9.2</junit.version>
</properties>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M9</version>
<configuration>
<includes>
<include>**/*Test.java</include>
<include>**/*Tests.java</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>3.0.0-M9</version>
<configuration>
<showSuccess>true</showSuccess>
<outputDirectory>${project.build.directory}/surefire-reports</outputDirectory>
</configuration>
</plugin>
</plugins>
</reporting>
</project>
Generate the reports by running these commands:
mvn clean test
mvn surefire-report:report
mvn site
The HTML reports will be available in target/site/surefire-report.html
. For more advanced styling and custom templates, you can configure the plugin with additional parameters:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>3.0.0-M9</version>
<configuration>
<linkXRef>false</linkXRef>
<showSuccess>true</showSuccess>
<outputName>junit-report</outputName>
<reportsDirectories>
<reportsDirectory>${project.build.directory}/surefire-reports</reportsDirectory>
</reportsDirectories>
</configuration>
</plugin>
Gradle HTML Report Configuration
Gradle has built-in HTML test reporting that’s enabled by default. Here’s how to customize and enhance it:
plugins {
id 'java'
}
repositories {
mavenCentral()
}
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
test {
useJUnitPlatform()
reports {
html.enabled = true
xml.enabled = true
junitXml.enabled = true
html {
destination = file("$buildDir/reports/tests/html")
}
xml {
destination = file("$buildDir/reports/tests/xml")
}
}
testLogging {
events "passed", "skipped", "failed"
exceptionFormat "full"
showStandardStreams = false
}
finalizedBy jacocoTestReport
}
Run tests and generate reports:
./gradlew clean test
# Reports available at build/reports/tests/test/index.html
For custom report styling, create a CSS file and reference it in your build script:
test {
reports {
html {
enabled = true
stylesheet = file('src/test/resources/custom-test-report.css')
}
}
}
Advanced HTML Reporting with ExtentReports
ExtentReports provides much more sophisticated HTML reports with charts, screenshots, and custom logging. Here’s the implementation:
<dependency>
<groupId>com.aventstack</groupId>
<artifactId>extentreports</artifactId>
<version>5.0.9</version>
</dependency>
Create a test listener to integrate ExtentReports:
import com.aventstack.extentreports.ExtentReports;
import com.aventstack.extentreports.ExtentTest;
import com.aventstack.extentreports.reporter.ExtentSparkReporter;
import com.aventstack.extentreports.reporter.configuration.Theme;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.TestWatcher;
public class ExtentReportExtension implements TestWatcher {
private static ExtentReports extent;
private static ThreadLocal<ExtentTest> test = new ThreadLocal<>();
static {
ExtentSparkReporter htmlReporter = new ExtentSparkReporter("reports/extent-report.html");
htmlReporter.config().setTheme(Theme.STANDARD);
htmlReporter.config().setDocumentTitle("Test Execution Report");
htmlReporter.config().setReportName("JUnit Test Results");
extent = new ExtentReports();
extent.attachReporter(htmlReporter);
extent.setSystemInfo("Environment", "Test");
extent.setSystemInfo("User", System.getProperty("user.name"));
}
@Override
public void testSuccessful(ExtensionContext context) {
test.get().pass("Test passed");
}
@Override
public void testFailed(ExtensionContext context, Throwable cause) {
test.get().fail(cause);
}
@Override
public void testDisabled(ExtensionContext context, Optional<String> reason) {
test.get().skip("Test disabled: " + reason.orElse("No reason"));
}
public static void createTest(String testName) {
ExtentTest extentTest = extent.createTest(testName);
test.set(extentTest);
}
public static void flushReports() {
extent.flush();
}
}
Use the extension in your test classes:
@ExtendWith(ExtentReportExtension.class)
public class SampleTest {
@BeforeEach
void setUp() {
ExtentReportExtension.createTest("Sample Test Case");
}
@AfterAll
static void tearDown() {
ExtentReportExtension.flushReports();
}
@Test
void testAddition() {
int result = 2 + 3;
assertEquals(5, result);
}
}
Comparison of HTML Report Tools
Tool | Setup Complexity | Customization | Features | Performance Impact | Best For |
---|---|---|---|---|---|
Maven Surefire | Low | Limited | Basic reporting | Minimal | Simple Maven projects |
Gradle Built-in | None | Medium | Good visual design | Minimal | Gradle projects |
ExtentReports | Medium | High | Charts, screenshots, logs | Low | Professional reporting |
Allure Framework | High | Very High | Timeline, trends, attachments | Medium | Enterprise projects |
JaCoCo with reports | Medium | Medium | Coverage + test results | Low | Coverage analysis |
Real-World Use Cases and Examples
Here are practical scenarios where HTML reports prove particularly valuable:
Continuous Integration Pipeline: When running tests on a VPS or dedicated server, HTML reports provide immediate visibility into test failures without digging through logs.
# Jenkins Pipeline Example
pipeline {
agent any
stages {
stage('Test') {
steps {
sh 'mvn clean test'
}
post {
always {
publishHTML([
allowMissing: false,
alwaysLinkToLastBuild: true,
keepAll: true,
reportDir: 'target/site',
reportFiles: 'surefire-report.html',
reportName: 'JUnit Report'
])
}
}
}
}
}
Multi-module Maven Projects: Aggregate reports across modules for comprehensive testing overview:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>3.0.0-M9</version>
<configuration>
<aggregate>true</aggregate>
<linkXRef>false</linkXRef>
</configuration>
<reportSets>
<reportSet>
<reports>
<report>report</report>
</reports>
</reportSet>
<reportSet>
<id>aggregate</id>
<inherited>false</inherited>
<reports>
<report>report</report>
</reports>
</reportSet>
</reportSets>
</plugin>
Integration with Test Categories: Generate separate reports for different test types:
@ExtendWith(ExtentReportExtension.class)
@Tag("integration")
public class IntegrationTest {
@Test
@Tag("database")
void testDatabaseConnection() {
// Database integration test
}
@Test
@Tag("api")
void testApiEndpoint() {
// API integration test
}
}
Best Practices and Common Pitfalls
Performance Considerations: HTML report generation can slow down build times, especially with large test suites. Use these optimizations:
- Generate reports only in CI/CD pipelines, not during local development
- Configure parallel test execution to reduce overall runtime
- Use build profiles to conditionally enable detailed reporting
- Implement report archiving to prevent disk space issues
<profiles>
<profile>
<id>detailed-reports</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<parallel>methods</parallel>
<threadCount>4</threadCount>
<reportFormat>xml</reportFormat>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Security and Accessibility: When hosting reports on web servers, implement proper access controls:
# Apache .htaccess example for report directory
AuthType Basic
AuthName "Test Reports"
AuthUserFile /path/to/.htpasswd
Require valid-user
# Nginx configuration
location /reports {
auth_basic "Test Reports";
auth_basic_user_file /etc/nginx/.htpasswd;
try_files $uri $uri/ =404;
}
Common Issues and Solutions:
- Missing test results: Ensure XML output is generated before HTML conversion
- Encoding problems: Set UTF-8 encoding in build configuration
- Large report files: Implement report rotation and cleanup strategies
- Browser compatibility: Test reports across different browsers, especially in corporate environments
Integration with Code Coverage: Combine JUnit reports with JaCoCo for comprehensive analysis:
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.8</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
HTML reports transform raw test data into actionable insights that improve development workflows. Whether you’re using basic Maven/Gradle reporting or advanced tools like ExtentReports, the key is choosing the right level of detail for your team’s needs while maintaining build performance. For more information about JUnit 5 features, check the official JUnit 5 User Guide.

This article incorporates information and material from various online sources. We acknowledge and appreciate the work of all original authors, publishers, and websites. While every effort has been made to appropriately credit the source material, any unintentional oversight or omission does not constitute a copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe that any content used in this article infringes upon your copyright, please contact us immediately for review and prompt action.
This article is intended for informational and educational purposes only and does not infringe on the rights of the copyright owners. If any copyrighted material has been used without proper credit or in violation of copyright laws, it is unintentional and we will rectify it promptly upon notification. Please note that the republishing, redistribution, or reproduction of part or all of the contents in any form is prohibited without express written permission from the author and website owner. For permissions or further inquiries, please contact us.