iOS 로직 테스트와 함께 CocoaPod를 사용할 때 라이브러리를 찾을 수 없음


148

내 podspec의 일부 라이브러리에서 기능을 사용하는 프로젝트의 클래스에 대해 iOS 논리 테스트를 작성하려고합니다. Xcode에서 제공하는 표준 단위 테스트 번들을 사용하고 있습니다 (응용 프로그램 테스트는 아니지만 단위 테스트 만 가능).

예를 들어, Magical Record를 사용하고 해당 라이브러리를 podspec에 연결했습니다. 내 작업 공간의 포드 프로젝트에 있으며 앱이 시뮬레이터 또는 장치에서 실행될 때 예상대로 작동합니다. 그러나 Magical Record를 사용하는 객체를 테스트에 연결하려고하면 Magical Record에서 선택기를 찾을 수 없다는 링커 오류가 발생합니다. 논리 테스트 번들에서 HEADER_SEARCH_PATH를 업데이트하려고 시도했지만 CocoaPods가 만든 헤더 디렉토리로 하드 코딩했지만 운이 없습니다.

문제없이 CocoaPods 라이브러리를 사용하지 않는 클래스에 대해 단위 테스트를 실행할 수 있습니다.

내가 잘못 가고 있습니까? 컴파일러가 CocoaPods 라이브러리를 볼 수 있도록 다른 작업을 수행해야합니까?

답변:


224

CocoaPods 1.0이 이에 대한 구문을 변경했습니다. 이제 다음과 같이 보입니다 :

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

target 'Sail' do
    shared_pods
end

target 'Sail-iOS' do
    shared_pods
end

사전 CocoaPods 1.0 답변

당신이 사용하려는 것은 link_with에서 Podfile입니다. 다음과 같은 것 :

link_with 'MainTarget', 'MainTargetTests'

그런 다음 pod install다시 실행 하십시오.


7
이것은 즉시 문제를 해결했습니다.
mttrb

9
나는이 이상한 오류를 얻을 - 테스트 할 때, isSubclassOfClass:호출이 반환 NO그들이 반환해야하는 위치 YES. 내가 이것을 설명 할 수있는 유일한 이유는 종속성이 실제로 주 대상과 테스트 대상 모두에 연결되어 있고 테스트 대상의 번들 로더가 주 번들을로드 할 때 어떤 클래스를 취할 것인지 결정할 수 없기 때문입니다.
fabb

4
isKindOfClass:반환 NO해야 할 때 반환 하는 것과 동일한 문제가 YES있습니다. Class테스트하고있는 객체 와 포인터를 기록하면 Class두 가지 값이 있습니다. 분명히 앱 번들의 코드는 단위 테스트 코드와 다른 기호를 사용합니다. 누구든지 이것을 해결할 방법을 찾았습니까?
Nicholas Hart

2
다른 사람들이 언급 한 오류로 인해 이것이 좋은 방법이라고 생각하지 않습니다. 구성 파일 '기준'비트를 업데이트하십시오. libPods.a를 두 번 연결하지 않았는지 확인하십시오.
밥 Spryn

3
이것은 여러 대상으로 포드를 설정하는 공식 CocoaPods 방식이므로 허용되는 답변이어야합니다. 고마워 Keith!
cschuff

174

내 앱의 주요 대상이 CocoaPods 라이브러리에서 설정을받는 방법을 살펴보면서이 사실을 알았습니다. CocoaPods에는 Pods.xcconfig라는 .xcconfig 파일이 포함되어 있습니다. 이 파일에는 모든 헤더 검색 경로가 포함됩니다.

프로젝트 탐색기에서 프로젝트를보고 정보 탭을 클릭하면 맨 위 섹션에 빌드 구성이 나열됩니다. 다른 구성에 대해 펼침 삼각형을 열면 기본 대상 아래에 포드가 표시됩니다. 드롭 다운을 클릭하고 로직 테스트 대상에도 포드를 추가해야했습니다.

구성 스냅 샷

또한의 설정을 복사했다 $(inherited)${PODS_HEADERS_SEARCH_PATHS}HEADER_SEARCH_PATHS / 내 주요 목표로하고 빌드 설정에서 논리 테스트 대상을 통해 복사합니다.

