You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Selenium+TestNG+Java框架中软断言失败步骤在ExtentReports中展示

Hey there! Let's work through this problem together. You want to swap out hard assertions for soft ones so your test steps keep running even if one fails, and also make sure each soft assertion failure gets logged directly under its corresponding step in ExtentReports (instead of just a generic failure at the end). Here's a practical, step-by-step solution:

Step 1: Understand the Core Problem

TestNG's native SoftAssert only reports all failures at once when you call assertAll(), which doesn't tie failures to individual test steps in ExtentReports. We need to bridge this gap by wrapping soft assertions with Extent logging logic.

Step 2: Create a Custom Extent-Aware Soft Assert Class

We'll build a utility class that combines TestNG's SoftAssert with ExtentReports' logging. This ensures every assertion failure is immediately logged to the correct test step without stopping execution.

import com.aventstack.extentreports.ExtentTest;
import com.aventstack.extentreports.Status;
import org.testng.asserts.SoftAssert;

public class ExtentSoftAssert {
    private final SoftAssert softAssert;
    private final ExtentTest extentTest;

    // Constructor ties the soft assert to a specific ExtentTest instance
    public ExtentSoftAssert(ExtentTest extentTest) {
        this.softAssert = new SoftAssert();
        this.extentTest = extentTest;
    }

    // Example: Assert True with step-specific logging
    public void assertTrue(boolean condition, String failureMessage) {
        try {
            softAssert.assertTrue(condition, failureMessage);
        } catch (AssertionError e) {
            // Log failure directly to the current Extent test/step
            extentTest.log(Status.FAIL, String.format("%s | Failure Details: %s", failureMessage, e.getMessage()));
        }
    }

    // Example: Assert Equals with value comparison logging
    public void assertEquals(Object actual, Object expected, String failureMessage) {
        try {
            softAssert.assertEquals(actual, expected, failureMessage);
        } catch (AssertionError e) {
            extentTest.log(Status.FAIL, String.format(
                "%s | Expected: %s | Actual: %s | Failure Details: %s",
                failureMessage, expected, actual, e.getMessage()
            ));
        }
    }

    // Add more assertion methods (assertFalse, assertNotNull, etc.) as needed

    // Final check to trigger TestNG's failure reporting
    public void assertAll() {
        try {
            softAssert.assertAll();
        } catch (AssertionError e) {
            extentTest.log(Status.FAIL, String.format(
                "All soft assertions completed. Total failures: %d",
                softAssert.getAllErrors().size()
            ));
            throw e; // Re-throw to mark the test as failed in TestNG
        }
    }
}
Step 3: Integrate the Custom Soft Assert into Your Test Class

In your test methods, initialize the custom soft assert with your ExtentTest instance, and log each test step explicitly. This ensures failures are linked to the correct step in the report.

import com.aventstack.extentreports.ExtentReports;
import com.aventstack.extentreports.ExtentTest;
import com.aventstack.extentreports.reporter.ExtentSparkReporter;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

public class LoginFlowTest {
    private WebDriver driver;
    private ExtentReports extentReports;
    private ExtentTest test;
    private ExtentSoftAssert extentSoftAssert;

    @BeforeMethod
    public void setup() {
        // Initialize Selenium driver
        driver = new ChromeDriver();
        driver.manage().window().maximize();

        // Initialize ExtentReports
        ExtentSparkReporter sparkReporter = new ExtentSparkReporter("test-output/login-test-report.html");
        extentReports = new ExtentReports();
        extentReports.attachReporter(sparkReporter);

        // Create test instance for the current test method
        test = extentReports.createTest("End-to-End Login Flow Test");
        // Initialize our custom soft assert
        extentSoftAssert = new ExtentSoftAssert(test);
    }

    @Test
    public void invalidLoginTest() {
        // Step 1: Navigate to login page
        test.log(Status.INFO, "Navigating to login page");
        driver.get("https://your-test-site.com/login");
        extentSoftAssert.assertEquals(driver.getTitle(), "Secure Login", "Step 1: Login page title mismatch");

        // Step 2: Enter username
        test.log(Status.INFO, "Entering username");
        driver.findElement(By.id("username")).sendKeys("test_user");
        extentSoftAssert.assertEquals(
            driver.findElement(By.id("username")).getAttribute("value"),
            "test_user",
            "Step 2: Username input value mismatch"
        );

        // Step 3: Enter invalid password
        test.log(Status.INFO, "Entering invalid password");
        driver.findElement(By.id("password")).sendKeys("wrong_pass");
        extentSoftAssert.assertEquals(
            driver.findElement(By.id("password")).getAttribute("value"),
            "wrong_pass",
            "Step 3: Password input value mismatch"
        );

        // Step 4: Click login button
        test.log(Status.INFO, "Clicking login button");
        driver.findElement(By.id("login-btn")).click();
        extentSoftAssert.assertTrue(
            driver.findElement(By.id("error-alert")).isDisplayed(),
            "Step 4: Error alert not displayed after invalid login"
        );

        // Final check to ensure TestNG captures all failures
        extentSoftAssert.assertAll();
    }

    @AfterMethod
    public void teardown() {
        if (driver != null) {
            driver.quit();
        }
        // Flush ExtentReports to write all logs to the report file
        extentReports.flush();
    }
}
Key Notes
  • Step-Specific Logging: Each test step uses test.log(Status.INFO) to create a clear entry in ExtentReports. Failures from soft assertions are logged directly under these steps.
  • Custom Assert Methods: You can extend the ExtentSoftAssert class with any assertion types you need (e.g., assertFalse, assertNotNull) following the same pattern.
  • Final assertAll(): This method is critical—it tells TestNG to mark the test as failed if any soft assertions failed, and logs the total number of failures in the report.

内容的提问来源于stack exchange,提问作者JustNatural

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:16:25