Bibliotheken wurden bei Verwendung von CocoaPods mit iOS-Logiktests nicht gefunden

148

Ich versuche, einige iOS-Logiktests für Klassen in meinem Projekt zu schreiben, die Funktionen aus einigen Bibliotheken in meiner Podspec verwenden. Ich verwende das in Xcode bereitgestellte Standard-Unit-Test-Bundle (obwohl keine Anwendungstests, sondern nur Unit-Tests).

Zum Beispiel verwende ich Magical Record und habe diese Bibliothek in meiner Podspec verlinkt. Es ist im Pods-Projekt in meinem Arbeitsbereich vorhanden und funktioniert wie erwartet, wenn die App im Simulator oder auf dem Gerät ausgeführt wird. Wenn ich versuche, das Objekt, das Magical Record verwendet, mit dem Test zu verknüpfen, wird jedoch ein Linkerfehler angezeigt, der besagt, dass die Selektoren von Magical Record nicht gefunden werden können. Ich habe versucht, mein HEADER_SEARCH_PATH in meinem Logiktest-Bundle zu aktualisieren und es sogar hart in das von CocoaPods erstellte Header-Verzeichnis zu codieren, aber kein Glück.

Ich kann problemlos Unit-Tests für Klassen ausführen, die keine CocoaPods-Bibliotheken verwenden.

Mache ich das falsch? Sollte ich etwas anderes tun, damit der Compiler die CocoaPods-Bibliotheken sieht?

Mark Struzinski
quelle

Antworten:

224

CocoaPods 1.0 hat die Syntax dafür geändert. Es sieht jetzt so aus:

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 Antwort

Was Sie verwenden möchten, ist link_withvon Ihrem Podfile. Etwas wie:

link_with 'MainTarget', 'MainTargetTests'

Dann pod installwieder laufen .

Keith Smiley
quelle
7
Dies hat das Problem für mich sofort behoben.
MTTRB
9
Ich bekomme dabei seltsame Fehler - beim Testen isSubclassOfClass:kehren Anrufe dorthin zurück, NOwo sie zurückkehren sollen YES. Der einzige Grund, warum ich dies erklären kann, ist, dass die Abhängigkeiten tatsächlich sowohl mit dem Haupt- als auch mit dem Testziel verknüpft werden. Wenn der Bundle Loader des Testziels das Hauptpaket lädt, kann er nicht entscheiden, welche Klasse verwendet werden soll.
Fabb
4
Ich habe das gleiche Problem mit der isKindOfClass:Rückkehr, NOwenn es zurückkehren sollte YES. Wenn ich den Zeiger auf das ClassObjekt, das ich teste, und das Classder Klasse, mit der ich vergleichen möchte, protokolliere, sind dies zwei verschiedene Werte. Offensichtlich verwendet mein Code aus dem App-Bundle ein anderes Symbol für die Klasse als der Code aus meinen Unit-Tests. Hat jemand einen Weg gefunden, dies zu lösen?
Nicholas Hart
2
Ich denke nicht, dass dies ein guter Weg ist, da einige andere Fehler erwähnt haben. Bleiben Sie beim Aktualisieren der Konfigurationsdatei 'basierend auf' Bit. Stellen Sie sicher, dass Sie libPods.a nicht zweimal verlinkt haben.
Bob Spryn
3
Dies sollte die akzeptierte Antwort sein, da dies der offizielle Weg von CocoaPods ist, Pods mit mehreren Zielen einzurichten. Vielen Dank Keith!
Cschuff
174

Ich habe dies herausgefunden, indem ich mir angesehen habe, wie das Hauptziel meiner App darin bestand, Einstellungen von der CocoaPods-Bibliothek zu erhalten. CocoaPods enthält eine .xcconfig-Datei mit dem Namen Pods.xcconfig. Diese Datei enthält alle Header-Suchpfade.

Wenn Sie sich Ihr Projekt im Projektnavigator ansehen und auf die Registerkarte Info klicken, werden Ihre Build-Konfigurationen im oberen Bereich aufgelistet. Wenn Sie das Offenlegungsdreieck für Ihre verschiedenen Konfigurationen öffnen, werden Pods unter Ihrem Hauptziel aufgelistet. Ich musste auf das Dropdown-Menü klicken und dem logischen Testziel auch Pods hinzufügen.

Konfigurations-Snapshot

Ich musste auch die Einstellungen von $(inherited)und ${PODS_HEADERS_SEARCH_PATHS}von meinem Hauptziel kopieren und sie unter Build-Einstellungen / HEADER_SEARCH_PATHS auf das logische Testziel kopieren.

