Không tìm thấy thư viện khi sử dụng CocoaPods với các bài kiểm tra logic của iOS


148

Tôi đang cố gắng viết một số bài kiểm tra logic iOS đối với các lớp trong dự án của tôi có sử dụng chức năng từ một số thư viện trong podspec của tôi. Tôi đang sử dụng gói thử nghiệm đơn vị tiêu chuẩn được cung cấp trong Xcode (mặc dù không phải là Thử nghiệm ứng dụng, chỉ là Thử nghiệm đơn vị).

Ví dụ: tôi sử dụng Magical Record và tôi có thư viện đó được liên kết trong podspec của mình. Nó hiện diện trong dự án Pods trong không gian làm việc của tôi và hoạt động như mong đợi khi ứng dụng đang chạy trong trình giả lập hoặc trên thiết bị. Tuy nhiên, khi tôi cố gắng liên kết để kiểm tra đối tượng sử dụng Magical Record, tôi gặp lỗi liên kết nói rằng nó không thể tìm thấy các công cụ chọn từ Magical Record. Tôi đã thử cập nhật HEADER_SEARCH_PATH trong gói thử nghiệm logic của mình, thậm chí mã hóa nó cứng vào thư mục tiêu đề được tạo bởi CocoaPods, nhưng không gặp may.

Tôi có thể chạy thử nghiệm đơn vị đối với các lớp không sử dụng thư viện CocoaPods mà không gặp vấn đề gì.

Tôi đang đi về điều này sai? Tôi có nên làm một cái gì đó khác để có được trình biên dịch để xem các thư viện của Cốc Cốc không?

Câu trả lời:


224

CocoaPods 1.0 đã thay đổi cú pháp cho việc này. Bây giờ nó trông như thế này:

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

target 'Sail' do
    shared_pods
end

target 'Sail-iOS' do
    shared_pods
end

Câu trả lời trước của Cốc Cốc 1.0

Những gì bạn muốn sử dụng là link_withtừ của bạn Podfile. Cái gì đó như:

link_with 'MainTarget', 'MainTargetTests'

Sau đó chạy pod installlại.


7
Điều này ngay lập tức khắc phục vấn đề cho tôi.
mttrb

9
Tôi nhận được lỗi lạ với điều này - khi kiểm tra, isSubclassOfClass:các cuộc gọi trở lại NOnơi họ sẽ trả lại YES. Lý do duy nhất tôi có thể giải thích điều này là các phụ thuộc thực sự được liên kết với cả mục tiêu chính và mục tiêu thử nghiệm và khi trình tải gói của mục tiêu thử nghiệm tải gói chính, nó không thể quyết định nên chọn lớp nào.
fabb

4
Tôi có cùng một vấn đề với việc isKindOfClass:trở lại NOkhi nó nên trở lại YES. Nếu tôi đăng nhập con trỏ đến Classđối tượng của mình, tôi đang kiểm tra và Classlớp tôi muốn so sánh với chúng là hai giá trị khác nhau. Rõ ràng mã của tôi từ gói ứng dụng đang sử dụng một ký hiệu khác cho lớp so với mã từ các bài kiểm tra đơn vị của tôi. Có ai tìm được cách giải quyết chuyện này không?
Nicholas Hart

2
Tôi không nghĩ rằng đây là một cách tốt để đi do những lỗi mà một số người khác đã đề cập. Tiếp tục cập nhật tệp cấu hình 'dựa trên' bit. Hãy chắc chắn rằng bạn đã không liên kết libPods.a hai lần.
Bob Spryn

3
Đây phải là câu trả lời được chấp nhận vì đây là cách chính thức của Cốc Cốc để thiết lập Pods với nhiều mục tiêu. Thx rất nhiều Keith!
cschuff

174

Tôi đã tìm ra điều này bằng cách xem cách mục tiêu chính của ứng dụng của tôi nhận được các cài đặt từ thư viện CocoaPods. CocoaPods bao gồm tệp .xcconfig có tên Pods.xcconfig. Tập tin này chứa tất cả các đường dẫn tìm kiếm tiêu đề.

Nếu bạn nhìn vào dự án của mình trong trình điều hướng dự án và nhấp vào tab Thông tin, bạn sẽ thấy cấu hình bản dựng của mình được liệt kê ở phần trên cùng. Nếu bạn mở tam giác tiết lộ cho các cấu hình khác nhau của mình, bạn sẽ thấy các Pod được liệt kê dưới mục tiêu chính của bạn. Tôi đã phải bấm vào trình đơn thả xuống và thêm Pods vào mục tiêu kiểm tra logic.

Ảnh chụp cấu hình

Tôi cũng đã phải sao chép các thiết lập của $(inherited)${PODS_HEADERS_SEARCH_PATHS} từ mục tiêu chính của mình và sao chép chúng vào mục tiêu kiểm tra logic trong Cài đặt xây dựng / HEADER_SEARCH_PATHS.

