Configures ExtentReports v5 for a JVM (or .NET via `extentreports-dotnet`) test run: wires `ExtentSparkReporter`, `attachReporter`, `createTest`, the `info`/`pass`/`warning`/`skip`/`fail` log chain, screenshots via `MediaEntityBuilder`, hierarchical `createNode` parent/child tests, and category/author/device labels, emitting a static HTML report alongside JUnit XML for CI artifact upload. Use when a suite on the Aventstack ExtentReports stack wants a richer per-test HTML narrative than JUnit XML gives; for code-coverage reporting use jacoco-analysis, and for hosted cross-run flakiness analytics use currents-integration.
75
94%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
ExtentReports is a Java / .NET test reporting library - ExtentReports
holds the run; pluggable reporters (ExtentSparkReporter for
HTML, ExtentKlovReporter for the Klov server) consume the events
and produce the artifact (extent-wiki).
Project status note (extent-readme): "ExtentReports is being sunset and will be replaced by ChainTest Framework." Teams already on ExtentReports v5 should plan a future migration; new projects should evaluate ChainTest first.
This skill covers the v5 API as documented in the official wiki.
extentreports-dotnet project (same
API shape).If the team is starting fresh, evaluate ChainTest (the announced
successor per extent-readme) before adopting ExtentReports.
For framework-agnostic richer reporting,
allure-reports covers similar ground
with broader language support.
extentreports dependency (or extentreports-dotnet for
.NET) and pin the version.ExtentReports, attach an ExtentSparkReporter("<path>"),
and call extent.flush() at the end of the run - without flush()
no file is written.createTest(name) then chain log levels
(info / pass / warning / skip / fail); attach failure
screenshots via MediaEntityBuilder.Maven:
<dependency>
<groupId>com.aventstack</groupId>
<artifactId>extentreports</artifactId>
<version>5.1.2</version>
</dependency>Per extent-readme, v5.1.2 is the latest release as of 2024-06-26. Pin a version explicitly; the project is in maintenance mode pending ChainTest.
Per the extent-wiki complete example:
import com.aventstack.extentreports.ExtentReports;
import com.aventstack.extentreports.MediaEntityBuilder;
import com.aventstack.extentreports.Status;
import com.aventstack.extentreports.markuputils.MarkupHelper;
import com.aventstack.extentreports.reporter.ExtentSparkReporter;
public class Main {
public static void main(String[] args) {
ExtentReports extent = new ExtentReports();
ExtentSparkReporter spark = new ExtentSparkReporter("target/Spark/Spark.html");
extent.attachReporter(spark);
// ... createTest calls ...
extent.flush();
}
}Three load-bearing pieces:
new ExtentReports() - the run aggregator. Holds tests +
metadata; emits to all attached reporters on flush().new ExtentSparkReporter("<path>") - the HTML reporter.
Path is the output file.extent.attachReporter(spark) - wires reporter to the run.extent.flush() at the end of the run writes the report to disk.
Without flush(), no file is written - the most common new-user
mistake.
Per extent-wiki:
extent.createTest("LogLevels")
.info("info")
.pass("pass")
.warning("warn")
.skip("skip")
.fail("fail");The chain reads top-to-bottom in the report. info is neutral;
pass / fail / skip set the test's overall status; warning
surfaces a yellow flag without changing status.
Each createTest returns an ExtentTest; calls on it accumulate
log entries. Multiple createTest calls on the same extent
produce multiple test entries in the report.
Per extent-wiki:
extent.createTest("ScreenCapture")
.addScreenCaptureFromPath("extent.png")
.pass(MediaEntityBuilder.createScreenCaptureFromPath("extent.png").build());Two patterns:
.addScreenCaptureFromPath("...") - attaches the screenshot
to the test as a top-level media entity.MediaEntityBuilder.createScreenCaptureFromPath("...").build()
passed to a status method - attaches the screenshot to the
specific log entry (the .pass(...) call here).The latter pattern is preferred for failure screenshots: capture the
screenshot inside the test framework's @AfterEach failure hook
and pass it to .fail(...) so the failure log includes the visual
evidence inline.
A minimal runnable report with one passing test, the log-level chain,
and a screenshot inlined on the pass entry:
import com.aventstack.extentreports.ExtentReports;
import com.aventstack.extentreports.MediaEntityBuilder;
import com.aventstack.extentreports.reporter.ExtentSparkReporter;
public class Demo {
public static void main(String[] args) {
ExtentReports extent = new ExtentReports();
extent.attachReporter(new ExtentSparkReporter("target/Spark/Spark.html"));
extent.createTest("checkout adds item")
.info("navigated to cart")
.pass("item added",
MediaEntityBuilder.createScreenCaptureFromPath("cart.png").build());
extent.flush(); // writes target/Spark/Spark.html - omit it and nothing is written
}
}Open target/Spark/Spark.html in a browser: the test shows the
info and pass log lines top-to-bottom with the screenshot inlined
on the pass entry.
ExtentReports HTML is a human artifact, not a CI gate - keep emitting
JUnit XML for the gate and upload the Spark HTML alongside it.
Register the reporter through a JUnit 5 TestWatcher (or TestNG
listener) so every pass/fail is logged and flush() runs in the
suite teardown, then upload target/Spark/ with if: always()
(Extent matters most on failure runs). The lifecycle extension and
the artifact-upload step are in
references/api-and-ci-wiring.md.
| Anti-pattern | Why it fails | Fix |
|---|---|---|
Skipping extent.flush() | No HTML file written; CI artifact step uploads an empty directory. | Always call flush() in the suite-level teardown (see Operating in CI). |
| One ExtentReports instance per test class (separate HTML files) | Reports fragment across the run; reviewer has to open N files. | One per run; use Categories to navigate (see the richer-API reference). |
| Logging assertion details without screenshots on UI tests | Failure context is missing the visual; debugging requires reproducing. | MediaEntityBuilder on every .fail(...) (see Screenshots and media). |
| ExtentReports as a substitute for JUnit XML in CI gating | The HTML is for humans; CI gates need machine-readable XML. | Emit both; gate on JUnit XML; surface Extent as artifact. |
| Hard-coded category / author strings | Drift; renames don't propagate; filter list grows polluted. | Author a small enum / constants class; reference centrally. |
| Adopting ExtentReports for a new project in 2026+ | Project is sunset per extent-readme; you'll migrate later. | Evaluate ChainTest (announced successor) or allure-reports. |
| Manually computing pass/fail counts vs trusting the reporter | Reporter aggregates from the events; manual count drifts. | Read the extent.flush()-emitted extent.json for programmatic access. |
extent.json companion file (auto-emitted)
rather than parsing the HTML.extent.json, format markdown, post via gh pr comment).allure-reports - framework-agnostic
alternative with broader language support (and not sunset).junit-xml-analysis - pair with
ExtentReports for CI gating; the JUnit XML is the gate, the
Spark HTML is the human-readable artifact.