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 @@
-
+
+
+