마지막으로, 로직 테스트 대상에 대한 라이브러리와 바이너리 빌드 링크 단계에서 libPods.a를 추가해야했습니다.

이것이 다른 사람을 도울 수 있기를 바랍니다.


훌륭한! 단위 테스트를 위해 MagicalRecord와 OCMockito 및 OCHamcrest를 사용합니다. 이 수정으로 CocoaPods를 통해 모두 설치할 수 있습니다! 감사!
Fogmeister

4
이것은 나를 위해 일했습니다. 감사합니다. NOTE .. 테스트 프로파일과 메인 프로파일 모두에 libPods.a를 추가 할 필요가 없었습니다. 이것은 중복 기호 오류를 일으킨다
Craig Bruce

나도 "사용자 정의"빌드 설정을 복사해야했다. 헤더 검색 경로는 테스트 대상에 정의되지 않은 $ PODS_ROOT를 나타냅니다. Editor-> Add Build Setting-> Add User-Defined Setting으로 이동 한 다음 기본 대상에서 $ PODS_ROOT 값을 복사하여 추가 할 수 있습니다.
Shinigami

11
이 문제를 해결하는 올바른 방법은 아닙니다. link_with로 답변을 참조하십시오. 또한 포드 파일에서 대상별 로 다른 포드를 지정할 수 있습니다 . 즉, 테스트 대상에 OCMockito 만 포함합니다.
dbainbridge

예, 그렇습니다! 이 답변을하기 전에 프로젝트에서 테스트 대상을 삭제해야했습니다! Thanks man :)
Josip B.

53

여기에 CocoaPods를 사용한 단위 테스트 솔루션이 있습니다 .

Xcode에서 프로젝트 파일을 연 다음 프로젝트 (대상이 아닌)를 선택하십시오. 오른쪽 패널에는 구성이라는 섹션이 있습니다. 테스트 대상의 "구성 파일 기반"열에서 포드를 선택하십시오.

여기에 이미지 설명을 입력하십시오


Specta테스트 프로젝트와 연결하지만 주 프로젝트와는 연결하지 않으려 는 테스트 별 종속성이있는 경우 어떻게해야 합니까? : S
fatuhoku

이것은 효과가 있었고 포드 구성이나 설정을 변경할 필요가 없습니다 ... 훌륭한 솔루션.
Richard

1
이 솔루션은 오류를 생성 할 수 있지만 Class Foo is implemented in both MyApp and MyAppTestCase. One of the two will be used. Which one is undefined. Cocoapods의 버그로 인한 것 같습니다. 아래 @JRV 답변을 참조하십시오.
Richard

그것들은 단지 경고가 아닙니다. 이러한 설정을 사용하면 적절한 Xcode 코드 적용 범위 데이터가 생성되지 않으며 대부분의 경우 시작하는 동안 단위 테스트가 중단됩니다.
i4niac

드래그 앤 드롭으로 Estimote SDK를 수동으로 가져 왔는데, 포드가 없습니다. 이 문제를 해결하는 방법?
Guru Teja

18

라이브러리를 테스트 대상에 연결해야한다는 다른 답변에 동의합니다. 그러나 지금까지 제안 사항 중 어느 것도 도움이되지 않았습니다. @fabb는 다음과 같이 주석을 작성합니다. "테스트 할 때 isSubclassOfClass:호출은 YES를 반환해야하는 곳에서 NO를 반환합니다. 이것을 설명 할 수있는 유일한 이유는 종속성이 실제로 주 대상과 테스트 대상, 그리고 테스트 대상의 번들에 연결되어 있기 때문입니다. 로더가 기본 번들을로드하므로 어떤 클래스를 수행할지 결정할 수 없습니다. " 이 스레드의 모든 이전 제안과 동일한 문제가 발생합니다.

내가 해결해야 할 해결책은 내 주요 대상과 테스트 대상에 대한 특정 포드를 정의하기 위해 Podfile을 업데이트하는 것입니다.

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

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

이었다 필요 내가 어떤 테스트 특정 포드를 사용하지 않은 경우에도 내 테스트 대상에 대한 포드를 지정할 수 있습니다. 그렇지 않으면 CocoaPods가 프로젝트에 필요한 연결 논리를 삽입하지 않습니다.

