pointfreeco / swift-snapshot-testing

📸 Delightful Swift snapshot testing.
https://www.pointfree.co/episodes/ep41-a-tour-of-snapshot-testing
MIT License
3.81k stars 584 forks source link

Snapshotting view hierarchy throws error `UIViewControllerHierarchyInconsistency #335

Open lnfnunes opened 4 years ago

lnfnunes commented 4 years ago

I'm getting the error mentioned in the title. I could find on closed issues a similar one #310 that was closed but the error persists though, so I'm opening this new issue for that.

Bellow is a very simple test case to reproduce it:

import SnapshotTesting
import XCTest

final class SnapshotViewControllerTests: XCTestCase {

    var rootViewController: UIViewController = UIViewController() {
        didSet {
            UIApplication.shared.keyWindow?.rootViewController = rootViewController
            rootViewController.beginAppearanceTransition(true, animated: false)
        }
    }

    override func setUp() {
        super.setUp()
        rootViewController = UIViewController()
    }

    func testRootViewController() {
        assertSnapshot(matching: rootViewController, as: .image)
    }
}

Thanks in advance cc: @stephencelis @hassfers @GHMarcus

edulpn commented 4 years ago

We detected something like this too. I was calling assertSnapshot on the unwrapped keyWindow and it was giving me headaches when trying to manually changing the keyWindow.rootViewController (I noticed it was incrementing the UIApplication.shared.windows.count everytime I was calling assertSnapshot). Then I tried doing the same thing @lnfnunes, calling assertSnapshot directly to the keyWindow.rootViewController and started getting the same error.

My guess is that this framework is creating separate windows for each assertSnapshot, even if the thing we are snapshotting is already inside a window hierarchy, and it's breaking when it already is.

edulpn commented 4 years ago

I'll create an issue for my specific problem with some better info later

adammcarter commented 3 years ago

I'm still seeing this issue myself.

In my case I have a child view controller inside another view controller. Pulling out the child VC and any of it's views to be used in a snapshot test result in the same exception being raised.

My current workaround is to take my child VC and call removeFromParent() before asserting snapshots.