2025-02-10 11:15:21
,某些文章具有时效性,若有错误或已失效,请在下方留言。Both Swift Testing and XCTest have simple mechanisms for controlling how long tests should be allowed to run before being considered a failure. This is critically important for concurrent tests, where the system could otherwise be waiting huge lengths of time.
Swift Testing 和 XCTest 都有简单的机制来控制测试在被视为失败之前应允许运行多长时间。这对于并发测试至关重要,否则系统可能会等待很长时间。
With Swift Testing, time limits are set by adding an extra trait to the @Test
macro called .timeLimit()
. This lets you specify how many minutes – yes, minutes – the test should be allowed to run for before it’s considered a failure.
在 Swift Testing 中,通过向 @Test
宏添加一个名为 .timeLimit()
的额外 trait 来设置时间限制。这允许您指定在将测试视为失败之前应允许运行多少分钟(是的,分钟)。
For example, we could apply a 1-minute maximum runtime like this:
例如,我们可以应用最长 1 分钟的运行时间,如下所示:
@Test("Loading view model names", .timeLimit(.minutes(1)))
func loadNames() async {
let viewModel = ViewModel()
await viewModel.loadNames()
#expect(viewModel.names.isEmpty == false, "Names should be full of values.")
}
If you use a time limit with a whole test suite, that limit is applied to all tests inside there individually. If you then use a different time limit for a specific test, the shorter of the two is used.
如果对整个测试套件使用时间限制,则该限制将单独应用于其中的所有测试。如果您随后对特定测试使用不同的时间限制,则使用两者中较短的时间限制。
Over in XCTest, we can do something similar with XCTestExpectation
, but we need to wrap our async work in a task so that we have control over the execution time – if we used await
directly then the test would stop while the work happened, regardless of the execution time limit.
在 XCTest 中,我们可以对 XCTestExpect
做类似的事情,但我们需要将异步工作包装在一个任务中,以便我们可以控制执行时间——如果我们直接使用 await
,那么测试将在工作发生时停止,无论执行时间限制如何。
So, the XCTest code would look like this:
因此,XCTest 代码将如下所示:
final class DataHandlingTests: XCTestCase {
func test_loadNames() async {
let viewModel = ViewModel()
let expectation = XCTestExpectation(description: "Names should be full of values.")
Task {
await viewModel.loadNames()
if viewModel.names.isEmpty == false {
expectation.fulfill()
}
}
await fulfillment(of: [expectation], timeout: 60)
}
}
The fulfillment(of:timeout:)
function measures its timeout in seconds rather than minutes, so I’ve used 60 there to match the Swift Testing code.fulfillment(of:timeout:)
函数以秒而不是分钟为单位来测量其超时时间,因此我在那里使用了 60 来匹配 Swift 测试代码。
Important: Unit tests work best when they are fast – you should be able to execute thousands of them a second. This means trying to perform live networking in frequently run unit tests is a bad idea, and you should either carve those tests off into a separate test target you run less frequently, or set up test mocks that let you send back virtual data immediately rather than waiting for the network.
重要: 单元测试在快速时效果最佳 – 您应该能够在每秒执行数千个单元测试。这意味着尝试在频繁运行的单元测试中执行实时网络是一个坏主意,您应该将这些测试划分到您运行频率较低的单独测试目标中,或者设置测试模拟,以便您立即发回虚拟数据,而不是等待网络。