web-dev-qa-db-fra.com

Bibliothèques non trouvées lors de l'utilisation de CocoaPods avec des tests de logique iOS

J'essaie d'écrire des tests de logique iOS sur des classes de mon projet qui utilisent les fonctionnalités de certaines des bibliothèques de mon podspec. J'utilise le kit de tests unitaires standard fourni dans Xcode (bien que ce ne soit pas des tests d'application, mais uniquement des tests unitaires).

Par exemple, j'utilise Magical Record et cette bibliothèque est liée à mon podspec. Il est présent dans le projet Pods dans mon espace de travail et fonctionne comme prévu lorsque l'application s'exécute dans le simulateur ou sur le périphérique. Cependant, lorsque j'essaie de lier au test l'objet qui utilise Magical Record, un message d'erreur indiquant qu'il ne trouve pas les sélecteurs dans Magical Record s'affiche. J'ai essayé de mettre à jour mon HEADER_SEARCH_PATH dans mon ensemble de tests logiques, même en le codant de manière définitive dans le répertoire des en-têtes créé par CocoaPods, mais sans succès.

Je peux exécuter des tests unitaires sur des classes qui n'utilisent pas les bibliothèques CocoaPods sans problème.

Est-ce que je me trompe? Devrais-je faire quelque chose d'autre pour que le compilateur voie les bibliothèques CocoaPods?

147
Mark Struzinski

Je l'ai compris en regardant comment l'objectif principal de mon application recevait les paramètres de la bibliothèque CocoaPods. CocoaPods inclut un fichier .xcconfig nommé Pods.xcconfig. Ce fichier contient tous les chemins de recherche en-tête. 

Si vous examinez votre projet dans le navigateur de projet et que vous cliquez sur l'onglet Informations, vos configurations de construction apparaissent dans la section supérieure. Si vous ouvrez le triangle d'affichage de vos différentes configurations, les pods apparaissent sous votre cible principale. Je devais cliquer sur le menu déroulant et ajouter des pods à la cible du test de logique également.

Configurations Snapshot

Je devais également copier les paramètres de $(inherited) et ${PODS_HEADERS_SEARCH_PATHS} à partir de ma cible principale et les copier vers la cible de test logique sous Paramètres de construction/HEADER_SEARCH_PATHS. 

Enfin, j'ai dû ajouter libPods.a lors de la phase de construction du lien binaire avec bibliothèques pour ma cible de tests logiques.

J'espère que cela pourra aider quelqu'un d'autre.

173
Mark Struzinski

CocoaPods 1.0 a changé la syntaxe pour cela. Cela ressemble maintenant à ceci:

def shared_pods
    pod 'SSKeychain', '~> 0.1.4'
    ...
end

target 'Sail' do
    shared_pods
end

target 'Sail-iOS' do
    shared_pods
end

Pre CocoaPods 1.0 réponse

Ce que vous voulez utiliser est link_with de votre Podfile. Quelque chose comme:

link_with 'MainTarget', 'MainTargetTests'

Ensuite, exécutez à nouveau pod install.

223
Keith Smiley

J'ai trouvé ici une solution Tests unitaires avec CocoaPods :

Ouvrez le fichier de projet dans Xcode, puis choisissez le projet (pas la cible). Dans le panneau de droite, il existe une section intitulée Configurations. Choisissez Modules dans la colonne "Basé sur le fichier de configuration" pour votre cible de test.

enter image description here

53
Mingming

Je suis d'accord avec les autres réponses disant qu'il est nécessaire de relier les bibliothèques aux cibles de test. Cependant aucune des suggestions jusqu'ici m'a aidé. Comme @fabb écrit dans un commentaire: "lors du test, les appels isSubclassOfClass: renvoient NON où ils doivent renvoyer YES. La seule raison pour laquelle je peux expliquer cela est que les dépendances sont vraiment liées à la fois à la cible principale et à la cible de test, et lorsque la cible de test le chargeur de paquet charge le paquet principal, il ne peut pas décider quelle classe prendre. " Je reçois le même problème avec toutes les suggestions précédentes dans ce fil.

