swift-snapshot-testing
swift-snapshot-testing copied to clipboard
Snapshot is different with what's in simulator window (even with delay)
Hi there, first of thank you for making such an awesome library!
The issue I struggled with is that I can't understand why the snapshot is different from what is on the screen
Heres the simulator's:

and here's the snapshot:

the only thing that makes a difference is that update
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) {
self.contentView.backgroundColor = .red
self.label.textColor = .yellow
self.setNeedsDisplay()
self.setNeedsLayout()
}
Test
class SnapshotAfterUpdateTests: XCTestCase {
private var sut = UIStoryboard(
name: "Main",
bundle: Bundle(for: ViewController.self)
).instantiateInitialViewController()!
func testExample1() {
delay(2) // here's a delay
assertSnapshot(matching: sut, as: .image)
}
}
func delay(_ second: TimeInterval) {
let date = Date(timeIntervalSinceNow: second)
RunLoop.current.run(until: date)
}
full project to reproduce: https://github.com/MaximBazarov/SnapshotAfterUpdate
Have you tried using the "wait" strategy?
Instead of:
delay(2) // here's a delay
assertSnapshot(matching: sut, as: .image)
It would be (I think, no compiler helping here...):
assertSnapshot(matching: sut, as: .wait(for: 2, on: .image))
@Sherlouk thank you for the answer, I couldn't find that strategy though.
what fixed this for me is
sut.view.setNeedsDisplay()
delay(0.1)
assertSnapshot(matching: sut, as: .image)
but doesn't seem to be an elegant solution, also I don't think it's even a snapshot-testing framework problem, because when debug sut is in the state as on a screenshot, so somehow it doesn't get rendered by the time
I couldn’t find that strategy though
Perhaps you are not on the latest version? Or it hasn’t been released in a tagged build (try using master rather than a version!)
@Sherlouk yes, it's in master.
so the result is the same, but doesn't solve the problem alone
func testExample1() {
sut.view.setNeedsDisplay() // that line has to be here, no idea why yet
assertSnapshot(matching: sut, as: .wait(for: 2, on: .image))
}
Not sure if I'm doing something wrong, but even when I use .wait, it only loads the viewController after the specified time interval.
Let's say I start an animation of 0.3 seconds in the viewDidAppear. How can I make the snapshot wait for this 0.3 seconds?
@MaximBazarov I just ran into a similar issue and noticed that asserting using UIViewController will never update. No matter how long you tell the .wait expectation to wait. On the other hand, asserting using UIView works flawlessly. I tried your project and assertSnapshot(matching: sut.view, as: .wait(for: 2, on: .image)) generates the expected screenshot.
@matheusalano you'll find this approach useful as well. Assert the view controller's view using the .wait strategy and you should be fine.