我正在为我的应用程序中的一些视图/视图控制器编写单元测试。
我的应用程序使用UICollectionView,单元格包含使用kingfisher加载的图像。我正在使用FBSnapshotTestCase记录视图的图像,并将它们与已知良好的图像进行比较(顺便说一句,当我们的开发人员自己拉取请求时,使用buddybuild's CI自动运行测试,这真的很酷)。
我使用NSURLSession-Mock将预先扫描的数据(包括JSON和图像)插入到测试中。
我的问题是,似乎很难编写测试来获得用户看到的最终结果;我经常发现这一点(除非图像已经缓存--因为我在测试设置中清除了缓存,以确保测试是从干净的状态运行的!)我拍摄的所有屏幕截图都缺少图像,只显示占位符。
发布于 2017-08-30 13:55:20
我已经找到了让它可靠工作的方法,但我看不出我对自己的解决方案是否100%满意。
首先,我在didFinishLaunchingWithOptions中这样做是为了避免加载应用程序的主UI,这会在尝试为应用程序的主屏幕编写测试时造成各种混乱:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
BuddyBuildSDK.setup()
//Apply Itison UI Styles
ItIsOnUIAppearance.apply()
#if DEBUG
if let _ = NSClassFromString("XCTest") {
// If we're running tests, don't launch the main storyboard as
// it's confusing if that is running fetching content whilst the
// tests are also doing so.
let viewController = UIViewController()
let label = UILabel()
label.text = "Running tests..."
label.frame = viewController.view.frame
label.textAlignment = .center
label.textColor = .white
viewController.view.addSubview(label)
self.window!.rootViewController = viewController
return true
}
#endif然后在测试中,一旦我完成了UIViewController的设置,我需要这样做:
func wait(for duration: TimeInterval) {
let waitExpectation = expectation(description: "Waiting")
let when = DispatchTime.now() + duration
DispatchQueue.main.asyncAfter(deadline: when) {
waitExpectation.fulfill()
}
waitForExpectations(timeout: duration+1)
}
_ = viewController.view // force view to load
viewController.viewWillAppear(true)
viewController.view.layoutIfNeeded() // forces view to layout; necessary to get kingfisher to fetch images
// This is necessary as otherwise the blocks that Kingfisher
// dispatches onto the main thread don't run
RunLoop.main.run(until: Date(timeIntervalSinceNow:0.1));
viewController.view.layoutIfNeeded() // forces view to layout; necessary to get kingfisher to fetch images
wait(for: 0.1)
FBSnapshotVerifyView(viewController.view)如果我不这样做的基本问题是,只有当FBSnapshotVerifyView强制布局视图时,KingFisher才开始加载图像,并且( KingFisher通过将块分派到后台线程来加载图像,后台线程再将块分派回主线程)这太迟了-发送到主线程的块不能运行,因为主线程在FBSnapshotVerifyView()中被阻塞。如果没有对'layoutIfNeeded()‘和RunLoop.main.run()的调用,主队列的下一个测试GCD直到/ KingFisher / dispatch_async让运行循环运行才能运行,这已经太晚了。
我对我的解决方案不太满意。我不清楚为什么我需要layoutIfNeeded()两次并运行两次运行循环),所以我真的很欣赏其他的想法,但我希望这至少能帮助其他遇到同样情况的人,因为它需要一点挠头才能弄清楚发生了什么。
https://stackoverflow.com/questions/45952889
复制相似问题