Swift testing 框架的 #require 宏

140 阅读2分钟

Swift Testing 是苹果的 XCTest 现代替代库,并引入了新的宏,如 #require。我们之前已经介绍了 #expect 宏,现在将深入研究它的同伴,为给定的测试设置需求。

每个 #require 宏都需要通过测试才能继续。这是一种早期的逻辑预期,除非满足所有要求,否则不会继续。虽然使用 Swift Testing 编写测试不需要宏,但它会使测试更清晰、更容易理解。让我们开始吧。

#reqiure

许多测试在开始测试目标之前需要特定的输入需求。你可以使用带有 #expect 宏的常规断言来编写这些需求。例如,当我们有一个带有可选初始化式的 Person 结构时:

struct Person {
    let firstName: String
    let lastName: String

    var fullName: String {
        firstName + " " + lastName
    }

    init?(firstName: String, lastName: String) {
        guard !lastName.isEmpty else {
            return nil
        }
        self.firstName = firstName
        self.lastName = lastName
    }
}

我们可以编写一个测试 fullName 的需求,以确保构造的 person 不是 nil:

@Test func fullName() {
    let person = Person(firstName: "Zhang", lastName: "San")
    #expect(person != nil, "Zhang San")
    #expect(person?.fullName == "Zhang San")
}

然而,#expect宏并没有使它变得可读性更高,也没有清楚地表明它是测试开始时的必要条件。自我解释的代码是健壮的,在项目中应该始终是你的目标。因此,我们可以使用#require宏重写上面的测试,如下所示:

@Test func fullName() throws {
    let person = Person(firstName: "Zhang", lastName: "San")
    try #require(person != nil, "Person 结构体未成功初始化")
    #expect(person?.fullName == "Zhang San")
}

这是一个细微的差别,但测试变得更容易理解。我们可以通过使用#require宏的返回值进一步优化这个测试。

总结

Swift testing 框架可以让我们用新的 API 和像 #require 这样的宏来编写现代测试。虽然你不一定必须用 #require 宏来编写测试,但它将使你的代码自解释并且更加健壮。