2010-09-30 11 views
14

Ich habe eine iPhone iOS4.1-Anwendung, die lokalisierte Zeichenfolgen verwendet. Ich habe gerade begonnen, Komponententests mit dem SenTestingKit zu erstellen. Ich konnte viele verschiedene Arten von Werten erfolgreich testen.Unit Testing iPhone-Code, der NSLocalizedString verwendet

Ich bin nicht in der Lage richtig alle meine Code zu testen, die NSLocalizedString Anrufe verwendet, weil, wenn der Code in meinem LogicTests Ziel läuft, alle meine NSLocalizedString nur die Zeichenfolge Schlüssel Rückrufe.

Ich habe meine Localizable.strings-Datei zum LogicTests-Ziel hinzugefügt.

Meine Frage ist: Wie muss ich mein LogicTests-Ziel konfigurieren, damit Aufrufe von NSLocalizedString die lokalisierte Zeichenfolge und nicht den Zeichenfolgenschlüssel zurückgeben.

Antwort

9

Dieses Problem machte mich verrückt, aber ich war in der Lage, NSLocalizedString zu verhalten.

ZOUL war richtig, wenn Sie das MainBundle in einem logischen Test auf die Konsole drucken, ist es nicht das gleiche Paket, das Ihre Localizable.strings-Datei enthält. Sie müssen NSLocalizedString bedingt neu definieren, wenn Sie Ihre Komponententests ausführen. Ich habe es in den folgenden Schritten:

  1. Wir brauchen eine Möglichkeit zu sagen, wenn wir in unseren Logik-Tests Ziel sind, so fügen Sie so etwas wie LOGIC_TESTS auf Ihre Logik Tests Preprocessor Macros Build Einstellung des Ziels.
  2. Es gibt nur 1 Platz in meinem Code, wo ich NSLocalizedString neu definieren muss, so konnte ich den folgenden Code in der Kopfzeile entsprechend dieser Klasse platzieren. Wenn Sie dieses Problem an mehreren Stellen haben, würde ich vorschlagen, den folgenden Code in eine Kopfzeile zu setzen und #include-wo Sie es brauchen (Ich habe versucht, eine .pch-Datei, aber es funktioniert nicht in Logiktests). Wie dem auch sei, stellen Sie diesen irgendwo im Header der Klasse (n), die NSLocalizedString verwenden:

    #ifdef LOGIC_TESTS 
    #undef NSLocalizedString 
    #define NSLocalizedString(key, comment) [[NSBundle bundleWithIdentifier:@"YOUR_IDENTIFIER"] localizedStringForKey:(key) value:@"" table:nil] 
    #endif 
    

ersetzen YOUR_IDENTIFIER mit dem Bundle Identifier des Bündels Ihrer App (in Ihrer Info.plist Datei gefunden, Schlüssel ist CFBundleIdentifier). Dies setzt voraus, dass Sie in Ihrem Logic Tests-Ziel LOGIC_TESTS als Präprozessor-Makro nur definiert haben.

edit: Merkwürdiger, einmal entfernte ich einige Debug-Code diese Lösung funktioniert nicht mehr. Es sieht so aus, als müssten Sie Xcode dazu bringen, das Paket ebenfalls zu laden. Die folgende tut es:

NSString *path = @"path_to_main_bundle"; 
NSBundle *bundle = [NSBundle bundleWithPath:path]; 
NSLog(@"bundles: %@", [NSBundle allBundles]); 

Wo path_to_main_bundle== [[NSBundle mainBundle] bundlePath] ist, wenn Sie Ihr Hauptziel führen. Loggen Sie es einfach einmal in gdb ein oder verwenden Sie NSLog auf Ihrem App-Delegaten, um den Pfad zu erfassen. Es sollte ungefähr so ​​aussehen: /Users/YOUR_USER_NAME/Library/Application Support/iPhone Simulator/4.1/Applications/UUID_LOTS_OF_LETTERS_AND_NUMBERS_HERE/App.app.