Schließlich musste ich libPods.a in der Build-Phase Link Binary with Libraries für mein Ziel für Logiktests hinzufügen.

Hoffe, dies kann jemand anderem helfen.

Mark Struzinski
quelle
Brillant! Ich benutze MagicalRecord sowie OCMockito und OCHamcrest für Unit-Tests. Mit diesem Fix kann ich sie jetzt alle über CocoaPods installieren! Vielen Dank!
Fogmeister
4
Das hat bei mir funktioniert, danke. HINWEIS .. Ich musste die libPods.a nicht sowohl zum Testprojekt als auch zum Hauptprojekt hinzufügen. Dies verursacht einen doppelten Symbolfehler
Craig Bruce
Für mich musste ich auch die "Benutzerdefinierten" Build-Einstellungen kopieren. Die Header-Suchpfade beziehen sich auf $ PODS_ROOT, das nicht auf dem Testziel definiert wurde. Sie können es hinzufügen, indem Sie zu Editor-> Build-Einstellung hinzufügen-> Benutzerdefinierte Einstellung hinzufügen und dann den Wert $ PODS_ROOT vom Hauptziel kopieren.
Shinigami
11
Dies ist nicht der richtige Weg, um dies zu beheben. Siehe Antwort mit link_with. Sie können auch verschiedene Pods pro Ziel in Ihrer Pod-Datei angeben , dh nur OCMockito in Ihr Testziel aufnehmen.
Dbainbridge
Ja Ja Ja! Vor dieser Antwort musste ich das Testziel aus meinen Projekten löschen! Danke Mann :)
Josip B.
53

Es gibt eine Lösung, die ich hier gefunden habe. Unit-Tests mit CocoaPods :

Öffnen Sie die Projektdatei in Xcode und wählen Sie dann das Projekt (nicht das Ziel) aus. Im rechten Bereich befindet sich ein Abschnitt namens Konfigurationen. Wählen Sie Pods in der Spalte "Basierend auf Konfigurationsdatei" für Ihr Testziel.

Geben Sie hier die Bildbeschreibung ein

Mingming
quelle
Was ist, wenn es testspezifische Abhängigkeiten gibt, Spectadie Sie mit dem Testprojekt verknüpfen möchten, aber nicht mit dem Hauptprojekt? : S
Fatuhoku
Dies hat funktioniert und erfordert keine Änderungen an der Pod-Konfiguration oder am Setup ... Ausgezeichnete Lösung.
Richard
1
Obwohl diese Lösung einen Fehler verursachen kann: Class Foo is implemented in both MyApp and MyAppTestCase. One of the two will be used. Which one is undefined. Dies scheint durch einen Fehler in Cocoapods verursacht zu sein; siehe @ JRV Antwort unten.
Richard
Das sind nicht nur Warnungen. Mit einem solchen Setup werden keine richtigen Xcode-Code-Abdeckungsdaten generiert und Unit-Tests hängen in den meisten Fällen nur während des Starts.
i4niac
Ich habe das Estimote SDK manuell per Drag & Drop importiert. Ich erhalte keine Pods. Wie kann ich das beheben?
Guru Teja
18

Ich stimme den anderen Antworten zu und sage, dass es notwendig ist, die Bibliotheken mit den Testzielen zu verknüpfen. Keiner der bisherigen Vorschläge hat mir jedoch geholfen. Wie @fabb in einem Kommentar schreibt: "Beim Testen geben isSubclassOfClass:Aufrufe NEIN zurück, wo sie JA zurückgeben sollten. Der einzige Grund, warum ich dies erklären kann, ist, dass die Abhängigkeiten wirklich sowohl mit dem Haupt- als auch mit dem Testziel verknüpft werden und wenn das Paket des Testziels Der Loader lädt das Hauptpaket und kann nicht entscheiden, welche Klasse er nehmen soll. " Ich habe das gleiche Problem mit allen vorherigen Vorschlägen in diesem Thread.

Die Lösung, die ich zur Arbeit bekam, bestand darin, meine Poddatei zu aktualisieren, um bestimmte Pods für mein Hauptziel und mein Testziel zu definieren:

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

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

Es war notwendig , einen Pod für mein Testziel anzugeben, obwohl ich keine testspezifischen Pods verwendet habe. Andernfalls würde CocoaPods nicht die erforderliche Verknüpfungslogik in mein Projekt einfügen.

Dieser Link hat mir geholfen, zu diesem Schluss zu kommen.

