web-dev-qa-db-fra.com

UITcode Xcode 7 avec interface utilisateur localisée

Dans mon application, j'utilise NSLocalizedString pour localiser mon application. Maintenant, je veux passer à UITests et avoir Testcode comme ceci:

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

Cela fonctionne pour l'anglais mais échoue pour les autres langues.

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

Echec - probablement parce que Localizable.strings est dans un autre lot. Comment puis-je tester une application localisée?

25
netshark1000

Je voulais réellement tester le contenu des fonctionnalités de l'interface utilisateur et pas seulement leur existence, donc définir une langue par défaut ou utiliser les identificateurs d'accessibilité ne conviendrait pas.

Cela s'appuie sur les réponses de Volodymyr et matsoftware . Cependant, leurs réponses reposent sur deviceLanguage qui doit être explicitement défini dans SnapshotHelper. Cette solution récupère de manière dynamique la langue actuellement prise en charge par le périphérique.

  1. Ajoutez les fichiers Localizable.strings à votre cible UITest.
  2. Ajoutez le code suivant à votre cible 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. Accéder à la méthode par localizedString(key)

Pour les langues avec un code de script, la localeCode sera langCode-scriptCode (par exemple, zh-Hans). Sinon, la localeCode sera langCode-regionCode (par exemple, pt-BR). testBundle tente d’abord de résoudre le problème de lproj de localeCode, puis retombe à langCode.

S'il ne peut toujours pas obtenir le paquet, il retourne "?" pour la chaîne, il échouera donc tous les tests d'interface utilisateur qui recherchent des chaînes spécifiques.

8
SeanR

Option 1: Legen Sie eine Standardsprache fest

Voir plus de détails Schéma pour les essais de formation de stagiaires et pour les célébrations du festival. Voir l'appli dans les dates les plus récentes, les tests de qualité pour les tests de performance, les tests de sécurité.

Stellen Sie die Option unter Produkt -> Schema -> Schemas verwalten oder ein⌘⇧,. En savoir plus sur les options de commande et de retour pour les ordinateurs.

Xcode - Set the Default Application Language

Vorteile : Einfache, einmalige Änderung.

Nachteile : Captures d'écran capturées Captures d'écran mit Schnappschuss (outil simple, avec application supplémentaire et tests UI-test ausgeführt und der App Store généré par le Web) verwendet werden Screenshots auf dem Weg).

Option 2: Verwenden Sie -accessibilityIdentifier für lokalisierte Zeichenfolgen

Verwenden Sie accessibilityIdentifier, anstatt über den angezeigten Texte ou Signification du contenu. Meurs wird vom UI Testing-Framework gelesen, aber niemals Benutzern angezeigt oder vorgelesen (Auch bei aktivierter Eingabehilfe). Dans tous les domaines, Apple meurt pour le monde des affaires, a été tuée par le gouvernement.

Anschließend können Sie accessibilityLabel und accessibilityValue wie gewohnt mit den lokalisierten Versionen festlegen.

Vorteile : Cliquez ici pour afficher le texte intégral, cliquez ici. B. für automatisierte Screenshots.

Nachteile : Mes connaissances, mes références, ses notes, ses notes, ses notes, ses notes, ses notes.

24
Joe Masilotti

VOUS POUVEZ RÉUTILISER VOS GROUPES DE LOCALISATION DE PROJET!

Lorsque vous testez le comportement des boîtes de message, vous devez savoir exactement quelle boîte de message vient d'apparaître. Vous devez copier votre localisation à partir d'un autre schéma pendant la phase de construction.

Dans votre cible Tests d’interface utilisateur -> Phases de construction -> Copier les ressources d’un ensemble, ajoutez les fichiers de localisation nécessaires (par exemple, Localizable.strings).

Ajoutez une fonction similaire à celle-ci:

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 */

Ensuite, dans votre code, vous pouvez utiliser app.buttons [localizedString ("localized.string.key")]

L'article complet est ici: https://github.com/fastlane-old/snapshot/issues/321#issuecomment-159660882

11

Jusqu'à présent, le moyen le plus simple et le plus fiable consiste à référencer des éléments avec elementBoundByIndex () Comme ceci: 

    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()

Vous pouvez deviner/expérimenter avec ces valeurs et trouver les éléments dont vous avez besoin.

6
Vladimir Shutyuk

