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获取设备正在使用的实际支持的语言。
- 将
Localizable.strings
文件添加到您的UITest目标。 -
将以下代码添加到您的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 "?" }
-
通过
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选项选项卡并设置语言。
优点 :简单,一次性更改。
缺点 :不能用于创build本地快照截图(一个工具,通过UItesting运行你的应用程序,并沿途生成App Store屏幕截图)。
选项2:为本地化string使用-accessibilityIdentifier
而不是通过显示的文本或值访问项目,请使用accessibilityIdentifier
。 这是由UItesting框架读取,但从未显示或读取给用户(即使启用了辅助function)。 在旧的UIAutomation文档中,苹果提到使用这个开发者function,这就像一个很好的用例。
然后,您可以像使用本地化版本一样继续设置accessibilityLabel
和accessibilityValue
。
优点 :可以用于更通用的解决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]; }