Cuối cùng, tôi đã phải thêm libPods.a trong giai đoạn xây dựng Liên kết nhị phân với Thư viện cho mục tiêu kiểm tra logic của tôi.

Hy vọng điều này có thể giúp đỡ người khác.


Xuất sắc! Tôi sử dụng MagicalRecord và cả OCMockito và OCHamcrest để thử nghiệm đơn vị. Với bản sửa lỗi này, giờ đây tôi có thể cài đặt tất cả chúng thông qua Cốc Cốc! Cảm ơn!
Fogmeister

4
Điều này làm việc cho tôi, cảm ơn. LƯU Ý .. Tôi không cần thêm libPods.a vào cả proj thử nghiệm và proj chính. Điều này gây ra lỗi ký hiệu trùng lặp
Craig Bruce

Đối với tôi, tôi cũng phải sao chép cài đặt bản dựng "Người dùng xác định". Đường dẫn tìm kiếm tiêu đề đề cập đến $ PODS_ROOT không được xác định trên mục tiêu thử nghiệm. Bạn có thể thêm nó bằng cách vào Trình chỉnh sửa-> Thêm cài đặt bản dựng-> Thêm cài đặt do người dùng xác định sau đó sao chép giá trị $ PODS_ROOT từ mục tiêu chính.
Shinigami

11
Đây không phải là cách chính xác để khắc phục điều này. Xem câu trả lời với link_with. Bạn cũng có thể chỉ định các nhóm khác nhau trên cơ sở từng mục tiêu trong tệp nhóm của mình, nghĩa là chỉ bao gồm OCMockito trong mục tiêu thử nghiệm của bạn.
dbainbridge

Có có có! Trước câu trả lời này, tôi đã phải xóa mục tiêu thử nghiệm khỏi các dự án của mình! Cảm ơn người đàn ông :)
Josip B.

53

Có một giải pháp tôi tìm thấy ở đây Bài kiểm tra đơn vị với CocoaPods :

Mở tệp dự án trong Xcode, sau đó chọn Dự án (không phải mục tiêu), trong bảng bên phải, có một phần được gọi là Cấu hình. Chọn Pods trong cột "Dựa trên tệp cấu hình" cho mục tiêu thử nghiệm của bạn.

nhập mô tả hình ảnh ở đây


Chà, nếu có những phụ thuộc cụ thể kiểm thử, như thế Spectabạn muốn liên kết với dự án thử nghiệm chứ không phải với dự án chính thì sao? : S
fatuhoku 17/1/2015

Điều này hoạt động và không yêu cầu bất kỳ thay đổi nào đối với cấu hình pod hoặc thiết lập ... Giải pháp tuyệt vời.
Richard

1
Mặc dù giải pháp này có thể tạo ra lỗi: Class Foo is implemented in both MyApp and MyAppTestCase. One of the two will be used. Which one is undefined. Điều này dường như được gây ra bởi một lỗi trong Cocoapods; xem @JRV trả lời bên dưới.
Richard

Đó không chỉ là những cảnh báo. Với thiết lập như vậy, không có dữ liệu bao phủ mã Xcode phù hợp được tạo ra và các kiểm tra đơn vị chỉ bị treo trong khi khởi chạy trong hầu hết các trường hợp.
i4niac

Tôi đã nhập thủ công SDK ước tính bằng cách kéo và thả, tôi không nhận được nhóm. Làm thế nào để giải quyết điều này?
sư Teja

18

Tôi đồng ý với các câu trả lời khác nói rằng cần phải có các thư viện được liên kết với các mục tiêu thử nghiệm. Tuy nhiên không có gợi ý nào cho đến nay đã giúp tôi. Như @fabb viết trong một bình luận: "khi thử nghiệm,isSubclassOfClass: các cuộc gọi trở về KHÔNG khi họ nên trả về CÓ. Lý do duy nhất tôi có thể giải thích là các phụ thuộc thực sự được liên kết với cả mục tiêu chính và mục tiêu thử nghiệm và khi gói mục tiêu thử nghiệm loader tải gói chính, nó không thể quyết định lớp nào sẽ lấy. " Tôi nhận được cùng một vấn đề với tất cả các đề xuất trước đó trong chủ đề này.

Giải pháp mà tôi phải làm việc là cập nhật Podfile của mình để xác định các Pod cụ thể cho mục tiêu chính và mục tiêu thử nghiệm của tôi:

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

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

Cần phải chỉ định một Pod cho mục tiêu thử nghiệm của tôi mặc dù tôi không sử dụng bất kỳ Pod cụ thể thử nghiệm nào. Nếu không, CocoaPods sẽ không chèn logic liên kết cần thiết vào dự án của tôi.

