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

TestNG Soft Assert疑问:如何实现所有URL校验后执行assertAll?

你的需求完全可行!

首先得指出你当前代码里的核心问题:每次调用checkUrl方法时都新建了一个SoftAssert实例,这意味着每个URL的断言都是独立的,没法汇总所有结果。要实现“先跑完所有URL校验再统一输出断言结果”的需求,关键是让所有URL校验共享同一个SoftAssert实例。

下面给你两种推荐的实现方案:

方案一:使用类级别的SoftAssert实例(推荐)

把SoftAssert声明为测试类的成员变量,让所有checkUrl调用共享这个实例,最后在统一的@Test方法末尾调用assertAll()来汇总结果。

修改后的完整代码示例:

import org.testng.annotations.Test;
import org.testng.asserts.SoftAssert;
import java.net.HttpURLConnection;
import java.net.URL;

public class UrlRedirectTest {
    // 类级别的SoftAssert实例,所有校验共享
    private final SoftAssert softAssert = new SoftAssert();

    // 把checkUrl改为普通工具方法,去掉@Test和static修饰符
    private void checkUrl(String requestUrl, String expectedUrl) {
        try {
            URL obj = new URL(requestUrl);
            HttpURLConnection conn = (HttpURLConnection) obj.openConnection();
            conn.setReadTimeout(5000);
            conn.addRequestProperty("Accept-Language", "en-US,en;q=0.8");
            conn.addRequestProperty("User-Agent", "Mozilla");
            conn.addRequestProperty("Referer", "google.com");
            
            System.out.println("\nRequest URL ... " + requestUrl);
            boolean redirect = false;
            int status = conn.getResponseCode();
            
            if (status != HttpURLConnection.HTTP_OK) {
                if (status == HttpURLConnection.HTTP_MOVED_TEMP 
                    || status == HttpURLConnection.HTTP_MOVED_PERM 
                    || status == HttpURLConnection.HTTP_SEE_OTHER) {
                    redirect = true;
                }
            }
            
            System.out.println("Response Code ... " + status);
            if (redirect) {
                String redirectUrl = conn.getHeaderField("Location");
                String cookies = conn.getHeaderField("Set-Cookie");
                
                conn = (HttpURLConnection) new URL(redirectUrl).openConnection();
                conn.setRequestProperty("Cookie", cookies);
                conn.addRequestProperty("Accept-Language", "en-US,en;q=0.8");
                conn.addRequestProperty("User-Agent", "Mozilla");
                conn.addRequestProperty("Referer", "google.com");
                
                System.out.println("Redirect to URL : " + redirectUrl);
                softAssert.assertEquals(redirectUrl, expectedUrl, 
                    "Expected URL mismatch for request: " + requestUrl);
            } else {
                softAssert.assertTrue(redirect, 
                    "No redirect detected for request: " + requestUrl);
                System.out.println("** Please check status for " + requestUrl);
                System.out.println("************************************************");
                System.out.println("************************************************");
            }
        } catch (Exception e) {
            // 把异常也加入断言失败,避免遗漏错误
            softAssert.fail("Exception occurred while checking URL: " + requestUrl, e);
            e.printStackTrace();
        }
    }

    // 统一的测试入口,批量处理所有URL,最后汇总断言
    @Test
    public void verifyAllUrlRedirects() {
        // 这里可以添加所有需要校验的URL对
        checkUrl("https://example.com/old-page", "https://example.com/new-page");
        checkUrl("https://test-site.com/redirect-me", "https://test-site.com/target");
        // 更多URL...

        // 所有校验完成后,才触发断言结果汇总
        softAssert.assertAll();
    }
}

方案二:传递SoftAssert实例作为参数

如果不想用类成员变量,也可以在@Test方法中创建SoftAssert实例,然后把它作为参数传递给checkUrl方法,同样能实现共享断言上下文:

@Test
public void verifyAllUrlRedirects() {
    SoftAssert softAssert = new SoftAssert();
    
    checkUrl(softAssert, "https://example.com/old-page", "https://example.com/new-page");
    checkUrl(softAssert, "https://test-site.com/redirect-me", "https://test-site.com/target");
    // 更多URL...
    
    softAssert.assertAll();
}

private void checkUrl(SoftAssert softAssert, String requestUrl, String expectedUrl) {
    // 方法内容和方案一一致,只是使用传入的softAssert实例
}

关键注意点

  1. 去掉原方法的static和@Test:TestNG的@Test方法不建议设为static,而且如果每个URL单独作为@Test,会分散执行,没法统一汇总结果。应该把checkUrl作为工具方法,用一个统一的@Test方法来批量处理。
  2. 异常也要加入断言:原代码中只打印异常栈,但不会标记为断言失败,建议用softAssert.fail()把异常纳入结果汇总,确保所有问题都能被捕获。
  3. assertAll()必须调用:只有调用这个方法,TestNG才会把所有收集到的失败断言一次性抛出,否则即使有断言失败,测试也会显示通过。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:17:10