La solution à laquelle je me suis mis au travail consistait à mettre à jour mon fichier podfile afin de définir des pods spécifiques pour ma cible principale et pour ma cible de test:

target 'MyTarget' do
   pod 'AFNetworking', '~> 2.5.0'
   pod 'Mantle', '~> 1.5'
end

target 'MyTargetTests' do
   pod 'OCMockito', '~> 1.3.1'
end

Il était nécessaire de spécifier un pod pour ma cible de test même si je n'ai utilisé aucun pod spécifique au test. Sinon, CocoaPods n’insérerait pas la logique de liaison nécessaire dans mon projet.

Ce lien est ce qui m'a aidé à arriver à cette conclusion.

18
JRV

J'ai ajouté :exclusive => true pour éviter les erreurs de symbole dupliquées dans la cible de test de l'application.

target 'myProjectTests', :exclusive => true do
   pod 'OCMock', :head
   pod 'XCTAsyncTestCase', :git => 'https://github.com/iheartradio/xctest-additions.git'
end

link_with 'myProject', 'myProjectTests'

Lorsque j'ai remplacé l'objectif de test d'application par le test d'unité logique, l'erreur de l'éditeur de liens s'est produite . Après avoir supprimé :exclusive => true, tout fonctionne à nouveau.

target 'myProjectTests', do
   pod 'OCMock', :head
   pod 'XCTAsyncTestCase', :git => 'https://github.com/iheartradio/xctest-additions.git'
end

link_with 'myProject', 'myProjectTests'

:exclusive => true indique que tout ce qui est en dehors de do...end NE DOIT PAS être lié à myProjectTests, ce qui est raisonnable dans les cibles de test d'application, mais cela entraînera des erreurs de l'éditeur de liens dans les cibles de test logique.

6
Hai Feng Kao

Vous pouvez utiliser link_with selon la solution @Keith Smiley. 

Si vous avez des pods communs et des spécificités pour chaque cible, vous pouvez utiliser l’option "def" pour définir un groupe de pods. et utiliser le "def" plus tard dans la cible exclusive.

def import_pods
    pod 'SSKeychain'
end

target 'MyProjectTests', :exclusive => true do
  import_pods
end

target 'MyProject', :exclusive => true do
  import_pods
  pod 'Typhoon'
end

dans l'exemple ci-dessus, j'ai ajouté 'SSKeychain' aux deux cibles et 'Typhoon' uniquement à la cible 'MyProject'

6
Elihay

Ma solution à ce problème a été de changer mon Podfile pour inclure la bibliothèque dans les deux cibles comme celle-ci.

target "MyApp" do  
    pod 'GRMustache', '~> 7.0.2'
end

target "MyAppTests" do
    pod 'GRMustache', '~> 7.0.2'
end

Et depuis que j'utilise Swift, je devais également configurer la cible de test pour inclure le fichier MyApp-Bridging-Header.h. (Dans le groupe Compilateur Swift, sous l'onglet Paramètres de construction)

5
Qw4z1

J'ai eu un événement similaire lorsque j'ai perdu des fichiers de bibliothèque lors d'un contrôle de version. J'ai encore vu le fichier de bibliothèque dans mes pods, mais avec le code réel manquant, XCode a dit qu'il était parti. À mon grand désarroi, l'exécution de '' installation du pod '' ne rapportait pas immédiatement les fichiers perdus.

J'ai dû retirer et remplacer le pod manuellement en procédant comme suit:

  1. Supprimer la bibliothèque du fichier podfile
  2. Exécutez 'pod install' pour supprimer complètement la bibliothèque
  3. Remettez la bibliothèque dans le fichier podfile
  4. Exécutez à nouveau 'pod install'

Cela devrait remettre la bibliothèque en question dans sa forme originale. 

4
Maxwell

A partir de CocoaPods 1.x, il existe un nouveau moyen de déclarer des dépendances partagées entre une cible et la cible de test correspondante. J'avais utilisé la solution acceptée par Mark Struzinski jusqu'à présent, mais cette méthode a généré un grand nombre d'avertissements lors de l'exécution de mes tests: 

