Instruments Automation screenshot ignores programmatically added controls Instruments Automation screenshot ignores programmatically added controls xcode xcode

Instruments Automation screenshot ignores programmatically added controls


The problem you are seeing is because of several factors. As stated in your question, your issue is that:

  • UIAutomation screenshots will not include your styled button given the test project you have included and the automation script.

Under different conditions you see different behavior:

  • When the button is instantiated through a nib or storyboard the issue does not occur, only when it the button is declared and added to the view hierarchy in code (specifically, viewDidLoad of the view controller).

  • The button does appear in UIAutomation screenshots when run in earlier versions of iOS (i.e. iOS 8).

That said, if you remove the constraints added in viewDidLoad you will see the styled button start to appear in screenshots. This should be a hint - the constraints are part of the problem.

When the layout engine solving constraints it attempts to do as much work as possible in batches, coalescing constraints for performance. When the button and constraints are described in a nib or storyboard the constraints engine will get them all at once, and much earlier in the view hierarchy's life cycle. Because of this the steps of the layout process can be streamlined significantly.

When a constraint is added later in the view hierarchy life cycle however, the constraints need to be re-evaluated. Think of the added constraints as being added to a queue and the layout engine will re-evaluate them the next time the queue is "full". UIAutomation hooks into the UIAccessibility APIs to do it's thing - and accessibility may not know or care about what is happening to the layout of the visual representation. The visual representation may change, but not in a way that affects accessibility, and thus UIAutomation's view of the world.

iOS 9 changed several things about how the layout process works under the hood, which is why you are seeing this issue now.

There are a number of courses of action you can take:

  • Build your view hierarchy in a nib or storyboard. This will get you the most consistent experience and has performance and other advantages.

  • Use the accessibility API to hint that the position (accessibility frame) of the button has changed after the layout pass. Unfortunately you are still likely to see UIAutomation capture it while layout is occurring unless accessibility, visibility, or user interaction is disabled until layout is complete.

  • Instead of an arbitrary delay in your automation script, use the UIAutomation timeouts effectively to wait for the element to become available. This is covered in the documentation and is a best practice. Make it unavailable or invalid until layout has completed.

Using these methods I was able to easily get your example project to not reproduce the problem you are seeing. Some, or all of these solutions may be appropriate for your project - or not.


The problem with Instruments Automation likely won't be fixed.

Solution part 1: "Xcode 7 UI Tests" is the new "Instruments Automation".

Solution part 2: fastlane/snapshot is the new ui-screen-shooter. (ui-screen-shooter has been deprecated by its author and he recommends to switch to fastlane/snapshot.)

So I will turn to fastlane/snapshot and my problem will hopefully be solved.