gpt4 book ai didi

swift - 延迟单元测试

转载 作者:行者123 更新时间:2023-11-28 13:42:13 27 4
gpt4 key购买 nike

所以我有一个单元测试来测试诊所是否每 10 秒更新一次。 5 秒后,我清除了所有诊所。然后设置 9 秒后超时的期望值,以确保诊所得到更新。这是我的代码:

func testRefresh() {

let expec = expectation(description: "Clinics timer expectation")
let expec2 = expectation(description: "Clinics timer expectation2")
expec2.isInverted = true
let dispatchGroup = DispatchGroup(count: 5)

dataStore.load()

wait(for: [expec2], timeout: 5.0) // This is what I am asking about
self.dataStore.clinicsSignal.fire([])

dataStore.clinicsSignal.subscribeOnce(with: dispatchGroup) {
print("clinics signal = \($0)")
expec.fulfill()
}

wait(for: [expec], timeout: 9.0)
XCTAssertFalse(self.dataStore.clinics.isEmpty)
}

我想延迟 5 秒。像我那样使用倒置期望是我能找到让它发挥作用的唯一方法。我只是认为使用反向期望是不好的做法。

如果我使用 sleep(5) 它会停止整个程序 5 秒。我也尝试过使用 DispatchQueue.main.asyncAfter 的解决方案,如概述 here但无济于事。

最佳答案

我有两个建议一起使用:

  • 使用 spy test double确保您的数据存储用于刷新诊所的服务被调用两次
  • 注入(inject)刷新间隔使测试更快

spy 测试替身

测试数据加载的副作用,即它命中服务,可能是一种简化测试的方法。

与其使用不同的期望并以运行时可能不会发生的方式(dataStore.clinicsSignal.fire([]))运行被测系统,您可以只计算有多少服务被命中的次数,并断言该值为 2。

注入(inject)刷新间隔

我推荐的方法是注入(inject)诊所更新频率的时间设置,然后在测试中设置一个较低的值。

毕竟,我猜您感兴趣的是更新代码按预期运行,而不是每 10 秒运行一次。也就是说,它应该按照您设置的频率更新。

您可以通过在数据存储的初始化中将该值作为默认值,然后在测试中覆盖它来实现。

我建议使用较短的刷新间隔的原因是,在单元测试的上下文中,它们运行得越快越好。您希望反馈循环尽可能快。

把它们放在一起,或多或少是这样的

protocol ClinicsService {
func loadClinics() -> SignalProducer<[Clinics], ClinicsError>
}

class DataSource {

init(clinicsService: ClinicsService, refreshInterval: TimeInterval = 5) { ... }
}

// in the tests

class ClinicsServiceSpy: ClinicsService {

private(var) callsCount: Int = 0

func loadClinics() -> SignalProducer<[Clinics], ClinicsError> {
callsCount += 1
// return some fake data
}
}

func testRefresh() {
let clinicsServiceSpy = ClinicsServiceSpy()
let dataStore = DataStore(clinicsService: clinicsServiceSpy, refreshInterval: 0.05)

// This is an async expectation to make sure the call count is the one you expect
_ = expectation(
for: NSPredicate(
block: { input, _ -> Bool in
guard let spy = input as? ClinicsServiceSpy else { return false }
return spy.callsCount == 2
),
evaluatedWith: clinicsServiceSpy,
handler: .none
)

dataStore.loadData()

waitForExpectations(timeout: .2, handler: nil)
}

如果您还使用了 Nimble要获得更精细的期望 API,您的测试可能如下所示:

func testRefresh() {
let clinicsServiceSpy = ClinicsServiceSpy()
let dataStore = DataStore(clinicsService: clinicsServiceSpy, refreshInterval: 0.05)

dataStore.loadData()

expect(clinicsServiceSpy.callsCount).toEventually(equal(2))
}

您在这种方法中所做的权衡是通过编写更多代码使测试更直接。这是否是一个好的权衡取决于您的决定。

我喜欢以这种方式工作,因为它使我系统中的每个组件都没有隐式依赖关系,而且我最终编写的测试易于阅读,并且可以作为软件的动态文档使用。

让我知道你的想法。

关于swift - 延迟单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55874328/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com