8

Is there a way to switch an XCTest unit test into the right-to-left mode to test Arabic version of the app where sentences are written from right to left of the screen? My app code logic behaves differently based on language direction. I would like to verify this functionality in a unit test. What I need to do is to switch the app into the right-to-left language mode from an XCTest unit test case.

One can run the app in the right-to-left mode by changing the Scheme's Application language settings to Right-to-left Pseudolanguage. Is there a way to do similar thing in a unit test?

My imperfect solution

I ended up changing semanticContentAttribute of a view under test to .ForceRightToLeft. It does what I need to do. It does not feel like a very clean approach though. Firstly, it only works in iOS 9. Secondly, it looks like I am tinkering with my app views on a low level from the unit test. Instead, I would prefer to switch the whole app's language to right-to-left if it is possible.

class MyTests: XCTestCase {
  func testRightToLeft() {
    if #available(iOS 9.0, *) {
      let view = UIView()
      view.semanticContentAttribute = .ForceRightToLeft
      // Test code involving the view
    }
  }
}
Evgenii
  • 36,389
  • 27
  • 134
  • 170

4 Answers4

3

There's no easy way to do this right now with testing/UI testing besides passing in environment flags or setting the semanticContentAttribute as you are doing now. Filing a bug to Apple is highly recommended.

wakachamo
  • 1,723
  • 1
  • 12
  • 18
3

You can also change the device language & region in the scheme. This means you'll need separate schemes for the various LTR/RTL tests you want to run:

Xcode language & region settings

Xcode even provides pseudo-languages for extra-long string & RTL testing.

Brian Gerstle
  • 3,643
  • 3
  • 22
  • 22
  • Thanks, I have already mentioned this in the question. It does not affect unit tests unfortunately. – Evgenii Sep 16 '15 at 00:14
0

What you are looking for is Automated UI-Testing

This example JavaScript code changes the device orientation for example:

var target = UIATarget.localTarget();
var app = target.frontMostApp();
//set orientation to landscape left
target.setDeviceOrientation(UIA_DEVICE_ORIENTATION_LANDSCAPELEFT);
UIALogger.logMessage("Current orientation now " + app.interfaceOrientation());
//reset orientation to portrait
target.setDeviceOrientation(UIA_DEVICE_ORIENTATION_PORTRAIT);
UIALogger.logMessage("Current orientation now " + app.interfaceOrientation());

For testing, if your layout has changed to RTL or LTR you could try to access specific UI Elements and check their content against an expected content. So here is another example to check the contents of a TableViewCell from the official docs:

The crux of testing is being able to verify that each test has been performed and that it has either passed or failed. This code example runs the test testName to determine whether a valid element recipe element whose name starts with “Tarte” exists in the recipe table view. First, a local variable is used to specify the cell criteria:

var cell = UIATarget.localTarget().frontMostApp().mainWindow() \
.tableViews()[0].cells().firstWithPredicate("name beginswith 'Tarte'");

Next, the script uses the isValid method to test whether a valid element matching those criteria exists in the recipe table view.

if (cell.isValid()) {
  UIALogger.logPass(testName);
} else {
  UIALogger.logFail(testName);
}

If a valid cell is found, the code logs a pass message for the testName test; if not, it logs a failure message.

Notice that this test specifies firstWithPredicate and "name beginsWith 'Tarte'". These criteria yield a reference to the cell for “Tarte aux Fraises,” which works for the default data already in the Recipes sample app. If, however, a user adds a recipe for “Tarte aux Framboises,” this example may or may not give the desired results.

If you want to test a specific scheme:

Executing an Automation Instrument Script in Xcode After you have created your customized Automation template, you can execute your test script from Xcode by following these steps: Open your project in Xcode. From the Scheme pop-up menu (in the workspace window toolbar), select Edit Scheme for a scheme with which you would like to use your script. Select Profile from the left column of the scheme editing dialog. Choose your application from the Executable pop-up menu. Choose your customized Automation Instrument template from the Instrument pop-up menu. Click OK to approve your changes and dismiss the scheme editor dialog. Choose Product > Profile. Instruments launches and executes your test script.

ezcoding
  • 2,974
  • 3
  • 23
  • 32
  • Thanks, if I understood you correctly you are suggesting to test **device orientation changes** (portrait and landscape). If so, this is not what I am asking. I need a way to switch the test into the right-to-left language layout, to test languages like Arabic where the text is written from right to left. – Evgenii Aug 02 '15 at 06:51
  • 1
    Yes, that was just some example code. You can however check, if a UILabel is in the right position and if it shows the right content. This is done via `UI Testing` – ezcoding Aug 02 '15 at 06:53
  • Ok, so how can I switch this UI test into the right-to-left language mode, it is not very clear from the examples you provided, sorry. – Evgenii Aug 02 '15 at 06:57
  • 1
    I think that schemes apply to your test targets as well. Just try it! I don't know a lot about schemes, but I remember reading that you choose the targets for schemes. – ezcoding Aug 02 '15 at 07:15
  • Thanks, but unfortunately changing the language to Arabic in the test scheme still runs the app in the left-to-right mode. See my conversation in the answer by Carsten Witzke. – Evgenii Aug 02 '15 at 07:18
  • 1
    Ok. Why not pick a certain simulator - let's say the iphone 5 - and set it's language to arabic manually? And if you run your UI Tests, you always pick that specific simulator. I've edited my answer specific to schemes. – ezcoding Aug 02 '15 at 07:43
0

You can detect the writing direction via

let writingDirection = UIApplication.sharedApplication().userInterfaceLayoutDirection
switch writingDirection {
case .LeftToRight:
    //
case .RightToLeft:
    //
default:
    break // what now? You are obviously using iOS 11's topToBottom direction…
}

To set different languages and locales on startup this might be a proper solution.

Community
  • 1
  • 1
Carsten
  • 1,029
  • 14
  • 29
  • Thanks, I am not asking how to **detect** right-to-left language but rather how to switch the app into the right-to-left language mode form the unit test. Sorry if my question was not very clear. – Evgenii Aug 02 '15 at 06:53
  • 1
    The first thing that comes to my mind is this [SO answer](http://stackoverflow.com/questions/1669645/how-to-force-nslocalizedstring-to-use-a-specific-language/20257557#20257557). But it's most likely more an issue of the start parameters of the test suite itself. – Carsten Aug 02 '15 at 06:58
  • Thanks for idea: created new schema for the SCTest with Arabic language selected in its **Application language** setting. When I run the unit test the app still detects left-to-right language. – Evgenii Aug 02 '15 at 07:09
  • 1
    Ok, editing the **Run** phase does not affect the **Test** phase – stupid me. Let's see if we have more options on the command line… [Like this?](http://stackoverflow.com/questions/31428132/how-to-launch-ios-simulator-in-specific-language-from-command-line) – Carsten Aug 02 '15 at 07:12