You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Swift Testing中使用confirmation()满足expectedCount要求

Swift Testing中confirmation预期计数验证失败问题

我尝试用Swift Testing的confirmation(_:expectedCount:fileID:filePath:line:column:_:)方法的expectedCount参数,验证函数恰好执行25次,但测试报错:

Confirmation was confirmed 0 times, but expected to be confirmed 25 times

我的测试代码如下:

@Test func testStreamingPrimesUpTo100ShouldBe25() async {
    let maximumCount = 100
    await confirmation("Calculate primes up to \(maximumCount)", expectedCount: 25) { primesNumber in
        PrimeCalculator.calculateStreaming(upTo: maximumCount) { _ in
            primesNumber()
        }
    }
}

我曾试过在calculateStreaming的完成闭包里加计数器,用primerNumber.confirm(count: variable)验证,但触发了EXC_BREAKPOINT错误。

目标函数是计算100以内的质数,应该返回25个结果,PrimeCalculator的代码如下:

struct PrimeCalculator {
    static func calculateStreaming(upTo max: Int, completion: @escaping (Int) -> Void) {
        DispatchQueue.global().async {
            guard max > 1 else {
                return
            }
            var sieve = [Bool](repeating: true, count: max)
            sieve[0] = false
            sieve[1] = false
            for number in 2 ..< max {
                if sieve[number] == true {
                    for multiple in stride(from: number * number, to: sieve.count, by: number) {
                        sieve[multiple] = false
                    }
                    completion(number)
                }
            }
        }
    }
}

以下是XCTest里的等价测试,我想把它迁移到Swift Testing框架:

func testPrimesUpTo100ShouldBe25() {
    // given
    let maximumCount = 100
    let expectation = XCTestExpectation(description: "Calculate primes up to \(maximumCount)")
    expectation.expectedFulfillmentCount = 25
    // when
    PrimeCalculator.calculateStreaming(upTo: maximumCount) { number in
        expectation.fulfill()
    }
    wait(for: [expectation], timeout: 3)
}

问题分析与解决方法

问题根源

  1. 异步任务未等待:calculateStreaming在全局队列异步执行,但测试闭包没有等待该任务完成就退出,导致confirmation根本没机会捕获到任何确认调用,所以报0次确认。
  2. 错误使用confirm(count:):这个方法是用来一次性指定确认次数的,不是用来累加计数器的,直接传变量会触发框架的断言断点。

方案1:改造原方法为异步序列(推荐)

将calculateStreaming改为返回AsyncStream,适配Swift并发模型,测试代码更简洁可靠:

// 改造后的PrimeCalculator
struct PrimeCalculator {
    static func streamingPrimes(upTo max: Int) -> AsyncStream<Int> {
        AsyncStream { continuation in
            DispatchQueue.global().async {
                guard max > 1 else {
                    continuation.finish()
                    return
                }
                var sieve = [Bool](repeating: true, count: max)
                sieve[0] = false
                sieve[1] = false
                for number in 2 ..< max {
                    if sieve[number] {
                        for multiple in stride(from: number * number, to: sieve.count, by: number) {
                            sieve[multiple] = false
                        }
                        continuation.yield(number)
                    }
                }
                continuation.finish()
            }
        }
    }
}

// 测试代码
@Test func testStreamingPrimesUpTo100ShouldBe25() async {
    let maximumCount = 100
    await confirmation("Calculate primes up to \(maximumCount)", expectedCount: 25) { confirm in
        for await _ in PrimeCalculator.streamingPrimes(upTo: maximumCount) {
            confirm()
        }
    }
}

方案2:不改造原方法,添加等待逻辑

如果不想修改原方法,可以用信号量等待异步任务完成:

@Test func testStreamingPrimesUpTo100ShouldBe25() async {
    let maximumCount = 100
    let completionSemaphore = DispatchSemaphore(value: 0)
    var primeCount = 0
    
    await confirmation("Calculate primes up to \(maximumCount)", expectedCount: 25) { confirm in
        PrimeCalculator.calculateStreaming(upTo: maximumCount) { _ in
            confirm()
            primeCount += 1
            if primeCount == 25 {
                completionSemaphore.signal()
            }
        }
        completionSemaphore.wait()
    }
}

关键提示

  • confirmation的闭包必须等待所有异步操作完成,否则测试会提前结束,导致确认计数不足。
  • 尽量使用Swift原生并发API(如AsyncStream)替代传统闭包回调,这是Swift Testing框架推荐的异步测试方式。

内容的提问来源于stack exchange,提问作者Javier Heisecke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 08:15:21