이 링크 는이 결론에 도달하는 데 도움이되었습니다.


1
CocoaPods 문제에 대한 링크를 보내 주셔서 감사합니다. 문제를 해결하는 데 도움이되었습니다.
karlbecker_com

예!!!! 이 문제는 나를 괴롭 혔습니다. 이것은 내가 만난 유일한 현명한 cocoapod 답변입니다.
DonnaLea

1.x에서 이것을 처리하는 더 좋은 방법이 있습니다 : stackoverflow.com/a/40866889/2799670
Darren Black

6

:exclusive => true응용 프로그램 테스트 대상에서 중복 된 기호 오류를 피하기 위해 추가 했습니다.

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

link_with 'myProject', 'myProjectTests'

응용 프로그램 테스트 대상을 논리 장치 테스트 대상으로 변경하면 링커 오류가 발생합니다. 를 제거한 후 :exclusive => true모든 것이 다시 작동합니다.

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

link_with 'myProject', 'myProjectTests'

:exclusive => true외부의 모든 항목 do...end은에 연결해서는 안되며 myProjectTests이는 응용 프로그램 테스트 대상에서는 합리적이지만 논리 테스트 대상에서는 링커 오류가 발생합니다.


이 CocoaPods 문제에 대한 kylef의 답변 에서 볼 수 있듯이 독점적 인 솔루션 이었습니다.이 질문에 대한 JRV의 답변 덕분에 발견되었습니다!
karlbecker_com

1
예, 모두 @karlbecker_com에 의해 연결된 github에서 해당 문제를 읽어야합니다. 이것은 코코아 포드의 장기적 한계 인 것 같습니다. 거기에 대한 토론에 따르면, link_with는 필요하지 않습니다. 테스트 대상을 추가하고 : exclusive를 사용하십시오. 테스트 대상에 특정 포드가 필요하지 않은 경우 어쨌든 하나를 추가하면 코코아 포드는 처리하지 않습니다.
kball

@kball 어느 것이 link_with가 필요하지 않습니까? 응용 프로그램 테스트 또는 논리 장치 테스트?
Hai Feng Kao

그것을 사용해야 할 다른 이유가 없다면, link_with가 전혀 필요하지 않습니다. 또한 일반적으로 해당 포드를 테스트 번들과 연결하고 싶지 않습니다. 앱 번들에서 한 번만 링크 한 다음 종속성을 통해 테스트에서 참조해야합니다 (기본적으로 숨겨진 기호가 꺼져 있는지 확인). 그렇지 않으면 두 가지 버전의 포드 (앱 대상에 포함 된 버전, 테스트 대상에 포함 된 버전)가 있으므로 동작이 정의되지 않습니다.
kball

6

@Keith Smiley 솔루션에 따라 link_with를 사용할 수 있습니다.

공통 포드와 각 대상에 대한 세부 사항이있는 경우 "def"옵션을 사용하여 포드 그룹을 정의 할 수 있습니다. 배타적 대상에서 나중에 "def"를 사용하십시오.

def import_pods
    pod 'SSKeychain'
end

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

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

위의 예에서 두 대상에 'SSKeychain'을 추가하고 'MyProject'대상에만 'Typhoon'을 추가했습니다.


5

이 문제에 대한 나의 해결책은 Podfile을 다음과 같이 두 대상 모두에 라이브러리를 포함하도록 변경하는 것입니다.

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

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

그리고 swift를 사용하고 있기 때문에 MyApp-Bridging-Header.h파일 을 포함하도록 테스트 대상을 구성해야했습니다 . (빌드 설정 탭의 Swift Compiler 그룹에서)


3
주의-포드를 계속 추가하면 빌드 시간이 많이 늘어납니다.
fatuhoku

@fatuhoku는 그것을 몰랐습니다. 빌드 시간이 증가하는 이유에 대한 통찰력을 제공 할 수 있습니까?
Qw4z1

