7

I'm trying to test my iOS app using XCTestCase in different orientations. I need a way to programmatic way to change the orientation. I tried doing this in 2 methods, but both didn't change the orientation (orientation remained as UIInterfaceOrientationPortrait).

Attempt 1

[UIApplication sharedApplication].statusBarOrientation = UIInterfaceOrientationLandscapeLeft;`

Attempt 2

[[UIDevice currentDevice] setValue:[NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft] forKey:@"orientation"];`

When I read [[UIApplication sharedApplication] statusBarOrientation] Is there another way to change the orientation for testing purposes?

4 Answers4

9

Swift code:

XCUIDevice.shared.orientation = UIDeviceOrientation.portrait;
Dmytro
  • 1,290
  • 17
  • 21
6

use below solution. Do it in setup method.

[[UIDevice currentDevice] setValue:
                      [NSNumber numberWithInteger: UIInterfaceOrientationPortrait]
                            forKey:@"orientation"];

its working for me.

2

This should work, I am changing the orientation randomly because I am running several tests, I hope this is useful

        // Set a random device orientation
    let orient = [UIDeviceOrientation.portrait , UIDeviceOrientation.portraitUpsideDown, UIDeviceOrientation.landscapeLeft, UIDeviceOrientation.landscapeRight]
    XCUIDevice.shared().orientation = orient[Int(arc4random_uniform(UInt32(orient.count)))]
  • error: Cannot call value of non-function type 'XCUIDevice' – Corbin Miller May 21 '19 at 23:58
  • using random variables in tests like this is never a good idea. A test case should be deterministic. If you need tests for all orientations, then run them for all orientations – j0h4nn3s Jul 25 '22 at 14:50
1

If you want to run device rotating tests within the XCTest environment, my currently best known strategy is:

  • In Simulator, make sure the Rotate Device Automatically option is set.
  • Create an XCTest Host application and make sure its info.plist Supported interface orientations section is fully removed (you can't do that in your production app as the appStore will reject it.)
  • In the host application delegate implement -application:supportedInterfaceOrientationsForWindow: and return UIInterfaceOrientationMaskAll. This will effectively replace the former info.plist entries.
  • Then within your tests, call the private [UIDevice.currentDevice setValue:@(UIDeviceOrientation…) forKey:@"orientation"]; at need
  • This animates, so wait until all windows have changed their orientation by checking their frames and then continue your testing.
  • To speed up animations in tests, set window.layer.speed = 100. This makes the animations 100 times faster and hopefully your tests too.
berbie
  • 978
  • 10
  • 13
  • 2
    This answer helped me a lot, thanks! Not sure why it was downvoted. This is the only answer that correctly answers the question, which was for unit tests, not UI tests. One more tip... if you want to make this work on CI and need for "Rotate Device Automatically" to always be set, you can use `defaults write com.apple.iphonesimulator RotateWindowWhenSignaledByGuest true`. – Steven Peterson Nov 30 '19 at 21:34