JRV
quelle
1
Vielen Dank für den Link zum CocoaPods-Problem - das hat mir geholfen, mein Problem zu lösen!
karlbecker_com
JA!!!! Dieses Problem hat mich geplagt. Dies ist die einzige vernünftige Antwort von Cocoapods, auf die ich gestoßen bin.
DonnaLea
Es gibt eine bessere Möglichkeit, dies unter 1.x zu handhaben
Darren Black
6

Ich habe hinzugefügt :exclusive => true, um doppelte Symbolfehler im Anwendungstestziel zu vermeiden.

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

link_with 'myProject', 'myProjectTests'

Wenn ich das Anwendungstestziel in das Logikeinheitstestziel geändert habe, tritt der Linkerfehler auf. Nachdem ich entfernt habe :exclusive => true, funktioniert alles wieder.

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

link_with 'myProject', 'myProjectTests'

:exclusive => truegibt an, dass do...endNICHT alles außerhalb mit verknüpft werden sollte myProjectTests, was bei Anwendungstestzielen sinnvoll ist, aber bei logischen Testzielen Linkerfehler verursacht.

Hai Feng Kao
quelle
Exklusiv war die Lösung für mich, wie die Antwort von kylef zu diesem CocoaPods-Problem zeigt , die dank der Antwort von JRV auf diese Frage gefunden wurde!
karlbecker_com
1
Ja, jeder sollte dieses Problem auf github lesen, das von @karlbecker_com verlinkt ist. Dies scheint nur eine langfristige Einschränkung von Cocoapods zu sein. Nach der dortigen Diskussion ist link_with nicht erforderlich. Fügen Sie einfach das Testziel hinzu und verwenden Sie: exklusiv. Wenn Ihr Testziel keine bestimmten Pods benötigt, fügen Sie trotzdem einen hinzu, da Cocoapods ihn sonst nicht verarbeiten.
Ball
@kball Welches braucht man nicht link_with? Der Anwendungstest oder der Logikeinheitentest?
Hai Feng Kao
Sofern Sie keinen anderen Grund haben, es zu verwenden, sollten Sie link_with überhaupt nicht benötigen. Und im Allgemeinen möchten Sie diese Pods nicht mit Ihrem Testpaket verknüpfen. Sie sollten nur einmal im App-Bundle verknüpft und dann von Ihren Tests über die Abhängigkeit referenziert werden (um sicherzustellen, dass die standardmäßig ausgeblendeten Symbole deaktiviert sind). Andernfalls ist das Verhalten undefiniert, da zwei Versionen der Pods vorhanden sind - eine im App-Ziel und eine im Testziel.
Ball
6

Sie können link_with gemäß der @ Keith Smiley-Lösung verwenden.

Wenn Sie gemeinsame Pods und Besonderheiten für jedes Ziel haben, können Sie die Option "def" verwenden, um eine Gruppe von Pods zu definieren. und benutze das "def" später im exklusiven Ziel.

def import_pods
    pod 'SSKeychain'
end

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

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

Im obigen Beispiel habe ich den beiden Zielen 'SSKeychain' und 'Typhoon' nur dem Ziel 'MyProject' hinzugefügt

Elihay
quelle
5

Meine Lösung für dieses Problem bestand darin, mein Podfile so zu ändern, dass die Bibliothek in beiden Zielen wie diesem enthalten ist

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

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

Und da ich swift verwende, musste ich auch das Testziel so konfigurieren, dass es die MyApp-Bridging-Header.hDatei enthält. (In der Swift Compiler-Gruppe unter der Registerkarte Build Settings)

Qw4z1
quelle
3
Vorsicht - dies erhöht Ihre Bauzeiten um ein Vielfaches, da Sie immer mehr Pods hinzufügen!
Fatuhoku
@ Fatuhoku wusste das nicht. Können Sie einen Einblick geben, warum dies die Bauzeit verlängert?
Qw4z1
2
Nun, jede Erwähnung eines Pods ist ein Ziel in Ihrem PodsProjekt. Wenn Sie Ihre Pods zweimal erwähnen (einmal für Tests und einmal für die App), haben Sie zwei Zielgruppen. Dies verdoppelt effektiv den Konfigurationsaufwand pod install. Dies wird kein Problem sein, bis Sie> 15 Pods haben. Machen Sie sich also bis dahin keine allzu großen Sorgen.
Fatuhoku
1
Dies ist die einzige Lösung, die für mich mit Cocoapods 1.0
William Entriken
Ab 1.x ist dies die offizielle Methode für Tests, die App-Abhängigkeiten erben: stackoverflow.com/a/40866889/2799670
Darren Black
4