La réponse de Volodymyr m'a beaucoup aidé, mais elle peut échouer si le nom du dossier de l'ensemble de localisation est différent de deviceLanguage défini dans Snapshot. Cet extrait fonctionne bien pour moi dans Swift 3.0 et dans des langues telles que l'italien (les paramètres régionaux sont "it", mais la langue de l'appareil est "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
}
2
matsoftware

Si vous faites cela dans le but d'exécuter Snapshot (plutôt que de tester l'interface utilisateur), la solution la plus simple est de tricher et d'utiliser HSTestingBackchannel

C'est un outil que j'ai écrit qui vous permet d'envoyer des notifications de la classe UITesting à l'application. Vous écrivez ensuite un code dans l'application qui répond directement aux notifications.

0
Confused Vorlon

La réponse de SeanR est excellente (+1), mais il y a une amélioration mineure: 

Si vous utilisez la localisation de base, il est possible que votre Localizable.strings ne soit pas localisé dans votre langue de base. Ce n'est pas nécessaire car la langue de base serait utilisée dans ce cas. Si tel est le cas, la fonction localizedString de SeanR renverra „?“

La version étendue ci-dessous vérifie également la langue de base et renvoie la chaîne localisée dans la langue de base: 

func localizedString(_ key: String) -> String {
    let testBundle = Bundle(for: ShopEasyUITests.self)
    guard let currentLanguage = currentLanguage else { return "?" }
    if let testBundlePath = testBundle.path(forResource: currentLanguage.localeCode, ofType: "lproj"),
        let localizedBundle = Bundle(path: testBundlePath) {
        return NSLocalizedString(key, bundle: localizedBundle, comment: "")
    }
    if let testBundlePath = testBundle.path(forResource: currentLanguage.langCode, ofType: "lproj"),
        let localizedBundle = Bundle(path: testBundlePath) {
        return NSLocalizedString(key, bundle: localizedBundle, comment: "")
    }
    if let testBundlePath = testBundle.path(forResource: "Base", ofType: "lproj"),
        let localizedBundle = Bundle(path: testBundlePath) {
        return NSLocalizedString(key, bundle: localizedBundle, comment: "")
    }
    return "?"
}
0
Reinhard Männer

Solution Objective-C: Inspirée de la solution @Volodymyr Prysiazhniuk

- (NSString*)getLocalizedStringForKey :(NSString*)stringKey forUITestClass : (id) uiTestClass{
    if (!stringKey || !uiTestClass){
        return nil;
    }
    NSString *bundlePath = [[NSBundle bundleForClass: uiTestClass]bundlePath];
    NSBundle* bundle = [NSBundle bundleWithPath:bundlePath];
    NSString* localizedString = NSLocalizedStringWithDefaultValue(stringKey, nil, bundle, nil, nil);
    return localizedString;
}
0
Skander Fathallah

En plus de la réponse de Joe, vous pouvez également forcer le langage pour les tests d'interface utilisateur directement dans le code de test sans modifier un schéma comme celui-ci:

- (void)setUp
{
    [super setUp];

    self.continueAfterFailure = NO;
    XCUIApplication *app = [[XCUIApplication alloc] init];
    app.launchArguments = @[@"-AppleLanguages", @"(en)", @"-AppleLocale", @"en_EN"];
    [app launch];
}
0
Leszek Szary

Pour la fonction d'instantané de fastlane, SnapshotHelper.Swift lance l'application avec ces arguments. Donc, en interprétant ces valeurs, cette solution est déterministe et j'ai été capable de produire des instantanés corrects pour plusieurs langues:

func getLocale(str: String) -> String {
    let start = str.index(str.startIndex, offsetBy: 1)
    let end = str.index(start, offsetBy: 2)
    let range = start..<end

    var locale = str.substring(with: range)
    if locale == "en" {
        return "Base"
    }
    return locale
}

func localizedString(_ key: String) -> String {
    print("app.launchArguments \(app.launchArguments)")
    guard let localeArgIdx = app.launchArguments.index(of: "-AppleLocale") else {
        return ""
    }
    if localeArgIdx >= app.launchArguments.count {
        return ""
    }
    let str = app.launchArguments[localeArgIdx + 1]
    let locale = getLocale(str: str)
    let testBundle = Bundle(for: Snapshot.self)
    if let testBundlePath = testBundle.path(forResource: locale, ofType: "lproj") ?? testBundle.path(forResource: locale, ofType: "lproj"),
        let localizedBundle = Bundle(path: testBundlePath)
    {
        return NSLocalizedString(key, bundle: localizedBundle, comment: "")
    }
    return ""
}

J'espère que cela t'aides

0
tsuz