核心摘要:在 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)
#require 是 XCTest 中 XCTUnwrap 的完美替代品。它可以尝试解包一个可选值(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 解包 |