Ich hatte ein ähnliches Ereignis, als ich während einer Versionskontrolle einige Bibliotheksdateien verlor. Ich habe die Bibliotheksdatei immer noch in meinen Pods gesehen, aber da der eigentliche Code fehlt, hat XCode gesagt, dass er weg ist. Zu meiner Bestürzung brachte das Ausführen von 'pod install' die verlorenen Dateien nicht sofort zurück.

Ich musste den Pod manuell entfernen und ersetzen, indem ich Folgendes tat:

  1. Entfernen Sie die Bibliothek aus der Poddatei
  2. Führen Sie 'pod install' aus, um die Bibliothek vollständig zu entfernen
  3. Legen Sie die Bibliothek wieder in das Podfile
  4. Führen Sie 'pod install' erneut aus

Dies sollte die betreffende Bibliothek wieder in ihre ursprüngliche Form bringen.

Maxwell
quelle
2

Es ist auch erwähnenswert, dass, wenn Sie libPods.azweimal hinzugefügt haben , Sie einen bösen Fehler wie diesen erhalten:

232 duplicate symbols for architecture i386

Um dies zu beheben, löschen Sie einfach eine der libPods.aReferenzen in Ihrem Projektexplorer.

Mat Ryer
quelle
2

Ab CocoaPods 1.x gibt es eine neue Möglichkeit, gemeinsame Abhängigkeiten zwischen einem Ziel und dem entsprechenden Testziel zu deklarieren. Ich hatte bis jetzt die von Mark Struzinski akzeptierte Lösung verwendet, aber die Verwendung dieser Methode ergab eine große Anzahl von Warnungen, als ich meine Tests ausführte, die:

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.

Mit CocoaPods 1.x können wir unser -Test-Ziel über die Suchpfade des übergeordneten Ziels als erben deklarieren, wie folgt:

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

Dies führt dazu, dass das -Test-Ziel ohne mehrere binäre Kopien Zugriff auf die Abhängigkeiten des App-Ziels hat. Dies hat die Testaufbauzeiten für mich erheblich verkürzt.

Darren Black
quelle
2

Versuchen Sie das, es funktioniert für mich,

Wir müssen Pods in Konfigurationen setzen,

Die Projekt-> Info-> Konfigurationen im Xcode-Projekt (Ihr Projekt) sollten für Debug, Release (und was Sie sonst noch haben) auf das Hauptprojekt 'Pods' eingestellt sein. Siehe "Header nicht gefunden - Suchpfade nicht enthalten"

Geben Sie hier die Bildbeschreibung ein

Hoffe das ist Hilfe für jemanden.

Jaywant Khedkar
quelle
1

Ich arbeite mit der GoogleMaps Objective-C POD-Integration unter iOS mit meiner Swift-App. Für mich bestand das Problem darin, dass das Testziel keinen Verweis auf die Bridge-Header-Datei ( SWIFT_OBJC_BRIDGING_HEADER ) in den Build-Einstellungen hatte. Stellen Sie sicher, dass sowohl Ihre App- als auch Ihre Test-App-Ziele darauf verweisen, damit die API-Aufrufe von Drittanbietern (Karten-API usw.) in schnellen Komponententests verwendet werden können.

appledevguru
quelle
1
Ich habe ein ähnliches Setup wie Sie. Ich habe den Bridging-Header bereits zum Testziel hinzugefügt. Es wird jedoch die Fehlermeldung "Kein solches Modul 'GoogleMaps'" angezeigt import GoogleMaps.
Nicolas Miari
0

Die nächste Syntax liefert für mich das beste Ergebnis (getestet unter 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

Ohne dies habe ich während des Testlaufs Warnungen über doppelte Symbole.

Danach verschwanden die Warnungen.

Maxim Kholyavkin
quelle
0

Ich hatte Probleme mit OpenCV unter XCTest. Es gab mir Linker-Fehler Undefined symbols for architecture arm64für Klassen wie cv::Mat. Ich installiere OpenCV über CocoaPods pod 'OpenCV', '~> 2.0'unter dem Hauptziel. Egal wie sehr ich versucht habe, die OpenCV-Abhängigkeit unter das Testziel zu stellen oder inherit! :search_pathsnichts davon zu verwenden, hat funktioniert. Die Lösung bestand darin, ein abstract_targetähnliches zu erstellen :

# 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 

Ebenfalls nützlich sind die Befehle pod deintegrate& pod clean, mit denen Sie das Projekt bereinigen und sicherstellen können, dass Sie beim Testen neu beginnen. Sie können diese beiden mit installieren [sudo] gem install cocoapods-deintegrate cocoapods-clean.

Foti Dim
quelle