Class SomeClass is implemented in both /Path/To/Test/Target and /Path/To/App/Target. One of the two will be used. Which one is undefined.

Avec CocoaPods 1.x, nous pouvons déclarer notre cible -Test comme héritant via les chemins de recherche de la cible parent, comme suit:

target 'MyApp' do
    pod 'aPod'
    pod 'anotherPod'
    project 'MyApp.xcodeproj'
end
target 'MyAppTests' do
    inherit! :search_paths
    project 'MyApp.xcodeproj'
end

Ainsi, la cible -Test aura accès aux dépendances de la cible de l'application, sans plusieurs copies binaires. Cela a sérieusement accéléré les temps de construction des tests pour moi.

2
Darren Black

Il est également intéressant de noter que si vous avez ajouté deux fois libPods.a, vous obtiendrez une mauvaise erreur comme celle-ci:

232 duplicate symbols for architecture i386

Pour résoudre ce problème, supprimez simplement l'une des références libPods.a de votre explorateur de projet.

2
Mat Ryer

Essayez ça ça marche pour moi,

Nous devons définir des pods dans les configurations,

Le projet-> Info-> Configurations dans le projet Xcode (votre projet) doit être défini sur le projet principal "Pods" pour le débogage, la publication (et ce que vous avez d'autre). Voir "En-têtes non trouvés - chemins de recherche non inclus"

 enter image description here

J'espère que c'est une aide pour quelqu'un.

1
Jaywant Khedkar

Je travaille avec l'intégration de GoogleMaps Objective-C POD sur iOS avec mon application Swift. Le problème était donc que la cible de test ne contenait aucune référence au fichier d'en-tête de pont ( Swift_OBJC_BRIDGING_HEADER ) dans les paramètres de construction. Assurez-vous que les objectifs de votre application et de vos applications de test sont bien orientés afin que les appels d'API tiers (API de cartes, etc.) puissent être utilisés dans les tests unitaires Swift.

1
appledevguru

La syntaxe suivante donne le meilleur résultat pour moi (testé sous cocoapod v.1.2.1):

https://github.com/CocoaPods/CocoaPods/issues/4626#issuecomment-210402349

 target 'App' do
    pod 'GoogleAnalytics' , '~> 3.0'
    pod 'GoogleTagManager' , '~> 3.0'

     pod 'SDWebImage', '~>3.7'
     platform :ios, '8.0'
     use_frameworks!

     target 'App Unit Tests' do
         inherit! :search_paths
     end
 end

Sans cela, j'ai des avertissements lors du test sur les symboles en double.

Après ces avertissements ont disparu.

0
Maxim Kholyavkin

J'ai eu des problèmes avec OpenCV sous XCTest. Cela me donnait des erreurs de lieur de Undefined symbols for architecture arm64 pour des classes comme cv::Mat. J'installe OpenCV via CocoaPods en utilisant pod 'OpenCV', '~> 2.0' sous la cible principale. Peu importe la difficulté avec laquelle j'ai essayé de placer la dépendance OpenCV sous la cible de test ou d'utiliser inherit! :search_paths, rien de tout cela n'a fonctionné. La solution consistait à créer un abstract_target comme ceci:

# Uncomment the next line to define a global platform for your project
platform :ios, '6.1.6'

abstract_target 'Shows' do
  pod 'RMVision', path: '../..'
  pod 'RMShared', path: '../../../RMShared'
  pod 'OpenCV', '~> 2.0'

  target 'RMVisionSample' do
    # Uncomment the next line if you're using Swift or would like to use dynamic frameworks
    # use_frameworks!

    # Pods for RMVisionSample
  end

  target 'RMVisionSampleTests' do
    # inherit! :search_paths
    # Pods for testing
  end

  target 'RMVisionBenchmarks' do
    # inherit! :search_paths
    # Pods for testing
  end

end 

Les commandes pod deintegrate & pod clean permettent également de nettoyer le projet et de vous assurer de tout recommencer à zéro lors des tests. Vous pouvez installer ces deux en utilisant [Sudo] gem install cocoapods-deintegrate cocoapods-clean.

0
Foti Dim