🔥

Swift Testing 宏对比:#expect vs #require 核心差异与选型

(更新于 )

核心摘要:在 Swift Testing 框架中,#expect 是“软断言”,失败后测试继续执行;#require 是“硬断言”,失败后立即终止当前测试。此外,#require 还是 XCTUnwrap 的现代替代品,用于安全解包可选值。

#expect#require 是 Swift Testing 框架(Swift 6 标准测试库)中最核心的两个宏。虽然它们都用于验证条件,但在错误处理机制和适用场景上存在本质区别。

1. 语法差异:try 的必要性

#require 的机制是通过抛出错误来停止测试执行,因此无论表达式本身是否抛出错误,调用它时必须使用 try 关键字。

Swift
@Test func syntaxDemo() throws {
    let value = 10
    
    // ✅ 正确:#expect 不需要 try (除非表达式本身抛出错误)
    #expect(value == 10) 
    
    // ✅ 正确:#require 必须配合 try 使用
    try #require(value > 0)
}

2. 核心功能:解包可选值 (Unwrapping)

#requireXCTestXCTUnwrap 的完美替代品。它可以尝试解包一个可选值(Optional),如果值为 nil,测试立即失败并停止;如果成功,则返回解包后的非空值供后续使用。

Swift
@Test func unwrappingDemo() throws {
    let user: User? = fetchUser()
    
    // 如果 user 为 nil,测试在此处终止,不再执行后续代码
    // 相当于 guard let user = user else { throw Failure }
    let validUser = try #require(user) 
    
    // 此处 validUser 已是非可选类型
    #expect(validUser.name == "Fatbobman")
}

3. 运行时行为:继续 vs 终止

这是两者最大的逻辑区别,决定了测试报告的详细程度。

#expect (软断言)

即使断言失败,测试函数继续执行。这允许你在一次测试运行中收集多个错误信息。

Swift
@Test func softAssertion() {
    #expect(1 == 2) // ❌ 失败,记录错误
    print("这行代码会被执行") 
    #expect(3 == 4) // ❌ 再次失败,记录第二个错误
}

结果:测试标记为失败,报告中显示 2 个 Issue。

#require (硬断言)

一旦断言失败,抛出错误,测试函数立即终止。适用于后续代码依赖于当前条件成立的场景(如前置条件检查)。

Swift
@Test func hardAssertion() throws {
    try #require(1 == 2) // ❌ 失败,抛出错误并终止
    print("这行代码永远不会执行")
}

结果:测试标记为失败,报告中仅显示 1 个 Issue。

总结:如何选择?

特性#expect#require
断言类型软断言 (Soft)硬断言 (Hard)
失败行为记录错误,继续执行记录错误,立即终止
关键字通常不需要 try必须使用 try
返回值返回解包后的值 (针对 Optional)
适用场景验证属性、状态检查前置条件检查、Optional 解包

延伸阅读

相关提示

订阅 Fatbobman 周报

每周精选 Swift 与 SwiftUI 开发技巧,加入众多开发者的行列。

立即订阅