Ich habe diesen Code in den Aufruf setUp für eine meiner Logik-Test-Klassen platziert. Und nein, ich habe keine Ahnung, warum ich allBundles einloggen muss, damit es funktioniert. Also, jeder, der eine Ahnung hat, lass es mich wissen!

+0

Es muss einen eleganteren Weg geben, dies zu tun, aber ich habe andere Sachen, an denen ich arbeiten muss. Ich vermute, dass die wirkliche Lösung darin besteht, einen Weg zu finden, die Bündelressourcen ohne merkwürdige Hardcoding und Introspektion zu finden. – kevboh

+0

Alter! Danke für eine so detaillierte Antwort. Dies wird eine große Hilfe sein. Ich bin überrascht, dass so wenige Leute das gefunden haben - vielleicht nicht viele Leute, die Unit-Tests lokalisieren. ;-) –

+0

Kein Problem. Ja, es ist komisch, wie ich im Interweb nichts zu diesem Problem finden konnte. Sagen Sie mir auf jeden Fall Bescheid, wenn Sie etwas anderes herausfinden. – kevboh

1

Vielleicht funktioniert NSLocalizedString nur innerhalb der Anwendungstests? Dies ist ein Makro, das localizedStringForKey:value:table: auf dem Hauptpaket aufruft. Vielleicht gibt +[NSBundle mainBundle] etwas iffy im Testziel zurück?

+0

Ich glaube, Sie sind ein zu etwas, ich bin ziemlich sicher, dass die Logik-Tests ein anderes Bündel verwenden dann das Hauptbündel. –

+0

Dies! Getestet mit Xcode 4.4 – Grav

4

ich das gleiche Problem auftritt, und dank @kevboth, ich angehen es um zwei Linien zu YourUnitTests-Prefix.pch:

#undef NSLocalizedString 
#define NSLocalizedString(key, comment) [[NSBundle bundleForClass:[self class]] localizedStringForKey:(key) value:@"" table:nil] 
+0

Beste Antwort IMHO. –

+0

Bemerkenswert: #undef NSLocalizedStringWithDefaultValue #define NSLocalizedStringWithDefaultValue (Schlüssel, Tabl, Bündel, val, Kommentar) [[NSBundle bundleForClass: [self-Klasse]] localizedStringForKey: (key) Wert: (val) Tabelle: (TBL)] –

7

konnte ich NSLocalizedString mit dem folgenden Code verwenden, in das Setup für meinen Unit-Test

- (void)setUp 
{ 
    [super setUp]; 

    NSString *bundlePath = [[NSBundle bundleForClass:[self class]] resourcePath]; 
    [NSBundle bundleWithPath:bundlePath]; 
} 
+0

Das hat gut für mich funktioniert, danke fürs Teilen! Die Verwendung von NSLocalizedStrings scheint automatisch zu funktionieren, wenn die Unit-Tests das Hauptanwendungs-Bundle (Bundle Loader-Einstellung) laden. –

+0

Danke, ich benutze GHUnit arbeitete für mich! – Denis

0

die sauberste Lösung scheint mir nur ein Localizable.strings in Ihrem octest Bündel aufzunehmen.

+2

Ich habe versucht, mein Testziel hinzuzufügen, hat aber nicht funktioniert. –

1

Eine Abkürzung für Swift: Dies ist eine einfache Version, die auf unterschiedliche Anwendungsfälle erweitert werden kann (beispielsweise bei der Verwendung von Tabellennamen).

public func NSLocalizedString(key: String, referenceClass:AnyClass) -> String 
{ 
    let bundle = NSBundle(forClass: referenceClass) 
    return NSLocalizedString(key, tableName:nil, bundle: bundle, comment: "") 
} 

Diese globale Methode kann in einer einzelnen SWIFT-Datei oder an einer anderen Stelle außerhalb des Klassenbereichs abgelegt werden. Verwenden Sie es wie folgt aus:

NSLocalizedString("YOUR-KEY", referenceClass: self) 
+1

Super! Arbeitete für mich! Vergessen Sie nicht, die .strings-Datei in Ihre Ziel-Mitgliedschaft aufzunehmen. –