How to force concurrent tests to run on a specific actor 如何强制并发测试在特定actor上运行

How to force concurrent tests to run on a specific actor 如何强制并发测试在特定actor上运行

温馨提示:本文最后更新于2025-02-10 11:19:11,某些文章具有时效性,若有错误或已失效,请在下方留言

Swift Testing and XCTest behave differently when it comes to running tests in parallel: unless you say otherwise, Swift Testing will run both synchronous and asynchronous tests on any task it likes, whereas XCTest will run asynchronous tests on background tasks will always run synchronous code on the main actor.
Swift Testing 和 XCTest 在并行运行测试时的行为不同:除非您另有说明,否则 Swift Testing 将对它喜欢的任何任务运行同步和异步测试,而 XCTest 将在后台任务上运行异步测试,并将始终在主要参与者上运行同步代码。

With Swift Testing, we have multiple options. First, we can mark individual tests with @MainActor or some other global actor, like this:
使用 Swift Testing,我们有多种选择。首先,我们可以使用 @MainActor 或其他全局 actor 标记单个测试,如下所示:

@MainActor
@Test("Loading view model names")
    func loadNames() async {
        // test code here
    }
}

Second, we can mark whole test suites with the same attribute, like this:
其次,我们可以使用相同的 attribute 标记整个测试套件,如下所示:

@MainActor
struct DataHandlingTests {
    @Test("Loading view model names")
        func loadNames() async {
            // test code here
        }
    }
}

And third, if you’re using confirmation() or withKnownIssue() you can specify a global actor to use for just that closure, allowing the rest of the test to run elsewhere. Here’s how that looks:
第三,如果你正在使用 confirmation() 或 withKnownIssue(),你可以指定一个全局 actor 来仅用于该闭包,从而允许测试的其余部分在其他地方运行。这是它的样子:

@Test("Loading view model names")
func loadNames() async {
    await withKnownIssue("Names can sometimes come back with too few values") { @MainActor in
        // test code here
    }
}

If you have a custom actor to work with, you can also pass it to the isolation parameter of both withKnownIssue() and confirmation().
如果您有要使用的自定义 actor,您还可以将其传递给 withKnownIssue() 和 confirmation() 的 isolation 参数。

In XCTest we similar options, including the ability to mark whole tests cases as running on a specific global actor:
在 XCTest 中,我们提供了类似的选项,包括将整个测试用例标记为在特定的全局参与者上运行的功能:

@MainActor
final class DataHandlingTests: XCTestCase {
    func test_iceCreamAllEaten() async {
        // test code here
    }
}

Or adding the same annotation to individual test cases:
或者为单个测试用例添加相同的注释:

final class DataHandlingTests: XCTestCase {
    @MainActor
    func test_iceCreamAllEaten() async {
        // test code here
    }
}

To get something similar to confirmation() where only one specific closure of work runs on the main actor, we’d need to create a task and isolate it there, like this:
要获得类似于 confirmation() 的东西,其中只有一个特定的 work closure 在 main actor 上运行,我们需要创建一个 task 并将其隔离在那里,如下所示:

final class DataHandlingTests: XCTestCase {
    func test_loadNames() async throws {
        let viewModel = ViewModel()
        let expectation = XCTestExpectation(description: "Names should be full of values.")

        Task { @MainActor in
            await viewModel.loadNames()

            if viewModel.names.isEmpty == false {
                expectation.fulfill()
            }
        }

        await fulfillment(of: [expectation], timeout: 60)
    }
}
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享