2010-09-30 5 views
14

Ho un'applicazione iPhone iOS4.1 che utilizza stringhe localizzate. Ho appena iniziato a costruire test unitari usando SenTestingKit. Sono stato in grado di testare con successo molti diversi tipi di valori.Unit Testing iPhone Codice che utilizza NSLocalizedString

Non riesco a testare correttamente il mio codice che utilizza le chiamate NSLocalizedString, perché quando il codice viene eseguito nel mio obiettivo LogicTests, tutte le mie chiamate NSLocalizedString restituiscono solo la chiave stringa.

Ho aggiunto il mio file Localizable.strings alla destinazione LogicTests.

La mia domanda è: come devo configurare il mio obiettivo LogicTests in modo che le chiamate a NSLocalizedString restituiscano la stringa localizzata e non la chiave di stringa.

risposta

9

Questo problema mi stava facendo impazzire, ma ero in grado di ottenere NSLocalizedString comportarsi.

zoul aveva ragione, se si stampa il mainBundle sulla console in un test di logica, non è lo stesso pacchetto che contiene il file Localizable.strings. È necessario ridefinire in modo condizionale NSLocalizedString ogni volta che si eseguono i test unitari. L'ho fatto nelle seguenti fasi:

  1. Abbiamo bisogno di un modo per dire quando siamo nel nostro obiettivo di test logici, in modo da aggiungere qualcosa di simile LOGIC_TESTS all'impostazione Preprocessor Macros costruzione del bersaglio test logici.
  2. C'è solo 1 posto nel mio codice in cui ho bisogno di ridefinire NSLocalizedString, quindi sono stato in grado di inserire il seguente codice nell'intestazione corrispondente a quella classe. Se stai riscontrando questo problema in più punti, ti suggerisco di inserire il seguente codice in un'intestazione e #include inserendolo dove ne hai bisogno (ho provato a utilizzare un file .pch ma non funziona nei test di logica). In ogni caso, mettere da qualche parte nell'intestazione di classe (i) che utilizzano NSLocalizedString:

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

Sostituire YOUR_IDENTIFIER con il Bundle Identifier del fascio della tua app (che si trova nel file Info.plist, chiave è CFBundleIdentifier). Ciò presuppone che tu abbia definito LOGIC_TESTS come una macro preprocessore solo nel tuo obiettivo Test di logica.

modifica: Stranamente, una volta rimosso il codice di debug, questa soluzione ha smesso di funzionare. Sembra che devi ingannare Xcode anche nel caricare il pacchetto. Di seguito lo fa:

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

Dove path_to_main_bundle è == [[NSBundle mainBundle] bundlePath] quando si esegue il vostro obiettivo principale. Basta registrarlo una volta in gdb o utilizzare NSLog sul delegato dell'app per afferrare il percorso. Dovrebbe assomigliare a /Users/YOUR_USER_NAME/Library/Application Support/iPhone Simulator/4.1/Applications/UUID_LOTS_OF_LETTERS_AND_NUMBERS_HERE/App.app.

Ho inserito quel codice nella chiamata setUp per una delle mie classi di test logiche. E no, non ho idea del motivo per cui devo registrare tutti i bundle per farlo funzionare, quindi chiunque abbia un indizio, per favore fatemelo sapere!

+0

Ci deve essere un modo più aggraziato per farlo, ma ho altre cose su cui ho bisogno di lavorare. Sospetto che la vera soluzione sia trovare un modo per localizzare le risorse del bundle senza strane codifiche e introspezioni. – kevboh

+0

Amico! Grazie per una risposta così dettagliata. Questo sarà di grande aiuto. Sono sorpreso che così poche persone sembrano averlo incontrato - forse non molte persone che localizzano il test unitario. ;-) –

+0

Nessun problema. Sì, è strano come non ho trovato nulla su questo problema nell'interwebs. Sicuramente fammi sapere se pensi a qualcos'altro su questo. – kevboh

1

Forse NSLocalizedString funzionerà solo all'interno dei test dell'applicazione? Questa è una macro che richiama localizedStringForKey:value:table: nel pacchetto principale. Forse +[NSBundle mainBundle] restituisce qualcosa incerto nel target di test?

+0

Credo che tu sei uno a qualcosa, io sono abbastanza sicuro che i test logici utilizzano un fascio differente allora il fascio principale. –

+0

Questo! Testato con Xcode 4.4 – Grav

4

ho lo stesso problema, e, grazie @kevboth, I affrontare con l'aggiunta di due linee di YourUnitTests-Prefix.pch:

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

Risposta migliore IMHO. –

+0

Da segnalare: #undef NSLocalizedStringWithDefaultValue #define NSLocalizedStringWithDefaultValue (chiave, tbl, fagotto, val, commentare) [[NSBundle bundleForClass: [class auto]] localizedStringForKey: il valore (chiave): (val) tabella: (TBL)] –

7

ho potuto utilizzare NSLocalizedString utilizzando il seguente codice in la messa a punto per la mia unità di prova

- (void)setUp 
{ 
    [super setUp]; 

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

Questo ha funzionato alla grande per me, grazie per aver condiviso! L'uso di NSLocalizedStrings sembra funzionare automaticamente quando l'unità esegue il test del pacchetto principale dell'applicazione (impostazione del bundle loader). –

+0

Grazie, sto usando GHUnit ha funzionato per me! – Denis

0

la soluzione più pulita, mi sembra solo di includere un Localizable.strings nel vostro pacco OCTest.

+2

Ho provato ad aggiungere il mio target di test ma non ha funzionato. –

1

Una scorciatoia per Swift: Questa è una versione semplice che può essere estesa a diversi casi di utilizzo (per esempio con l'uso di tablenames).

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

Questo metodo globale può essere collocato in un unico file .swift o da qualche altra parte al di fuori del campo di applicazione della classe. Utilizzare in questo modo:

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

Fantastico! Ha funzionato per me! Non dimenticare di aggiungere il .strings-File nel tuo abbonamento Target. –