Swift Testing

I’ve recently turned on Swift 6.0 mode on of my projects and that means migrating all code to strict concurrency. I had some tests that used mocks to capture values and then using an #expect macro to check whether the captured values were the correct ones. One such test looked like this:

@Test
func loginWithNoAccountsAndSuccessfulLoginSavesTokenInCredentialManager() async throws
{
    let expectedCredentials = AccountCredentials(account: "test@instance.social",server: "instance.social", token: "mynewaccesstoken")
    
    var instanceUrlCalled: URL?
    var storedCredentials: AccountCredentials?
    let appModel = withDependencies {
        $0.defaultDatabase = try! appDatabase()
        $0.socialMediaClient = MockSocialMediaServer(connectToInstance:  { url in
            instanceUrlCalled = url
            return expectedCredentials
        })
        $0.accountCredentialsStorage.storeCredentials = { credentials in storedCredentials = credentials
        }
    } operation: {
        AppModel()
    }
    
    #expect(appModel.destination == nil)
    
    try await appModel.login()
    
    guard let expectedUrl = URL(string: "https://instance.social") else {
        Issue.record("Failed to creater URL from string")
        return
    }
    
    #expect(appModel.destination.is(\.onboardingScreen))
    #expect(expectedUrl == instanceUrlCalled)
    #expect(expectedCredentials == storedCredentials)
}

However, capturing these variables caused problems in strict concurrency mode. I could lead to potential data races and therefore swift 6.0 does not allow it. It took me some time to figure out how to fix this, and it turned out you shouldn’t capture any values at all! The fix was as easy as putting the #expect macros in the closures passed to the mock, like this:

I love the new Swift Testing framework and have been using it whenever I can. However, I still have a lot of legacy code that uses XCTest and I want to convert it to the new framework. This includes a lot of grunt work that I was thinking I hopefully could automate with GitHub Copilot. However, when I tried to do this, I found that Copilot often would create a mingle of XCTest and Swift Testing code, or stubbornly stuck to XCTest even when I asked it to use Swift Testing.