2013-06-17 9 views
14

L'unità applicativa esegue il test di build e test durante l'esecuzione nel simulatore, ma non riesce con un errore del linker durante la creazione e il test sul dispositivo.Test unità Xcode - Errore di collegamento durante la creazione del solo dispositivo

Il mio obiettivo applicazione ho impostato le seguenti impostazioni di generazione:

DEPLOYMENT_POSTPROCESSING = NO 
GCC_SYMBOLS_PRIVATE_EXTERN = NO 

Sul mio test di unità ho impostato le seguenti impostazioni: costruire

BUNDLE_LOADER = $(BUILT_PRODUCTS_DIR)/<app name>.app/<app> 
TEST_HOST = $(BUNDLE_LOADER) 

L'errore di linker è:

Undefined symbols for architecture armv7s: 
"_<An NSString * const>", referenced from: 
     -[UnitTestClassA setUp] in UnitTestClassA.o 
"_<Another NSString * const>", referenced from: 
     -[UnitTestClassB helperMethod:] in UnitTestClassB.o 
     -[UnitTestClassB anotherHelperMethod:] in UnitTestClassB.o 
ld: symbol(s) not found for architecture armv7s 
clang: error: linker command failed with exit code 1 (use -v to see invocation) 

... Ho "continua dopo aver commesso errori" attivato nelle preferenze di Xcode, ma non ricev un sacco di errori di linker che si lamentano di NSString * const. Se sto facendo qualcosa di sbagliato, mi aspetterei più errori di collegamento rispetto a quello che sto ottenendo poiché utilizzo costanti di stringa nel mio codice di produzione.

Sto creando le mie costanti stringa in questo modo:

file h ...

extern NSString * const ReallyGoodString; 

di file .m ...

NSString * const ReallyGoodString = @"This string is great!"; 

... il .m il file è un codice di produzione e parte del mio obiettivo di applicazione e quindi non devo collegarlo al bundle di test delle unità.

Quindi, cosa sta succedendo qui? Perché funziona correttamente nel simulatore e non sul dispositivo?

Ho pubblicato un sample project to Github che illustra il problema. Nel progetto di esempio è possibile vedere che questo problema è incoerente: alcuni simboli collegano semplicemente gli altri no.

+1

Lo hai mai capito? Sto avendo lo stesso problema. Anche straniero, prima funzionava bene, e il linker si lamenta solo di una costante di stringa in un file di intestazione da cui altri simboli vengono trovati bene. –

+0

@JonGrall non l'abbiamo ancora capito – edelaney05

risposta

27

Quando il linker crea l'eseguibile Linker-Error, elimina FHKViewControllerThisSymbolWontLink perché non viene utilizzato da alcun file nell'eseguibile. Il linker non sa che dovrebbe mantenere il simbolo in giro per essere usato dal bundle test unit (che viene caricato dinamicamente in fase di runtime).

Si può dire il linker non mettere a nudo il simbolo utilizzato per codificarla con l'attributo used, in questo modo:

NSString * const FHKViewControllerThisSymbolWontLink __attribute__((used)) = @"name"; 

Sarà necessario farlo per ogni simbolo si definisce che non è utilizzato dal principale eseguibile ma viene utilizzato dalla suite di test.

1

Alcune possibilità:

  1. si importa un colpo di testa e non si collega alla libreria corretta. Questo è comune, specialmente per le intestazioni per librerie come QuartzCore poiché non è incluso nei progetti per impostazione predefinita. Per risolvere:

    A. Aggiungere le librerie corrette nella sezione Collega binari con librerie delle fasi di creazione.

  2. Si copiano i file nel progetto ma si è dimenticato di controllare la destinazione per aggiungere i file. Per risolvere:

    A. Aprire le Fasi di creazione per la destinazione corretta, espandere Fonti di compilazione e aggiungere i file .m mancanti.

  3. Se si utilizzano test di logica, non sono supportati su dispositivi iOS, ma solo nel simulatore. Tuttavia, i test delle applicazioni funzionano sui dispositivi. Documenti per che:

IOS: Sebbene Xcode può eseguire test logici e unità di applicazione in simulatori, Xcode non può eseguire test di unità logiche sui dispositivi iOS. Pertanto, se si includono e sono attivi entrambi i tipi di test unitari nello schema , non sarà possibile utilizzare tale schema per eseguire i test unitari sui dispositivi iOS .

+0

Ri: 1 - Questi simboli sono dichiarati e definiti da me nel mio codice di produzione, Ri: 2 - I file .m fanno parte del target dell'app, Re: 3 - i test delle unità sono " test di applicazione "... tutti questi sono sicuramente pensieri nella giusta direzione, grazie! – edelaney05

+0

I test di applicazione e logica sono TIPI di test unitari? Sai se stai utilizzando test di logica o applicazione? –

+0

Nella domanda si può notare che richiamo specificatamente le impostazioni del caricatore di pacchetti e del test host di Build Setting (http://developer.apple.com/library/ios/documentation/developertools/Conceptual/UnitTesting/02-Setting_Up_Unit_Tests_in_a_Project/setting_up. html # // apple_ref/doc/uid/TP40002143-CH3-SW6). Inoltre, menzionato più avanti nella domanda, ho ricreato completamente il mio problema in un nuovo progetto Xcode; i test delle applicazioni sono l'impostazione predefinita per i test delle unità in qualsiasi nuovo progetto. – edelaney05

0

Una volta ho avuto un problema simile e la soluzione era semplice come la pulizia del progetto, immagino che tu abbia già provato questo, ma forse no. Ci proverei almeno. Basta andare su "Prodotto" -> "Pulisci" nella barra di navigazione in alto, o utilizzare la scorciatoia: "shift" "command" "K"

(Avrei scritto questo come commento e non come risposta, poiché non è più un semplice suggerimento, ma non ho abbastanza punti per commentare, mi dispiace).

+0

Accidenti. Vorrei che fosse così facile. Grazie per il suggerimento! – edelaney05

+0

Hai provato ad avviare un progetto completamente nuovo e copiare tutto il codice e i dati dal tuo vecchio progetto a quello nuovo? (Un cosiddetto riavvio completo)? – Sp3kk

+0

Tipo di. Ho appena iniziato un nuovo progetto con una singola classe e una suite di test che collegava la variabile globale statica. – edelaney05

12

Ciò è probabilmente dovuto al fatto che nella suite di test sono in uso simboli non utilizzati dall'applicazione principale e Dead Code Stripping attivato. È possibile disabilitare l'opzione Dead Code Stripping in base alla configurazione. Ho risolto un problema simile per consentire ai test di eseguire sul mio dispositivo sfogliando l'opzione su No solo per le build di debug.

+0

Questa è probabilmente l'opzione migliore, poiché funzionerà per tutto il codice, non solo per le istruzioni annotate con __attribute __ ((usato)). – aceontech

Problemi correlati