XCode 7 UITests与本地化的用户界面

在我的应用程序我使用NSLocalizedString本地化我的应用程序。 现在我想切换到UITests和哈伯testing代码是这样的:

 [tabBarsQuery.buttons["particiants"] tap]; 

这适用于英语,但其他语言失败。

 [tabBarsQuery.buttons[NSLocalizedString("PARTICIPANTS",comment:nil)] tap]; 

失败 – 可能是因为Localizable.strings在另一个包中。 我如何testing本地化的应用程序?

我想实际testingUIfunction的内容,而不仅仅是它们的存在,所以设置默认语言或使用可访问标识符将不适合。

这是build立在Volodymyr和matsoftware的答案之上的。 但是他们的答案依赖于需要在SnapshotHelper显式设置的deviceLanguage 。 此解决schemedynamic获取设备正在使用的实际支持的语言。

  1. Localizable.strings文件添加到您的UITest目标。
  2. 将以下代码添加到您的UITest目标中:

     var currentLanguage: (langCode: String, localeCode: String)? { let currentLocale = Locale(identifier: Locale.preferredLanguages.first!) guard let langCode = currentLocale.languageCode else { return nil } var localeCode = langCode if let scriptCode = currentLocale.scriptCode { localeCode = "\(langCode)-\(scriptCode)" } else if let regionCode = currentLocale.regionCode { localeCode = "\(langCode)-\(regionCode)" } return (langCode, localeCode) } func localizedString(_ key: String) -> String { let testBundle = Bundle(for: /* a class in your test bundle */.self) if let currentLanguage = currentLanguage, let testBundlePath = testBundle.path(forResource: currentLanguage.localeCode, ofType: "lproj") ?? testBundle.path(forResource: currentLanguage.langCode, ofType: "lproj"), let localizedBundle = Bundle(path: testBundlePath) { return NSLocalizedString(key, bundle: localizedBundle, comment: "") } return "?" } 
  3. 通过localizedString(key)访问方法

对于具有脚本代码的语言, localeCode将是langCode-scriptCode (例如, zh-Hans )。 否则, localeCode将是langCode-regionCode (例如, pt-BR )。 testBundle首先尝试通过localeCode来parsingtestBundle ,然后回langCode

如果仍然无法获得捆绑包,则返回“?” 对于string,所以它会失败任何查找特定string的UItesting。

选项1:设置默认语言

为UItesting创build一个新的scheme并设置默认的应用程序语言。 这将locking应用程序到一个本地化的文件,所以你可以写所有你的testing语言。

从产品 – >scheme – >pipe理scheme或⌘+,设置选项。 然后select选项选项卡并设置语言。

Xcode  - 设置默认的应用程序语言

优点 :简单,一次性更改。

缺点 :不能用于创build本地快照截图(一个工具,通过UItesting运行你的应用程序,并沿途生成App Store屏幕截图)。

选项2:为本地化string使用-accessibilityIdentifier

而不是通过显示的文本或值访问项目,请使用accessibilityIdentifier 。 这是由UItesting框架读取,但从未显示或读取给用户(即使启用了辅助function)。 在旧的UIAutomation文档中,苹果提到使用这个开发者function,这就像一个很好的用例。

然后,您可以像使用本地化版本一样继续设置accessibilityLabelaccessibilityValue

优点 :可以用于更通用的解决scheme,如采取自动截图。

缺点 :可能需要更多的工作来更改每个需要“非本地化”的标签进行testing。

您可以重新使用您的项目本地化捆绑!

当你testing消息框的行为时,你需要确切知道刚才出现的消息框。 您需要在构build阶段从另一个scheme复制您的本地化。

在您的UItesting目标 – >构build阶段 – >复制包资源,添加所需的本地化文件(例如Localizable.strings)。

添加一个类似于以下的函数:

 func localizedString(key:String) -> String { /*1*/ let localizationBundle = NSBundle(path: NSBundle(forClass: /*2 UITestsClass*/.self).pathForResource(deviceLanguage, ofType: "lproj")!) /*3*/ let result = NSLocalizedString(key, bundle:localizationBundle!, comment: "") // return result } /*1 Gets correct bundle for the localization file, see here: http://stackoverflow.com/questions/33086266/cant-get-access-to-string-localizations-in-ui-test-xcode-7 */ /*2 Replace this with a class from your UI Tests /*3 Gets the localized string from the bundle */ 

然后在你的代码中,你可以使用app.buttons [localizedString(“localized.string.key”)]

完整的文章在这里: https : //github.com/fastlane-old/snapshot/issues/321#issuecomment-159660882

到目前为止,我最简单可靠的方法是引用元素elementBoundByIndex()像这样:

  let app = XCUIApplication() let tabBar = app.tabBars tabBar.buttons.elementBoundByIndex(2).tap() app.navigationBars.buttons.elementBoundByIndex(0).tap() app.tables.cells.elementBoundByIndex(2).tap() app.tables.elementBoundByIndex(1).cells.elementBoundByIndex(0).tap() 

你可以猜测/试验这个值,find你需要的元素。

Volodymyr的答案帮了我很多,但是如果本地化包文件夹名称与快照中设置的deviceLanguage不同,它可能会失败。 这个代码片段在Swift3.0中可以正常工作,并且使用意大利语(当前语言环境是“it”,但是设备语言是“it-IT”)。

  func localizedString(key:String) -> String { let languageBundlePath = Bundle(for: PlinthUITests.self).path(forResource: deviceLanguage, ofType: "lproj") ?? Bundle(for: PlinthUITests.self).path(forResource: NSLocale.current.languageCode!, ofType: "lproj") let localizationBundle = Bundle(path: languageBundlePath!) let result = NSLocalizedString(key, bundle:localizationBundle!, comment: "") return result } 

如果你这样做的目的是运行快照(而不是实际的UItesting),那么我发现最简单的解决scheme是作弊和使用HSTestingBackchannel

这是我写的一个工具,它允许你从UITesting类发送通知给应用程序。 然后在应用程序中编写代码,直接响应通知。

除了Joe的回答之外,您还可以直接在testing代码中强制执行UItesting的语言,而无需像这样编辑计划:

 - (void)setUp { [super setUp]; self.continueAfterFailure = NO; XCUIApplication *app = [[XCUIApplication alloc] init]; app.launchArguments = @[@"-AppleLanguages", @"(en)", @"-AppleLocale", @"en_EN"]; [app launch]; }