pointfreeco / swift-snapshot-testing

📸 Delightful Swift snapshot testing.
https://www.pointfree.co/episodes/ep41-a-tour-of-snapshot-testing
MIT License
3.68k stars 556 forks source link

What's the way to use `assertSnapshot` in async test? #822

Open valeriyvan opened 6 months ago

valeriyvan commented 6 months ago

Please look below example of async test. Test with XCTAssertEqual works as expected but same test with assertSnapshot crashes.

What's the way to use assertSnapshot in async test?

struct AsyncSequenceExample: AsyncSequence {
    typealias Element = Int

    func makeAsyncIterator() -> AsyncIterator {
        print()
        return AsyncIterator()
    }

    struct AsyncIterator: AsyncIteratorProtocol {
        var current = 1

        mutating func next() async throws -> Element? {
            print("enter")
            try await Task.sleep(nanoseconds: 100_000_000) // Simulate an asynchronous operation
            defer { current += 1 }
            guard Int.random(in: 0..<100_000_000) > 1_000_000 else {
                return nil
            }
            print(current)
            return current
        }
    }
}

class MyTests: XCTestCase {
    func testAsyncSequence() async throws {
        let asyncSequence = AsyncSequenceExample()

        var result: [Int] = []
        do {
            for try await element in asyncSequence {
                result.append(element)
            }
        } catch {
            XCTFail("Unexpected error: \(error)")
        }

        // This test works as expected
        // XCTAssertEqual(result, [1, 2, 3])

        // But this crashes
        assertSnapshot(of: result.description, as: .lines)

    }
}
dwroth commented 4 months ago

The problem is the use of XCTWaiter.wait inside of verifySnapshot. Using the synchronous wait function in an asynchronous context is a known issue (that's why Apple introduced await fulfillment(of:).

tejassharma96 commented 3 months ago

Is this crash Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Current context must not be nil'? If so, I am hitting that issue too in an async test :/ is there any workaround that we can use until the library can be updated to support some sort of await assertSnapshot method?

tejassharma96 commented 3 months ago

Actually, I did find that marking all the async tests as @MainActor works, so there's that... still frustrating but I suppose it works now :/