Liên kết này là những gì đã giúp tôi đi đến kết luận này.


1
Cảm ơn vì liên kết đến vấn đề của Cốc Cốc - đã giúp tôi giải quyết vấn đề của mình!
karlbecker_com

ĐÚNG!!!! Vấn đề này đã làm tôi khó chịu. Đây là câu trả lời cocoapods hợp lý duy nhất tôi đi qua.
DonnaLea

Có cách xử lý vấn đề này tốt hơn dưới 1.x: stackoverflow.com/a/40866889/2799670
Darren Black

6

Tôi đã thêm :exclusive => trueđể tránh các lỗi ký hiệu trùng lặp trong mục tiêu thử nghiệm ứng dụng.

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

link_with 'myProject', 'myProjectTests'

Khi tôi thay đổi mục tiêu thử nghiệm ứng dụng thành thử nghiệm đơn vị logic, lỗi liên kết xảy ra. Sau khi tôi gỡ bỏ :exclusive => true, mọi thứ hoạt động trở lại.

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

link_with 'myProject', 'myProjectTests'

:exclusive => truenói rằng mọi thứ bên ngoài do...endKHÔNG nên được liên kết đến myProjectTests, điều này hợp lý trong các mục tiêu kiểm tra ứng dụng, nhưng nó sẽ gây ra lỗi liên kết trong các mục tiêu kiểm tra logic.


Độc quyền là giải pháp cho tôi, như thể hiện trong câu trả lời của kylef về vấn đề này của Cốc Cốc , được tìm thấy nhờ câu trả lời của JRV về câu hỏi này!
karlbecker_com

1
Có, mọi người nên đọc vấn đề đó trên github được liên kết bởi @karlbecker_com. Có vẻ như đây chỉ là một hạn chế lâu dài của cocoapods. Theo các cuộc thảo luận ở đó, link_with là không cần thiết. Đơn giản chỉ cần thêm mục tiêu thử nghiệm và sử dụng: độc quyền. Nếu mục tiêu thử nghiệm của bạn không cần bất kỳ nhóm cụ thể nào, hãy thêm một nhóm nếu không cocoapods sẽ không xử lý nó.
bóng ném

@kball Cái nào không cần link_with? Bài kiểm tra ứng dụng hay bài kiểm tra đơn vị logic?
Hải Phong Kao

Trừ khi bạn có một lý do khác để sử dụng nó, bạn hoàn toàn không cần link_with. Và nói chung, bạn không muốn liên kết các nhóm đó với gói thử nghiệm của mình. Chúng chỉ nên được liên kết một lần, trong gói ứng dụng và sau đó được các thử nghiệm của bạn tham chiếu thông qua sự phụ thuộc (đảm bảo các Biểu tượng ẩn theo mặc định bị tắt). Mặt khác, hành vi không được xác định bởi vì hai phiên bản của nhóm sẽ tồn tại - một phiên bản được bao gồm trong mục tiêu ứng dụng, một trong mục tiêu thử nghiệm.
bóng ném

6

Bạn có thể sử dụng link_with theo giải pháp @Keith Smiley.

Trong trường hợp bạn có các nhóm chung và thông số cụ thể cho từng mục tiêu, bạn có thể muốn sử dụng tùy chọn "def" để xác định nhóm các nhóm. và sử dụng "def" sau trong mục tiêu độc quyền.

def import_pods
    pod 'SSKeychain'
end

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

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

trong ví dụ trên, tôi đã thêm 'SSKeychain' vào cả hai mục tiêu và 'Typhoon' chỉ cho mục tiêu 'MyProject'


5

Giải pháp của tôi cho vấn đề này là thay đổi Podfile của tôi để đưa thư viện vào cả hai mục tiêu như thế này

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

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

Và vì tôi đang sử dụng swift nên tôi cũng phải định cấu hình mục tiêu thử nghiệm để bao gồm MyApp-Bridging-Header.htệp. (Trong nhóm Trình biên dịch Swift trong tab Cài đặt bản dựng)


3
Cẩn thận - điều này sẽ tăng thời gian xây dựng của bạn lên rất nhiều, khi bạn tiếp tục thêm nhiều nhóm!
fatuhoku

@fatuhoku không biết điều đó. Bạn có thể cung cấp một số cái nhìn sâu sắc về lý do tại sao nó làm tăng thời gian xây dựng?
Qw4z1

2
Vâng, mỗi đề cập đến một nhóm là một mục tiêu trong Podsdự án của bạn . Bằng cách đề cập đến các nhóm của bạn hai lần (một lần cho các thử nghiệm và một lần cho ứng dụng), bạn sẽ có hai bộ mục tiêu. Điều này có hiệu quả gấp đôi công việc cấu hình pod installphải làm. Điều này sẽ không thành vấn đề cho đến khi bạn có> 15 nhóm mặc dù vậy, đừng quá lo lắng cho đến lúc đó.
fatuhoku

