Skip to content

Commit 35a00db

Browse files
shossain786claude
andauthored
fix(junit5): fire ExecutionHook.onSuiteStart on the JUnit Platform (#156)
SeleniumBootLauncherListener only handled plan end, so suite-start hooks never ran for JUnit 5 / Cucumber-on-JUnit runs. Bootstrap (idempotent) and fire HookRegistry.onSuiteStart() in testPlanExecutionStarted. Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
1 parent 66c1a07 commit 35a00db

4 files changed

Lines changed: 66 additions & 0 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
99

1010
### Unreleased
1111

12+
- **JUnit Platform: suite-start hooks now fire** — `ExecutionHook.onSuiteStart()` was never called on the JUnit 5 path (only TestNG), so hooks that open a run or start a clock silently did nothing. `SeleniumBootLauncherListener` now bootstraps the framework and fires `onSuiteStart()` once per test plan.
13+
1214
- **Failed tests with trace links in GitHub Actions job summary** — when running inside GitHub Actions and `tracing.enabled: true` is on, failed tests are automatically summarized in a Markdown table (test name, error message, and path to the HTML trace file) appended to `$GITHUB_STEP_SUMMARY`. Triage failures and locate trace paths directly from the Actions job summary without downloading artifact bundles; no-op outside Actions or when all tests pass. (#137)
1315

1416
- **Bounded failure detail record** — every failed test now exports one optional-field `failureDetail` object with the failing locator, top application frame, last successful step, page URL/title, heal events, console errors, retry/history status, and representative same-cause context. The HTML failure panel and opt-in AI prompt reuse this record; raw errors and stack traces remain available. Text/list/URL limits and the exact AI data disclosure are documented. (#142)

‎docs-site/docs/changelog.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ All notable changes to Selenium Boot are documented here.
1111

1212
## [Unreleased]
1313

14+
- **JUnit Platform: suite-start hooks now fire** — `ExecutionHook.onSuiteStart()` was never called on the JUnit 5 path (only TestNG), so hooks that open a run or start a clock silently did nothing. `SeleniumBootLauncherListener` now bootstraps the framework and fires `onSuiteStart()` once per test plan.
15+
1416
- **Failed tests with trace links in GitHub Actions job summary** — when running inside GitHub Actions and `tracing.enabled: true` is on, failed tests are automatically summarized in a Markdown table (test name, error message, and path to the HTML trace file) appended to `$GITHUB_STEP_SUMMARY`. Triage failures and locate trace paths directly from the Actions job summary without downloading artifact bundles; no-op outside Actions or when all tests pass. (#137)
1517

1618
- **Bounded failure detail record** — every failed test now exports one optional-field `failureDetail` object with the failing locator, top application frame, last successful step, page URL/title, heal events, console errors, retry/history status, and representative same-cause context. The HTML failure panel and opt-in AI prompt reuse this record; raw errors and stack traces remain available. Text/list/URL limits and the exact AI data disclosure are documented. (#142)

‎src/main/java/com/seleniumboot/junit5/SeleniumBootLauncherListener.java‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.seleniumboot.flakiness.FlakinessAnalyzer;
88
import com.seleniumboot.hooks.HookRegistry;
99
import com.seleniumboot.internal.SeleniumBootContext;
10+
import com.seleniumboot.lifecycle.FrameworkBootstrap;
1011
import com.seleniumboot.metrics.ExecutionMetrics;
1112
import com.seleniumboot.reporting.JUnitXmlReporter;
1213
import com.seleniumboot.precondition.PreConditionRunner;
@@ -29,6 +30,22 @@
2930
@SeleniumBootApi(since = "1.9.0")
3031
public class SeleniumBootLauncherListener implements TestExecutionListener {
3132

33+
/**
34+
* Fires suite-start hooks once per test plan — the JUnit 5 equivalent of
35+
* {@code SuiteExecutionListener.onStart()}. Bootstrap is idempotent, so this is
36+
* safe alongside {@link SeleniumBootExtension#beforeAll}. A bootstrap failure is
37+
* left for the extension to surface with its full cause chain.
38+
*/
39+
@Override
40+
public void testPlanExecutionStarted(TestPlan testPlan) {
41+
try {
42+
FrameworkBootstrap.initialize();
43+
HookRegistry.onSuiteStart();
44+
} catch (Exception e) {
45+
System.err.println("[Selenium Boot] Suite start hooks skipped: " + e.getMessage());
46+
}
47+
}
48+
3249
@Override
3350
public void testPlanExecutionFinished(TestPlan testPlan) {
3451
try {
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.seleniumboot.unit;
2+
3+
import com.seleniumboot.hooks.ExecutionHook;
4+
import com.seleniumboot.hooks.HookRegistry;
5+
import com.seleniumboot.junit5.SeleniumBootLauncherListener;
6+
import org.testng.annotations.AfterMethod;
7+
import org.testng.annotations.Test;
8+
9+
import java.lang.reflect.Field;
10+
import java.util.List;
11+
12+
import static org.testng.Assert.assertEquals;
13+
14+
/**
15+
* Unit tests for {@link SeleniumBootLauncherListener} — the JUnit Platform
16+
* counterpart of {@code SuiteExecutionListener}.
17+
*/
18+
public class SeleniumBootLauncherListenerTest {
19+
20+
@AfterMethod
21+
public void resetRegistry() throws Exception {
22+
Field f = HookRegistry.class.getDeclaredField("hooks");
23+
f.setAccessible(true);
24+
((List<?>) f.get(null)).clear();
25+
}
26+
27+
@Test
28+
public void testPlanExecutionStarted_firesSuiteStartHookOnce() {
29+
CountingHook hook = new CountingHook();
30+
HookRegistry.register(hook);
31+
32+
new SeleniumBootLauncherListener().testPlanExecutionStarted(null);
33+
34+
assertEquals(hook.suiteStarts, 1, "onSuiteStart must fire once per test plan");
35+
}
36+
37+
private static final class CountingHook implements ExecutionHook {
38+
int suiteStarts;
39+
40+
@Override
41+
public void onSuiteStart() {
42+
suiteStarts++;
43+
}
44+
}
45+
}

0 commit comments

Comments
 (0)