Absolutely! Let’s continue building your automation framework by exploring TestNG Grouping, ExtentReports Integration, and Handling Failed Test Executions. This comprehensive guide will help you organize your tests efficiently, generate detailed reports, capture screenshots on failures, and rerun only the failed tests seamlessly.
Table of Contents
- 1. Introduction to TestNG Grouping
- 2. Implementing TestNG Groups in Your Test Cases
- 3. Configuring TestNG XML for Group Execution
- 4. Setting Up ExtentReports with Enhanced Features
- 5. Capturing Screenshots on Test Failures
- 6. Integrating ExtentReports Listener with TestNG
- 7. Executing Only Failed Test Cases
- 8. Best Practices
- 9. Conclusion
1. Introduction to TestNG Grouping
TestNG Grouping allows you to categorize your test methods into different groups, enabling selective execution based on specific criteria. This is particularly useful for organizing tests into categories like Sanity, Regression, Master, etc., allowing for flexible and efficient test runs.
Benefits of Grouping:
- Selective Execution: Run only specific groups of tests without executing the entire test suite.
- Organized Structure: Maintain a clear structure by categorizing tests based on functionality or priority.
- Parallel Execution: Combine grouping with parallel execution for optimized test runs.
2. Implementing TestNG Groups in Your Test Cases
To start grouping your tests, you need to annotate your test methods with the @Test annotation’s groups attribute.
2.1. Adding Groups to Test Methods
- Open Your Test Classes:
- Navigate to your test classes, e.g.,
LoginTest.java
,AccountRegistrationTest.java
, etc.
- Navigate to your test classes, e.g.,
- Annotate Test Methods with Groups:
- Use the
groups
attribute in the@Test
annotation to assign groups to each test method.
package com.opencart.tests; import org.testng.Assert; import org.testng.annotations.Test; /** * Test Class for Account Registration. */ public class AccountRegistrationTest extends BaseTest { @Test(groups = {"regression", "master"}) public void tc001_accountRegistrationTest() { // Test implementation } }
Explanation:
- Groups Assigned:
"regression"
: Indicates that this test is part of the regression suite."master"
: Indicates that this test is part of the master suite, which includes all tests.
- Use the
- Assigning Multiple Groups:
- A single test method can belong to multiple groups.
@Test(groups = {"sanity", "master"}) public void tc002_verifyLogin() { // Test implementation }
Explanation: This test belongs to both
"sanity"
and"master"
groups. - Creating a Data-Driven Test Group:
- For data-driven tests, you might want to assign them to a separate group like
"dataDriven"
.
@Test(dataProvider = "accountRegistrationData", dataProviderClass = DataProviderUtil.class, groups = {"dataDriven", "master"}) public void tc003_accountRegistrationDataDrivenTest(String firstName, String lastName, String email, String telephone, String password) { // Test implementation }
Explanation: This test is part of both
"dataDriven"
and"master"
groups. - For data-driven tests, you might want to assign them to a separate group like
2.2. Updating the Base Class with Group Annotations
To ensure that setup and teardown methods are associated with specific groups, annotate them accordingly.
package com.opencart.base;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
public class BaseTest {
protected static WebDriver driver;
@BeforeClass(groups = {"sanity", "regression", "master", "dataDriven"})
public void setUp() {
// Setup implementation
}
@AfterClass(groups = {"sanity", "regression", "master", "dataDriven"})
public void tearDown() {
// Teardown implementation
}
}
Explanation:
- The
setUp
andtearDown
methods are associated with all relevant groups to ensure they are executed during group-specific test runs.
3. Configuring TestNG XML for Group Execution
TestNG XML files define how tests are executed. By configuring groups in the XML, you can specify which groups to include or exclude during a test run.
3.1. Creating a Grouping TestNG XML File
- Create a New TestNG XML File:
- Right-click on your project > New > File.
- Name it
grouping.xml
and place it in your project root or a designated folder.
- Define Groups in the XML File:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"> <suite name="GroupingSuite"> <listeners> <listener class-name="com.opencart.utilities.ExtentReportManager"/> </listeners> <test name="GroupingTests"> <groups> <run> <include name="sanity"/> <include name="regression"/> <include name="master"/> <include name="dataDriven"/> </run> </groups> <classes> <class name="com.opencart.tests.LoginTest"/> <class name="com.opencart.tests.AccountRegistrationTest"/> </classes> </test> </suite>
Explanation:
- Listeners: Integrate
ExtentReportManager
to handle report generation. - Groups: Specify which groups to include during this test run.
- Classes: List all test classes that contain grouped tests.
- Listeners: Integrate
3.2. Running Specific Groups
To run only specific groups of tests, modify the <include>
tags in your testng.xml
file.
- Sanity Group:
<include name="sanity"/>
To run only the “sanity” group.
- Regression Group:
<include name="regression"/>
To run only the “regression” group.
- Master Group:
<include name="master"/>
To run all tests under the “master” group.
- Multiple Groups:
<include name="sanity"/> <include name="regression"/>
To run both “sanity” and “regression” groups.
3.3. Excluding Groups
Sometimes, you might want to include certain groups but exclude others.
<groups>
<run>
<include name="sanity"/>
<exclude name="regression"/>
</run>
</groups>
Explanation:
- This configuration will run tests in the “sanity” group but exclude those in the “regression” group.
4. Setting Up ExtentReports with Enhanced Features
ExtentReports is a popular reporting library that provides visually appealing and detailed reports. We’ll enhance its setup to include dynamic report naming, category information, and more.
4.1. Creating ExtentReportManager Utility Class
- Navigate to Utilities Package:
- Go to
src/test/java/com/opencart/utilities
.
- Go to
- Create ExtentReportManager.java:
- Right-click on utilities > New > Class.
- Name the class
ExtentReportManager
and click Finish.
- Implement ExtentReportManager Class:
package com.opencart.utilities; import com.aventstack.extentreports.ExtentReports; import com.aventstack.extentreports.ExtentTest; import com.aventstack.extentreports.reporter.ExtentSparkReporter; import com.aventstack.extentreports.reporter.configuration.Theme; import org.testng.ITestContext; import org.testng.ITestListener; import org.testng.ITestResult; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; /** * Listener class for ExtentReports integration. */ public class ExtentReportManager implements ITestListener { private static ExtentReports extent; private static ExtentTest test; /** * Initializes the ExtentReports instance with dynamic report naming. * * @param context TestNG test context. */ @Override public void onStart(ITestContext context) { // Generate timestamp for unique report name String timeStamp = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss").format(new Date()); String reportName = "TestAutomationReport_" + timeStamp + ".html"; // Define report file location String reportPath = System.getProperty("user.dir") + "/reports/" + reportName; // Initialize ExtentSparkReporter ExtentSparkReporter spark = new ExtentSparkReporter(reportPath); spark.config().setDocumentTitle("Automation Test Report"); spark.config().setReportName("Functional Testing"); spark.config().setTheme(Theme.STANDARD); // Initialize ExtentReports extent = new ExtentReports(); extent.attachReporter(spark); // Add system info extent.setSystemInfo("Tester Name", System.getProperty("user.name")); extent.setSystemInfo("Environment", "QA"); extent.setSystemInfo("Operating System", System.getProperty("os.name")); } /** * Creates a new test entry in the report upon test start. * * @param result The test result. */ @Override public void onTestStart(ITestResult result) { // Get test class and method name String className = result.getTestClass().getName(); String methodName = result.getMethod().getMethodName(); // Create new test in the report test = extent.createTest(className + " :: " + methodName); // Get groups and add as categories List groups = List.of(result.getMethod().getGroups()); for (String group : groups) { test.assignCategory(group); } } /** * Logs test success in the report. * * @param result The test result. */ @Override public void onTestSuccess(ITestResult result) { test.pass("Test Passed"); } /** * Logs test failure in the report and attaches screenshots. * * @param result The test result. */ @Override public void onTestFailure(ITestResult result) { try { // Capture screenshot String screenshotPath = new BaseTest().captureScreen(result.getMethod().getMethodName()); // Attach screenshot to the report test.fail(result.getThrowable()); test.addScreenCaptureFromPath(screenshotPath); } catch (IOException e) { e.printStackTrace(); test.fail("Failed to attach screenshot"); } } /** * Logs test skip in the report. * * @param result The test result. */ @Override public void onTestSkipped(ITestResult result) { test.skip(result.getThrowable()); } /** * Flushes the ExtentReports instance at the end of the suite. * * @param context The test context. */ @Override public void onFinish(ITestContext context) { extent.flush(); } // Other overridden methods can remain empty if not used @Override public void onTestFailedButWithinSuccessPercentage(ITestResult result) {} @Override public void onTestFailedWithTimeout(ITestResult result) {} }
Explanation:
- onStart:
- Initializes
ExtentReports
with a dynamic report name based on the current timestamp. - Configures report properties like title, name, and theme.
- Adds system information dynamically (e.g., tester name, environment, OS).
- Initializes
- onTestStart:
- Creates a new test entry in the report using the class and method name.
- Assigns categories based on the groups the test belongs to.
- onTestSuccess:
- Logs the test as passed.
- onTestFailure:
- Captures a screenshot upon test failure.
- Attaches the screenshot and logs the exception details.
- onTestSkipped:
- Logs the test as skipped along with the reason.
- onFinish:
- Flushes the report to ensure all logs are written.
- onStart:
- Integrating ExtentReports with TestNG XML:To enable ExtentReports as a listener, you need to specify it in your TestNG XML files.
Example:
<listeners> <listener class-name="com.opencart.utilities.ExtentReportManager"/> </listeners>
Explanation: The
<listeners>
section integrates theExtentReportManager
as a TestNG listener, ensuring that reports are generated based on test execution events.
5. Capturing Screenshots on Test Failures
Capturing screenshots upon test failures is crucial for debugging and provides visual evidence of failures.
5.1. Implementing Screenshot Capture in BaseTest
- Open BaseTest.java:
- Navigate to
src/test/java/com/opencart/base/BaseTest.java
.
- Navigate to
- Add Screenshot Capture Method:
package com.opencart.base; import org.apache.commons.io.FileUtils; import org.openqa.selenium.OutputType; import org.openqa.selenium.TakesScreenshot; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; public class BaseTest { protected static WebDriver driver; @BeforeClass(groups = {"sanity", "regression", "master", "dataDriven"}) public void setUp() { // Initialize WebDriver (e.g., ChromeDriver) System.setProperty("webdriver.chrome.driver", "path_to_chromedriver"); driver = new ChromeDriver(); driver.manage().window().maximize(); driver.get("http://localhost/opencart"); } @AfterClass(groups = {"sanity", "regression", "master", "dataDriven"}) public void tearDown() { if (driver != null) { driver.quit(); } } /** * Captures a screenshot of the current browser window. * * @param testMethodName The name of the test method. * @return The path to the captured screenshot. */ public String captureScreen(String testMethodName) { // Generate timestamp String timeStamp = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss").format(new Date()); // Define screenshot file name and path String screenshotName = testMethodName + "_" + timeStamp + ".png"; String screenshotPath = System.getProperty("user.dir") + "/screenshots/" + screenshotName; // Capture screenshot File src = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE); File dest = new File(screenshotPath); try { FileUtils.copyFile(src, dest); } catch (IOException e) { e.printStackTrace(); } return screenshotPath; } }
Explanation:
- captureScreen Method:
- Generates a timestamp to ensure unique screenshot filenames.
- Captures the screenshot using Selenium’s
TakesScreenshot
interface. - Saves the screenshot in the
screenshots
folder with the test method name and timestamp. - Returns the path to the captured screenshot for report attachment.
- captureScreen Method:
- Creating Screenshots Directory:
- Ensure that the
screenshots
directory exists in your project root. - Create Screenshots Folder:
- Navigate to your project root.
- Right-click > New > Folder.
- Name it
screenshots
.
- Ensure that the
6. Integrating ExtentReports Listener with TestNG
To fully integrate ExtentReports, ensure that your TestNG XML files are configured to use the listener, and your test classes are properly set up.
6.1. Updating TestNG XML with Listener
As shown in Section 3.3, ensure that your TestNG XML includes the ExtentReportManager
listener.
<listeners>
<listener class-name="com.opencart.utilities.ExtentReportManager"/>
</listeners>
6.2. Ensuring WebDriver is Static
To prevent multiple instances of WebDriver, make the driver
variable static in the BaseTest
class.
protected static WebDriver driver;
Explanation: Making driver
static ensures that the same WebDriver instance is shared across different classes and listeners, preventing conflicts.
7. Executing Only Failed Test Cases
TestNG provides a mechanism to rerun only the failed test cases from the previous run, which is highly beneficial for efficient test executions and debugging.
7.1. Understanding TestNG Failed XML
After a test run, TestNG generates a testng-failed.xml
file containing only the failed tests. You can rerun this XML to execute only the failed tests.
7.2. Executing Failed Tests
- Locate testng-failed.xml:
- After a test run, navigate to the
test-output
folder. - Find the
testng-failed.xml
file.
- After a test run, navigate to the
- Run testng-failed.xml:
- Right-click on
testng-failed.xml
> Run As > TestNG Suite. - This will execute only the tests that failed in the previous run.
- Right-click on
7.3. Automating Failed Test Execution
For convenience, you can create a separate TestNG XML file dedicated to running failed tests.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="FailedTestsSuite">
<listeners>
<listener class-name="com.opencart.utilities.ExtentReportManager"/>
</listeners>
<test name="FailedTests">
<classes>
<class name="com.opencart.tests.FailedTestClass"/>
</classes>
</test>
</suite>
Note:
- TestNG’s
testng-failed.xml
automatically includes only failed tests. Manually creating a separate XML for failed tests is optional and depends on your project’s requirements.
8. Best Practices
Implementing TestNG Grouping and ExtentReports effectively requires adhering to best practices to ensure maintainability and scalability.
- Consistent Group Naming:
- Use clear and descriptive group names like
"sanity"
,"regression"
,"master"
,"dataDriven"
. - Avoid ambiguous or overlapping group names.
- Use clear and descriptive group names like
- Maintain Single XML Configuration for Grouping:
- Utilize a single
grouping.xml
file to manage all group executions. - Avoid creating multiple XML files for different groups to reduce complexity.
- Utilize a single
- Dynamic Report Naming:
- Incorporate timestamps in report names to maintain history and avoid overwriting previous reports.
- Centralized Configuration:
- Manage common configurations (like report paths, WebDriver setups) in utility classes or configuration files.
- Error Handling:
- Implement robust error handling in listeners to gracefully manage exceptions during report generation or screenshot capture.
- Avoid Hardcoding Sensitive Information:
- Refrain from hardcoding credentials or sensitive data. Use environment variables or secure storage mechanisms.
- Regularly Review and Update Dependencies:
- Keep your project dependencies up-to-date to leverage the latest features and security patches.
- Integrate with Continuous Integration (CI) Tools:
- Incorporate your TestNG suites into CI pipelines (like Jenkins) for automated test executions on code changes.
- Document Your Framework:
- Maintain clear documentation of your test framework setup, configurations, and conventions to aid team collaboration.
- Optimize Test Execution:
- Balance the number of groups and test methods to optimize parallel executions without overloading system resources.
9. Conclusion
By implementing TestNG Grouping and integrating ExtentReports, you’ve significantly enhanced your automation framework’s efficiency, organization, and reporting capabilities. Grouping allows for selective test executions, making your testing process more flexible and targeted. ExtentReports provides comprehensive and visually appealing reports, aiding in quick analysis and debugging.
Key Takeaways:
- TestNG Grouping: Categorize tests into meaningful groups for selective execution.
- ExtentReports Integration: Generate dynamic and detailed reports with screenshots on failures.
- Handling Failed Tests: Efficiently rerun only failed tests to save time and resources.
- Best Practices: Adhere to best practices for maintainable and scalable test frameworks.
Next Steps:
- Implement Additional Features:
- Explore integrating Selenium Grid for distributed test executions across multiple environments.
- Incorporate Data-Driven Testing using Apache POI for running tests with multiple data sets.
- Enhance Reporting:
- Customize ExtentReports further by adding charts, graphs, or integrating with other reporting tools.
- Automate report archiving and retention policies.
- Continuous Integration (CI):
- Set up CI pipelines to automate test executions on code commits or schedule regular test runs.
- Advanced TestNG Features:
- Utilize TestNG’s advanced features like dependencies, priorities, and annotations for more complex test scenarios.
- Security Enhancements:
- Secure sensitive data within your test framework and reports.
- Implement access controls for report visibility within your team.
Happy Testing! 🚀