1
Đây là giải pháp duy nhất phù hợp với tôi với Cocoapods 1.0
William Entriken

Kể từ 1.x, đây là phương pháp chính thức để kiểm tra kế thừa phụ thuộc ứng dụng: stackoverflow.com/a/40866889/2799670
Darren Black

4

Tôi đã có một sự cố tương tự khi tôi bị mất một số tệp thư viện trong một số kiểm soát phiên bản. Tôi vẫn thấy tệp thư viện trong Pods của mình nhưng với mã thực tế bị thiếu, XCode nói rằng nó đã biến mất. Theo tôi, việc chạy 'cài đặt pod' không ngay lập tức đưa các tập tin bị mất trở lại.

Tôi đã phải loại bỏ và thay thế pod thủ công bằng cách làm như sau:

  1. Xóa thư viện khỏi Podfile
  2. Chạy 'pod install' để xóa hoàn toàn thư viện
  3. Đặt thư viện trở lại vào Podfile
  4. Chạy lại 'cài đặt pod'

Điều này sẽ đặt thư viện trong câu hỏi trở lại ở dạng ban đầu của nó.


2

Cũng đáng lưu ý rằng nếu bạn đã libPods.athêm hai lần, bạn sẽ gặp một số lỗi khó chịu như thế này:

232 duplicate symbols for architecture i386

Để sửa nó, chỉ cần xóa một trong các libPods.atham chiếu trong Project Explorer của bạn.


2

Kể từ Cốc Cốc 1.x, có một cách mới để khai báo các phụ thuộc được chia sẻ giữa mục tiêu và mục tiêu thử nghiệm tương ứng. Tôi đã sử dụng giải pháp được chấp nhận bởi Mark Struzinski cho đến thời điểm này, nhưng sử dụng phương pháp này mang lại một số lượng lớn cảnh báo khi chạy thử nghiệm của tôi rằng:

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.

Với CocoaPods 1.x, chúng tôi có thể khai báo mục tiêu -Test của chúng tôi là kế thừa thông qua các đường dẫn tìm kiếm của mục tiêu cha mẹ, như vậy:

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

Điều này sẽ dẫn đến mục tiêu -Test có quyền truy cập vào các phụ thuộc của mục tiêu ứng dụng mà không có nhiều bản sao nhị phân. Điều này đã nghiêm túc tăng tốc thời gian xây dựng thử nghiệm cho tôi.



1

Tôi đang làm việc với tích hợp GoogleMaps Objective-C POD trên iOS với ứng dụng Swift của tôi và vì vậy, vấn đề là mục tiêu Thử nghiệm không có tham chiếu đến Tệp Tiêu đề Cầu ( SWIFT_OBJC_BRIDGING_HEADER ) trong Cài đặt bản dựng. Đảm bảo cả mục tiêu ứng dụng và ứng dụng thử nghiệm của bạn đều chỉ ra điều đó để các lệnh gọi API của bên thứ 3 (API bản đồ, v.v.) có thể được sử dụng trong các thử nghiệm đơn vị nhanh chóng.


1
Tôi có một thiết lập tương tự như bạn. Tôi đã thêm tiêu đề bắc cầu vào mục tiêu thử nghiệm, tuy nhiên tôi gặp lỗi "Không có mô-đun như vậy 'GoogleMaps'" import GoogleMaps.
Nicolas Miari

0

Cú pháp tiếp theo mang lại kết quả tốt nhất cho tôi (được thử nghiệm theo 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

Không có điều này, tôi có các cảnh báo trong khi chạy thử về các biểu tượng trùng lặp.

Sau khi cảnh báo này đã biến mất.


0

Tôi gặp vấn đề khi sử dụng OpenCV theo XCTest. Nó đã cho tôi các lỗi liên kết của Undefined symbols for architecture arm64các lớp như cv::Mat. Tôi đang cài đặt OpenCV thông qua Cốc Cốc sử dụng pod 'OpenCV', '~> 2.0'theo mục tiêu chính. Bất kể tôi đã cố gắng đặt sự phụ thuộc OpenCV như thế nào vào mục tiêu thử nghiệm hoặc inherit! :search_pathskhông sử dụng bất kỳ mục tiêu nào trong số đó. Giải pháp là tạo ra một thứ abstract_targetnhư vậy:

# 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 

Cũng hữu ích là các lệnh pod deintegrate& pod cleangiúp dọn dẹp dự án và đảm bảo rằng bạn bắt đầu mới khi thử nghiệm. Bạn có thể cài đặt hai cái đó bằng cách sử dụng [sudo] gem install cocoapods-deintegrate cocoapods-clean.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.