2
포드에 대한 각 언급은 Pods프로젝트 의 대상입니다 . 포드를 두 번 언급하면 ​​(테스트 및 앱에 대해 한 번) 두 개의 대상 세트가 있습니다. 이를 통해 구성 작업 pod install이 두 배로 늘어납니다 . 포드가 15 개를 초과 할 때까지는 문제가되지 않으므로 그때까지 너무 걱정하지 마십시오.
fatuhoku

1
이것은 Cocoapods 1.0에서 작동하는 유일한 솔루션입니다
William Entriken

1.x 현재, 이것은 앱 의존성을 상속하는 테스트를위한 공식적인 방법입니다 : stackoverflow.com/a/40866889/2799670
Darren Black

4

버전 관리 중에 라이브러리 파일을 잃어 버렸을 때도 비슷한 상황이 발생했습니다. 여전히 포드에서 라이브러리 파일을 보았지만 실제 코드가 누락되어 XCode가 사라 졌다고 말했습니다. 당황스럽게도 'pod install'을 실행해도 손실 된 파일을 즉시 가져 오지 못했습니다.

다음을 수행하여 수동으로 포드를 제거하고 교체해야했습니다.

  1. Podfile에서 라이브러리를 제거하십시오.
  2. 라이브러리를 완전히 제거하려면 'pod install'을 실행하십시오.
  3. 라이브러리를 Podfile에 다시 넣습니다.
  4. '포드 설치'를 다시 실행하십시오.

이것은 문제의 라이브러리를 원래 형식으로 되돌려 놓아야합니다.


2

또한 libPods.a두 번 추가 하면 다음 과 같은 불쾌한 오류가 발생합니다.

232 duplicate symbols for architecture i386

문제를 해결하려면 libPods.a프로젝트 탐색기에서 참조 중 하나를 삭제 하십시오.


2

CocoaPods 1.x부터 대상과 해당 테스트 대상간에 공유 종속성을 선언하는 새로운 방법이 있습니다. 지금까지 Mark Struzinski가 승인 한 솔루션을 사용하고 있었지만이 방법을 사용하면 다음과 같은 테스트를 실행할 때 많은 경고가 발생합니다.

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.

CocoaPods 1.x를 사용하면 다음과 같이 -Test 대상을 상위 대상의 검색 경로를 통해 상속으로 선언 할 수 있습니다.

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

이로 인해 -Test 대상이 여러 이진 사본없이 앱 대상의 종속성에 액세스 할 수 있습니다. 이로 인해 테스트 빌드 시간이 크게 단축되었습니다.



1

Swift 앱을 사용하여 iOS에서 GoogleMaps Objective-C POD 통합으로 작업 중이므로 테스트 대상 에 빌드 설정 의 브릿지 헤더 파일 ( SWIFT_OBJC_BRIDGING_HEADER )에 대한 참조가 없다는 것이 문제였습니다 . 타사 API 호출 (맵 API 등)을 신속한 단위 테스트에 사용할 수 있도록 앱 및 테스트 앱 대상이이를 가리키고 있는지 확인하십시오.


1
당신과 비슷한 설정이 있습니다. 테스트 대상에 브리징 헤더를 이미 추가했지만에 "No such module 'GoogleMaps'"오류가 표시됩니다 import GoogleMaps.
Nicolas Miari

0

다음 구문은 나에게 가장 좋은 결과를 제공합니다 (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

이것이 없으면 테스트 중에 중복 기호에 대한 경고가 표시됩니다.

이 경고가 사라진 후.


0

XCTest에서 OpenCV를 사용하는 데 문제가있었습니다. Undefined symbols for architecture arm64같은 클래스 의 링커 오류가 발생했습니다 cv::Mat. pod 'OpenCV', '~> 2.0'주요 대상에서 CocoaPods를 통해 OpenCV를 설치 하고 있습니다. 아무리 노력해도 OpenCV 종속성을 테스트 대상에 두거나 inherit! :search_paths아무 것도 사용 하지 않았습니다. 해결책은 abstract_target다음과 같이 만드는 것입니다.

# 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 

프로젝트를 정리하고 테스트 할 때 새로 시작하는 데 도움 이되는 pod deintegrate& pod clean명령 도 유용합니다 . 를 사용하여이 두 가지를 설치할 수 있습니다 [sudo] gem install cocoapods-deintegrate cocoapods-clean.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.