From 4c6f10b77f8cea58e484bb9fa779868f6b72712a Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 19:03:29 +0000 Subject: [PATCH 1/5] Bump Java compiler to 21 and upgrade maven-surefire-plugin to 3.5.2 --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 4eecc16..bba3701 100644 --- a/pom.xml +++ b/pom.xml @@ -13,8 +13,8 @@ UTF-8 - 1.8 - 1.8 + 21 + 21

x

@@ -62,7 +62,7 @@ org.apache.maven.plugins maven-surefire-plugin - 2.19.1 + 3.5.2 ./src/test/resources/suites/testng.xml From 8b469da1b463904499c7dfbf657beb226f7b3905 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 19:08:13 +0000 Subject: [PATCH 2/5] Use Duration-based implicitlyWait (Selenium 4) in BaseTest --- src/test/java/example/example/tests/BaseTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/example/example/tests/BaseTest.java b/src/test/java/example/example/tests/BaseTest.java index b962ab1..c12df7b 100644 --- a/src/test/java/example/example/tests/BaseTest.java +++ b/src/test/java/example/example/tests/BaseTest.java @@ -1,6 +1,6 @@ package example.example.tests; -import java.util.concurrent.TimeUnit; +import java.time.Duration; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; @@ -74,7 +74,7 @@ protected void setup() { ops.addArguments("--disable-dev-shm-usage"); driver = new ChromeDriver(ops); driver.manage().window().maximize(); - driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); + driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10)); WebDriverContext.setDriver(driver); } From 4b065574924c563c3d039896e4b9db09425ff000 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 19:14:03 +0000 Subject: [PATCH 3/5] Phase 3: bump TestNG to 7.10.2; migrate @AfterSuite wrapAllUp to @AfterTest --- pom.xml | 2 +- src/test/java/example/example/tests/BaseTest.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index bba3701..559d717 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ org.testng testng - 6.14.3 + 7.10.2 test diff --git a/src/test/java/example/example/tests/BaseTest.java b/src/test/java/example/example/tests/BaseTest.java index b962ab1..a8aecc9 100644 --- a/src/test/java/example/example/tests/BaseTest.java +++ b/src/test/java/example/example/tests/BaseTest.java @@ -7,7 +7,7 @@ import org.openqa.selenium.chrome.ChromeOptions; import org.testng.ITestContext; import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterSuite; +import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Listeners; @@ -45,7 +45,7 @@ public void globalSetup() { * * @param context the context */ - @AfterSuite(alwaysRun = true) + @AfterTest(alwaysRun = true) public void wrapAllUp(ITestContext context) { int total = context.getAllTestMethods().length; int passed = context.getPassedTests().size(); From 18d736484d2daa6295ef829cf8392eccd64721b7 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 19:35:46 +0000 Subject: [PATCH 4/5] Move suite-level summary to ISuiteListener for TestNG 7 TestNG 7 rejects native parameter injection into @AfterSuite (ISuite/ITestContext), and the prior @AfterTest workaround ran per- rather than once per suite. Move globalSetup/wrapAllUp into a SuiteSummaryListener (ISuiteListener) registered via @Listeners, aggregating results across all contexts so the summary runs exactly once per suite. --- .../listeners/SuiteSummaryListener.java | 51 +++++++++++++++++++ .../java/example/example/tests/BaseTest.java | 38 +------------- 2 files changed, 53 insertions(+), 36 deletions(-) create mode 100644 src/test/java/example/example/listeners/SuiteSummaryListener.java diff --git a/src/test/java/example/example/listeners/SuiteSummaryListener.java b/src/test/java/example/example/listeners/SuiteSummaryListener.java new file mode 100644 index 0000000..46dadca --- /dev/null +++ b/src/test/java/example/example/listeners/SuiteSummaryListener.java @@ -0,0 +1,51 @@ +package example.example.listeners; + +import org.testng.ISuite; +import org.testng.ISuiteListener; +import org.testng.ISuiteResult; +import org.testng.ITestContext; + +import example.example.util.LoggerUtil; +import example.example.util.MailUtil; +import example.example.util.TestProperties; + +/** + * Suite-level listener that loads global properties before the suite runs and, + * once the whole suite has finished, logs an execution summary and emails the + * report. This replaces the former {@code @BeforeSuite}/{@code @AfterSuite} + * hooks in {@code BaseTest}: TestNG 7 no longer supports native parameter + * injection into {@code @AfterSuite} methods, and a suite listener guarantees + * the summary runs exactly once per suite while aggregating results across every + * {@code } tag. + */ +public class SuiteSummaryListener implements ISuiteListener { + + @Override + public void onStart(ISuite suite) { + LoggerUtil.log("************************** Test Execution Started ************************************"); + TestProperties.loadAllPropertie(); + } + + @Override + public void onFinish(ISuite suite) { + int total = 0; + int passed = 0; + int failed = 0; + int skipped = 0; + for (ISuiteResult result : suite.getResults().values()) { + ITestContext context = result.getTestContext(); + total += context.getAllTestMethods().length; + passed += context.getPassedTests().size(); + failed += context.getFailedTests().size(); + skipped += context.getSkippedTests().size(); + } + LoggerUtil.log("Total number of testcases : " + total); + LoggerUtil.log("Number of testcases Passed : " + passed); + LoggerUtil.log("Number of testcases Failed : " + failed); + LoggerUtil.log("Number of testcases Skipped : " + skipped); + boolean mailSent = MailUtil.sendMail(total, passed, failed, skipped); + LoggerUtil.log("Mail sent : " + mailSent); + LoggerUtil.log("************************** Test Execution Finished ************************************"); + } + +} diff --git a/src/test/java/example/example/tests/BaseTest.java b/src/test/java/example/example/tests/BaseTest.java index b19a7a5..669bcad 100644 --- a/src/test/java/example/example/tests/BaseTest.java +++ b/src/test/java/example/example/tests/BaseTest.java @@ -5,19 +5,14 @@ import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.chrome.ChromeOptions; -import org.testng.ITestContext; import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; import org.testng.annotations.Listeners; import example.example.context.WebDriverContext; import example.example.listeners.LogListener; import example.example.listeners.ReportListener; -import example.example.util.LoggerUtil; -import example.example.util.MailUtil; -import example.example.util.TestProperties; +import example.example.listeners.SuiteSummaryListener; import io.github.bonigarcia.wdm.WebDriverManager; /** @@ -25,41 +20,12 @@ * * @author Bharathish */ -@Listeners({ ReportListener.class, LogListener.class }) +@Listeners({ ReportListener.class, LogListener.class, SuiteSummaryListener.class }) public class BaseTest { /** The driver. */ protected WebDriver driver; - /** - * Global setup. - */ - @BeforeSuite(alwaysRun = true) - public void globalSetup() { - LoggerUtil.log("************************** Test Execution Started ************************************"); - TestProperties.loadAllPropertie(); - } - - /** - * Wrap all up. - * - * @param context the context - */ - @AfterTest(alwaysRun = true) - public void wrapAllUp(ITestContext context) { - int total = context.getAllTestMethods().length; - int passed = context.getPassedTests().size(); - int failed = context.getFailedTests().size(); - int skipped = context.getSkippedTests().size(); - LoggerUtil.log("Total number of testcases : " + total); - LoggerUtil.log("Number of testcases Passed : " + passed); - LoggerUtil.log("Number of testcases Failed : " + failed); - LoggerUtil.log("Number of testcases Skipped : " + skipped); - boolean mailSent = MailUtil.sendMail(total, passed, failed, skipped); - LoggerUtil.log("Mail sent : " + mailSent); - LoggerUtil.log("************************** Test Execution Finished ************************************"); - } - /** * Setup. */ From 1a7bf44eb84ae6da33b5f1b1efba48dc8e9aa720 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 19:45:44 +0000 Subject: [PATCH 5/5] Register SuiteSummaryListener via testng.xml instead of @Listeners Suite-level listeners are more robustly registered in the testng.xml block than via @Listeners on a test class. Move SuiteSummaryListener there so its onStart/onFinish reliably fire once per suite. --- src/test/java/example/example/tests/BaseTest.java | 3 +-- src/test/resources/suites/testng.xml | 4 +++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/test/java/example/example/tests/BaseTest.java b/src/test/java/example/example/tests/BaseTest.java index 669bcad..cf55964 100644 --- a/src/test/java/example/example/tests/BaseTest.java +++ b/src/test/java/example/example/tests/BaseTest.java @@ -12,7 +12,6 @@ import example.example.context.WebDriverContext; import example.example.listeners.LogListener; import example.example.listeners.ReportListener; -import example.example.listeners.SuiteSummaryListener; import io.github.bonigarcia.wdm.WebDriverManager; /** @@ -20,7 +19,7 @@ * * @author Bharathish */ -@Listeners({ ReportListener.class, LogListener.class, SuiteSummaryListener.class }) +@Listeners({ ReportListener.class, LogListener.class }) public class BaseTest { /** The driver. */ diff --git a/src/test/resources/suites/testng.xml b/src/test/resources/suites/testng.xml index b282705..d3ac96d 100644 --- a/src/test/resources/suites/testng.xml +++ b/src/test/resources/suites/testng.xml @@ -1,7 +1,9 @@ - + + +