Merv-Local + TestNG guide
Introduction
TestNG is a popular Java test framework for suites, data providers, and parallel runs. Merv-Local integrates via MervTestNGHandler and writes the same live HTML dashboard, JSON contract, and KPI index as Cucumber and JUnit 5 — under merv.report.folder.
- How to add
merv-client-apito Maven or Gradle - Minimum
merv.propertiesfor local mode (including parallel) - How to register
MervTestNGHandlerintestng.xmlor with@Listeners - How to run parallel suites with
thread-count - How to record
info,testdata, andvalidationsteps withMervReporter - Optional Selenium/Playwright binding for per-step screenshots
- How to open live and final suite reports in a browser
Add dependency
Add MERV to your project (use the latest version from Maven Central when available):
<dependency>
<groupId>io.github.techelliiptica</groupId>
<artifactId>merv-client-api</artifactId>
<version>4.0.0</version>
</dependency>
Gradle:
testImplementation "io.github.techelliiptica:merv-client-api:4.0.0"
Configure merv.properties
Place merv.properties in your project root (next to pom.xml — the directory where you run mvn test).
Sample Configuration
merv.local=true
merv.regression_suite=Your Regression Suite Name
merv.report.folder=./merv-reports
Download sample merv.properties
Common properties
| Property | Role |
|---|---|
merv.local |
true — Merv-Local: write HTML/JSON reports on disk under
merv.report.folder (no cloud API).false — Merv-Server: send suites, cases, and steps to the MERV
cloud API (set merv.server, API key, and hierarchy as well).
|
merv.report.folder |
Root for timestamped run folders and index.html dashboard. |
merv.regression_suite |
Suite title in JSON and HTML. |
merv.execution.parallel |
true — parallel @Test methods share one suite folder safely (use with parallel="methods" in testng.xml).false — single-threaded run (default for most suites).
|
merv.screenshot |
true (or legacy on / yes) — capture a PNG after each executed step when a WebDriver or Playwright page is bound via MervTestNGHandler.setAutomationToolObject(...).false — no automatic step screenshots (smaller report folders).
|
Register TestNG listener
Register the listener in testng.xml (recommended for suite-wide coverage):
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="My Suite">
<listeners>
<listener class-name="org.teche.merv.client.plugin.MervTestNGHandler" />
</listeners>
<test name="Regression">
<classes>
<class name="com.example.MyTestClass" />
</classes>
</test>
</suite>
Or on a test class:
import org.testng.annotations.Listeners;
import org.teche.merv.client.plugin.MervTestNGHandler;
@Listeners(MervTestNGHandler.class)
public class MyTestClass {
// @Test methods, @BeforeMethod, @AfterMethod
}
Each @Test method becomes a Merv testcase. @BeforeMethod, the test body, and @AfterMethod appear as steps. TestNG groups on a method are stored as testcase tags in the report.
Parallel runs
Run up to three test methods in parallel with TestNG and Merv:
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="Parallel Suite" parallel="methods" thread-count="3">
<listeners>
<listener class-name="org.teche.merv.client.plugin.MervTestNGHandler" />
</listeners>
<test name="Parallel tests">
<classes>
<class name="com.example.MyTestClass" />
</classes>
</test>
</suite>
In merv.properties for parallel execution:
merv.execution.parallel=true
Each parallel thread needs its own WebDriver — create and bind the driver in @BeforeMethod and quit in @AfterMethod. Clear the automation binding after each method with MervTestNGHandler.setAutomationToolObject(null, null).
Bind automation (optional)
When merv.screenshot=true, register your driver or page before steps that should capture screenshots:
import org.teche.merv.client.plugin.AutomationTool;
import org.teche.merv.client.plugin.MervTestNGHandler;
// Selenium
MervTestNGHandler.setAutomationToolObject(AutomationTool.SELENIUM, driver);
// Playwright Java
MervTestNGHandler.setAutomationToolObject(AutomationTool.PLAYWRIGHT, page);
Plugin steps in tests
Use MervReporter — the same API as Cucumber and JUnit 5:
import org.teche.merv.client.plugin.MervReporter;
MervReporter.info("Reached checkout page");
MervReporter.testdata("Request body", jsonPayload);
MervReporter.validation("Order total", expectedTotal, actualTotal);
Each call creates a typed step (INFO, TEST_DATA, ASSERTION) in the live and final HTML reports.
File test data
Attach a file as test data — copies into the report folder and renders inline in HTML when possible:
import java.io.File;
import org.teche.merv.client.plugin.MervReporter;
MervReporter.testdata("Payload", new File("src/test/resources/payload.json"));
MervReporter.testdata("Expected UI", new File("screenshots/expected.png"));
- Text / JSON / CSV / Java — inline preview in the step
- Images — inline thumbnail; click to zoom
- Other files — download bar (max 20 MB per file)
Step screenshots
When merv.screenshot=true and a driver is bound, Merv captures a PNG after each executed step and stores it under {runFolder}/screenshots/.
In merv-report.html and merv-report-live.html:
- Steps with screenshots show a camera icon on the title
- Click the step header (title + status row) to show or hide the screenshot
- Use the toolbar Show screenshots toggle for the screenshot movie; per-step toggles still work when it is off
Run tests
With a testng.xml under src/test/resources/:
mvn test -Dsurefire.suiteXmlFiles=src/test/resources/testng.xml
Without a suite file, Surefire can still pick up *Test.java classes if the listener is on each class via @Listeners.
Gradle: configure the TestNG suite in your build, then ./gradlew test. Merv creates a timestamped run folder and refreshes index.html while tests execute.
Viewing Merv reports
After a run, reports live under {merv.report.folder} (for example
./merv-reports/). Open paths through a local web server — not via
file:// in the file manager.
index.html— dashboard: suite grid, KPI charts, consolidated views{runFolder}/html/merv-report.html— final suite report for one run{runFolder}/html/merv-report-live.html— live suite view while tests run (polls JSON every 5s)
Open with a web server
Merv-Local reports load JSON and charts with fetch. Browsers often block that on
file:// URLs. Use your IDE’s static server (or any local HTTP server) so the address
bar shows http://localhost:….
- Install the Live Server extension.
- Right-click
merv-reports/index.htmland choose Open with Live Server. - Open
{runFolder}/html/merv-report-live.htmlon the same server while tests run. - Click a step header with the camera icon to expand step screenshots in the suite report.
- Right-click
merv-reports/index.htmland choose Open in Browser. - Open suite reports from
{runFolder}/html/the same way. - Confirm the address bar shows
http://localhost:…, notfile://.
Other editors and CI
Any local static server works: npx serve merv-reports or
python3 -m http.server --directory merv-reports, then open
http://localhost:…/index.html.
Troubleshooting
| Issue | What to check |
|---|---|
| Blank dashboard or “load issue” | Open reports via http://localhost, not file://. Hard-refresh after a new run. |
| No Merv steps in report | Confirm MervTestNGHandler is in testng.xml or @Listeners. Use MervReporter for custom steps. |
Surefire ignores testng.xml |
Pass -Dsurefire.suiteXmlFiles=src/test/resources/testng.xml or configure suiteXmlFiles in the Surefire plugin. |
| No step screenshots | Set merv.screenshot=true and call MervTestNGHandler.setAutomationToolObject(...) in @BeforeMethod. |
| Click step but no image | Upgrade merv-client-api to 4.0.0+. Confirm screenshots/*.png exists under the run folder. |
| Parallel runs overwrite reports | Set merv.execution.parallel=true so threads share one suite folder safely. |
| Server mode instead of local | Ensure merv.local=true in merv.properties on the test classpath. |
What’s next
- Merv documentation — pick another framework
- Cucumber guide · JUnit 5 guide
- Merv-Server guide — send TestNG results to the cloud
- Sample local report
- Home — product overview and screenshots
MERV