UIView.animateWithDuration:animations:completion: 在 XCTest 中被取消
UIView.animateWithDuration:animations:completion: gets canceled in XCTest
我正在尝试对 UIView
上的扩展进行单元测试,它调用 animateWithDuration:animations:completion:
。
不幸的是,测试用例中的所有动画都会立即取消,因此完成块的 isFinished
参数始终为 false
.
有没有人知道如何让动画在测试用例中运行?
这是我的游乐场代码:
import UIKit
import XCTest
extension UIView {
func fadeOut(duration: TimeInterval, completion: ((Bool) -> Void)?) {
UIView.animate(withDuration: duration,
animations: {
self.alpha = 0.0
},
completion: { isFinished in
self.isHidden = isFinished
completion?(isFinished)
})
}
}
class UIViewTests: XCTestCase {
func testFadeView() {
// Given
let expectation = self.expectation(description: "Expect completion handler to be called.")
let view = UIView()
view.alpha = 1.0
// When
print("Date before", Date())
view.fadeOut(duration: 1.0) { (isFinished) in
print("Date completed", Date())
print("isFinished", isFinished)
expectation.fulfill()
}
// Then
wait(for: [expectation], timeout: 1.1)
XCTAssertTrue(view.isHidden) // <- this assertion always fails, cause `isFinished` inside the completion handler is always `false`.
XCTAssertEqual(view.alpha, 0.0, accuracy: CGFloat.ulpOfOne)
}
}
UIViewTests.defaultTestSuite.run()
断言XCTAssertTrue(view.isHidden)
总是失败。此外,日志语句输出:
Date before 2019-05-20 23:30:35 +0000
Date completed 2019-05-20 23:30:35 +0000
所以基本上动画会立即被杀死。
为了使用正确的标志完成动画,视图需要位于可见的 UIWindow 中。
let window = UIWindow()
window.addSubview(view)
window.isHidden = false
这样,你的测试就成功了。但是 UIKit 不会清理 window 而不在测试的最后给 运行 循环一个额外的刺激。所以添加
func tearDown() {
super.tearDown()
RunLoop.current.run(until: Date())
}
然后 window(以及其中的所有内容)将被释放。
现在它开始工作了,您可以通过减少持续时间来节省时间。我使用 duration: 0.001
将测试时间缩短到了 23 毫秒
我正在尝试对 UIView
上的扩展进行单元测试,它调用 animateWithDuration:animations:completion:
。
不幸的是,测试用例中的所有动画都会立即取消,因此完成块的 isFinished
参数始终为 false
.
有没有人知道如何让动画在测试用例中运行?
这是我的游乐场代码:
import UIKit
import XCTest
extension UIView {
func fadeOut(duration: TimeInterval, completion: ((Bool) -> Void)?) {
UIView.animate(withDuration: duration,
animations: {
self.alpha = 0.0
},
completion: { isFinished in
self.isHidden = isFinished
completion?(isFinished)
})
}
}
class UIViewTests: XCTestCase {
func testFadeView() {
// Given
let expectation = self.expectation(description: "Expect completion handler to be called.")
let view = UIView()
view.alpha = 1.0
// When
print("Date before", Date())
view.fadeOut(duration: 1.0) { (isFinished) in
print("Date completed", Date())
print("isFinished", isFinished)
expectation.fulfill()
}
// Then
wait(for: [expectation], timeout: 1.1)
XCTAssertTrue(view.isHidden) // <- this assertion always fails, cause `isFinished` inside the completion handler is always `false`.
XCTAssertEqual(view.alpha, 0.0, accuracy: CGFloat.ulpOfOne)
}
}
UIViewTests.defaultTestSuite.run()
断言XCTAssertTrue(view.isHidden)
总是失败。此外,日志语句输出:
Date before 2019-05-20 23:30:35 +0000
Date completed 2019-05-20 23:30:35 +0000
所以基本上动画会立即被杀死。
为了使用正确的标志完成动画,视图需要位于可见的 UIWindow 中。
let window = UIWindow()
window.addSubview(view)
window.isHidden = false
这样,你的测试就成功了。但是 UIKit 不会清理 window 而不在测试的最后给 运行 循环一个额外的刺激。所以添加
func tearDown() {
super.tearDown()
RunLoop.current.run(until: Date())
}
然后 window(以及其中的所有内容)将被释放。
现在它开始工作了,您可以通过减少持续时间来节省时间。我使用 duration: 0.001