If I create and show controllers programmatically, directly to control functions, when I check the On Top controller, I always get the Storyboard Root controller instead of the controller, which I just have created an instance, as if manually created controllers are never added to the application hierarchy .
What you say here is true, they are not added. In your pseudo code, all you did was create some view controllers and push them against each other.
Why do you expect them to be in the application hierarchy? You never added them there.
There are two problems here, and this is only the first.
The second problem:
UIApplication.sharedApplication().keyWindow?.rootViewController
This code captures the root view controller, which is actually the one that is at the very bottom (assuming that the "top" means more visible). When you use a storyboard, it will almost always be the initial controller.
That way, even if you add new view hierarchies to the hierarchy, the test you do will still fail.
Proposed solution
As a simple test, you donβt need to verify that your new view controller is on top of the visual hierarchy. For this you need to add it there.
All you really need to check is "If I push my view controller onto this newly created navigation stack, it should be at the top of this stack (visible)"
Thus, your test does not depend on the state of the application or other controllers in the hierarchy.
Pseudocode:
func testController(){ // Instantiate a controller let storyBoard:UIStoryboard = UIStoryboard(name: "Main", bundle: NSBundle(forClass: self.dynamicType)) let controller1 = storyBoard.instantiateViewControllerWithIdentifier("Controller1") as? ControllerOneViewController controller1.loadView() // Call a function that instantiates another controller controller1.pushAnotherController() // Test that the current shown controller is what we expect... let nav = controller1.navigationController! //Assuming it embedded in one XCTAssert(nav.visibleViewController.self == TheExpectedClass, "Controller is not what we expect") }