ExpectToEventuallyEqual 是一个用于异步代码的 XCTest 断言。
假设我们有一个从视图模型读取数据的表格视图。视图模型决定了表格中的行数
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
results.count
}
表格视图控制器的 viewDidLoad()
方法告诉视图模型加载数据,然后重新加载表格数据。 因为 load()
是异步的,所以我们等待它的结果并将它包装在 Task
中。
Task {
results = await viewModel.load()
self.tableView.reloadData()
}
如果此 Task
包含对闭包的调用,则测试可以等待 XCTestExpectation
并注入一个闭包,该闭包调用期望上的 fulfill()
。 因此,测试此方法的一种方法是添加一个完成闭包,该闭包在数据重新加载后触发。
另一种方法是以周期性间隔检查某些条件。 在将两个结果存根到视图模型后,这是一个 expectToEventuallyEqual
断言,它检查行数最终是否为 2
try await expectToEventuallyEqual(
actual: { tableDataSource.tableView(sut.tableView, numberOfRowsInSection: 0) },
expected: 2
)
该断言重复计算 actual
闭包,并将其与 expected
值进行比较。 只要它们相等,此断言就会通过。 如果超时且值仍然不相等,则断言失败。
有一个 SampleApp 你可以尝试查看一些通过的测试和一个失败的测试。
如果您有一个 Project.swift
文件,请声明以下依赖项
dependencies: [
.package(url: "https://github.com/jonreid/ExpectToEventuallyEqual", from: "1.0.0"),
],
然后将其添加到您的测试目标中
.testTarget(
name: "MyTests",
dependencies: [
"ExpectToEventuallyEqual",
],
允许 actual
闭包抛出异常。
actual
闭包和 expected
值必须计算为相同的 Equatable
类型。
默认 timeout
为 1 秒。您可以指定不同的值。
每次比较后,RunLoop
会短暂运行以处理线程上的其他事件。
失败时,断言报告预期值和最后实际值。 如果它们是字符串,则这些值显示在双引号中,以下字符表示为转义特殊字符
Jon Reid 和 Steven Baker 在一起教授 iOS 研讨会时创建了这个断言。