The XCTest framework does not seem to be compliant with the Swift 6 concurrency model. See the example below:
Test.swift:
@globalActor
actor TestActor: GlobalActor {
static let shared: TestActor = .init()
}
@TestActor
struct Test {}
XCTest.swift:
import XCTest
@testable import Test
final class Example: XCTestCase {
@TestActor
func testExample() {
let _ = Test()
}
}
This produces the following warning:
warning: data race detected: actor-isolated function at TestTests/XCTest.swift:6 was not called on the same actor
According to this thread, this seems to not be exclusive to XCTest, but it's easily reproducible with it.
Tests that use the Testing framework do not seem to have this issue:
SwiftTesting.swift:
import Testing
@testable import Test
@TestActor
@Test func example() async throws {
let _ = Test()
}
does not produce the warning.
More info:
macOS 14.6.1 (23G93)
Xcode 16.0 (16A242d)
Swift 6
Even though the Swift Testing framework works as intended in this case, it may not be feasible for folks to migrate all their tests to it. Thus it would be nice to fix XCTest.
Is this a bug that should be filed in the Swift repo?
Hi André! Sorry for the late reply—I missed this thread when you originally posted it.
Due to limitations inherent to Swift/Objective-C interop and due to how the XCTest framework[1] is designed, this particular method is not going to be correctly inferred as needing to run on your custom global actor when XCTest goes to execute it. To resolve the issue, you can mark testExample() as async:
import XCTest
@testable import Test
final class Example: XCTestCase {
@TestActor
func testExample() async {
let _ = Test()
}
}
I am referring here to XCTest.framework which ships with Xcode, not to the version of XCTest that is open-sourced and included with the Swift toolchain on Linux/Windows. ↩︎
Sorry about my delay this time @grynspan. async conversations, am I right?
Speaking of async, while before I had the compiler complain with a warning, now the compiler doesn't complain anymore, but the code crashes at runtime like this.
Following your advice here, I tested @crontab's code by marking the property as async and it did fix the crash there.
Perhaps there's maybe more to this than just the interop between Swift and Objective-C?
For context
Xcode: Version 16.2 (16C5032a)
swift-driver version: 1.115.1 Apple Swift version 6.0.3 (swiftlang-6.0.3.1.10 clang-1600.0.30.1)
Target: arm64-apple-macosx15.0