We've been tracking an issue on our project where we would have intermittently failing snapshot test cases. The gist of our approach is to render a view controller's view and compare that image to a reference image to see if they're different. There are several layers to our approach here:
Our issue is that sometimes the image created by the rendered view is empty. Just a large (correct size) transparent image.
I've tested each one in isolation and determined that none of those is the problem. Instead, I've been able to reproduce this in a standalone, plain Xcode project.
By using the same approach that FBSnapshotTestCases uses to render a view, I've created a simple test. To reproduce, create a new project of the "Master-Detail" template and give the detail view controller a Storyboard ID of "Detail". Then create this simple unit test.
func testExample1() {
let storyboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
let sut = storyboard.instantiateViewControllerWithIdentifier("Detail") as UIViewController
sut.beginAppearanceTransition(true, animated: false)
sut.endAppearanceTransition()
UIGraphicsBeginImageContextWithOptions(sut.view.frame.size, false, 0)
sut.view.drawViewHierarchyInRect(sut.view.bounds, afterScreenUpdates: true)
let image = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
let data = UIImagePNGRepresentation(image)
println("byte length: \(data.length)")
}
Nothing too fancy, and it will most likely pass. But, if you duplicate the code a few more times:
func testExample1() { ... }
func testExample2() { ... }
func testExample3() { ... }
The output is very strange (truncated):
Test Suite 'All tests' started at 2014-10-02 07:46:52 +0000
byte length: 27760
byte length: 17645
byte length: 27760
Test Suite 'All tests' passed at 2014-10-02 07:55:29 +0000.
Executed 3 tests, with 0 failures (0 unexpected) in 517.778 (517.781) seconds
The byte lengths should be identical, but they're not. The second test (and sometimes the third) will have an empty view, just like our problem.
A sample project demonstrating the problem is available here.
I was able to reproduce the issue using an Objective-C test project, so it's unlikely that it's a Swift problem. In past projects, we haven't used Storyboards for our view controller UI, so it's possible that there is an extra step necessary in order to "force" the view to load. It's also possible that this is an Xcode 6.x or iOS 8 issue (I've reproduced the problem with Xcode 6.0.1).
Has anyone experienced an issue like this, where rendered images of views from controllers loaded from Storyboards have been transparent?