Бібліотеки не знайдено при використанні CocoaPods з логічними тестами iOS


148

Я намагаюся написати деякі логічні тести iOS проти класів у своєму проекті, які використовують функціональність з деяких бібліотек мого підспеку. Я використовую стандартний тестовий пакет одиниць, що надається в Xcode (хоча це не Тестові додатки, а лише Тести одиниць).

Наприклад, я використовую Magical Record, і я маю цю бібліотеку, пов'язану в моєму підспеку. Він присутній у проекті Pods в моєму робочому просторі та працює так, як очікувалося, коли програма запущена в тренажері або на пристрої. Коли я намагаюся зв’язати з тестом об'єкт, який використовує 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клас, який я хочу порівняти, це два різних значення. Очевидно, що мій код із пакету додатків використовує для класу інший символ, ніж код з моїх тестових одиниць. Хтось знайшов спосіб вирішити це?
Ніколас Харт

2
Я не думаю, що це хороший шлях через помилки, про які згадували інші. Дотримуйтесь оновлення файлу конфігурації "на основі" біт. Переконайтеся, що ви не зв’язали libPods.a двічі.
Боб Сприн

3
Це має бути прийнятою відповіддю, оскільки це офіційний спосіб CocoaPods для встановлення Pods з кількома цілями. Thx багато Кіт!
cschuff

174

Я вирішив це, переглянувши, як головна мета мого додатка отримує налаштування з бібліотеки CocoaPods. CocoaPods включає файл .xcconfig з назвою Pods.xcconfig. Цей файл містить усі шляхи пошуку в заголовку.

Якщо ви подивитеся на свій проект у навігаторі проектів та натисніть вкладку Інформація, у верхньому розділі ви побачите свої конфігурації побудови. Якщо ви відкриєте трикутник розкриття для різних конфігурацій, під основним націленням ви побачите Pods. Мені довелося натиснути спадне меню і додати також Pods до цілі логічного тестування.

Знімок конфігурацій

Я також повинен був скопіювати налаштування $(inherited)та ${PODS_HEADERS_SEARCH_PATHS}з моєї основної цілі та скопіювати їх у логічну тестову ціль у розділі Налаштування збірки / HEADER_SEARCH_PATHS.

Нарешті, мені довелося додати libPods.a у фазу побудови Бінарного з бібліотеками для моєї цілі логічного тестування.

Сподіваюся, що це здатне допомогти комусь іншому.


Блискуче! Я використовую MagicalRecord, а також OCMockito та OCHamcrest для тестування одиниць. За допомогою цього виправлення я тепер можу встановити їх усі через CocoaPods! Дякую!
Fogmeister

4
Це працювало для мене, дякую. ПРИМІТКА .. Мені не потрібно було додавати libPods.a як у тестовий прой, так і в основний proj. Це спричиняє помилку повторюваного символу
Крейг Брюс

Для мене мені довелося також скопіювати налаштування збірки "Зазначені користувачем". Шляхи пошуку заголовків посилаються на $ PODS_ROOT, який не визначений у тестовій цілі. Ви можете додати його, перейшовши в Редактор-> Додати налаштування збірки-> Додати налаштовані користувачем налаштування, потім скопіювавши значення $ PODS_ROOT з основної цілі.
Shinigami

11
Це не правильний спосіб виправити це. Дивіться відповідь за допомогою link_with. Ви також можете вказати різні стручки за цільовою основою у вашому файлі стручка, тобто включити лише OCMockito у вашу тестову ціль.
dbainbridge

Так Так Так! Перед цією відповіддю мені довелося видалити Тестову ціль зі своїх проектів! Спасибі людина :)
Йосип Б.

53

Я знайшов тут рішення про тестування блоку з какаоподами :

Відкрийте файл проекту в Xcode, потім виберіть Проект (не ціль), на правій панелі є розділ, який називається Конфігурації. У стовпці "На основі файлу конфігурації" для тестової цілі виберіть "Pods".

введіть тут опис зображення


Що робити, якщо існують залежності від тесту, такі як Spectaви хочете пов'язати з тестовим проектом, але не з основним проектом? : S
фатухоку

Це спрацювало і не потребує змін у конфігурації або налаштуваннях стручків ... Відмінне рішення.
Річард

1
Хоча це рішення може створити помилку: Class Foo is implemented in both MyApp and MyAppTestCase. One of the two will be used. Which one is undefined. це, мабуть, викликано помилкою в Cocoapods; див. відповідь @JRV нижче.
Річард

Це не просто попередження. При такому налаштуванні не генеруються належні дані про покриття коду Xcode, а тести одиниць просто зависають під час запуску у більшості випадків.
i4niac

Я імпортував Estimote SDK вручну шляхом перетягування, я не отримую стручки. Як це вирішити?
Гуру Тея

18

Я погоджуюся з іншими відповідями, які говорять про те, що необхідно зв'язати бібліотеки з тестовими цілями. Однак жодна з пропозицій поки що мені не допомогла. Як в коментарі пише @fabb: "під час тестування isSubclassOfClass:дзвінки повертають НІ, куди вони повинні повернути ДА. Єдиною причиною, яку я можу пояснити, є те, що залежності дійсно пов'язані як з основною, так і з тестовою ціллю, і коли пакет тестової цілі" Навантажувач завантажує основний комплект, він не може визначити, який клас брати. " У мене є та сама проблема з усіма попередніми пропозиціями в цій темі.

Я вирішив працювати над тим, щоб оновити свій Podfile для визначення конкретних Pods для моєї основної цілі та моєї тестової цілі:

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

ТАК!!!! Це питання мене мучить. Це єдина розважлива відповідь какаопів, на яку я натрапив.
DonnaLea

Є кращий спосіб вирішення цього питання під 1.x: stackoverflow.com/a/40866889/2799670
Даррен Блек

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, що розумно в тестових цілях додатків, але це спричинить помилки лінкера в логічних тестових цілях.


Ексклюзивним було рішення для мене, як показано у відповіді kylef на це питання CocoaPods , яке було знайдено завдяки відповіді JRV на це питання!
karlbecker_com

1
Так, усі повинні прочитати цю проблему на github, яку посилається на @karlbecker_com. Здається, це лише тривале обмеження какаоподів. Відповідно до обговорення там, link_with не є необхідним. Просто додайте тестову ціль і використовуйте: ексклюзив. Якщо вашій тестовій цілі не потрібні конкретні стручки, додайте їх все одно, інакше какаоди не оброблять його.
kball

@kball Кому не потрібен link_with? Тест програми або тест логічної одиниці?
Хай Фен Као

Якщо у вас немає іншої причини використовувати його, вам взагалі не знадобиться link_with. І взагалі кажучи, ви не хочете пов'язувати ці стручки зі своїм тестовим пакетом. Вони повинні бути пов’язані лише один раз у пакеті додатків, а потім посилатися вашими тестами через залежність (вимкнення символів, прихованих за замовчуванням). Інакше поведінка не визначена, оскільки існуватимуть дві версії стручків - одна, що входить у ціль програми, а одна - у тестовій.
kball

6

Ви можете використовувати link_with відповідно до рішення @Keith Smiley.

Якщо у вас є загальні стручки та специфіки для кожної цілі, ви можете скористатися параметром "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"


5

Моє рішення цієї проблеми полягало в тому, щоб змінити мій Podfile, щоб включити бібліотеку в обидві цілі, як ця

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

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

А оскільки я використовую швидкий, мені також довелося налаштувати тестову ціль, щоб вона включала MyApp-Bridging-Header.hфайл. (У групі компілятора Swift на вкладці Налаштування збірки)


3
Обережно - це збільшить час збирання на багато, оскільки ви постійно додаватимете більше стручків!
фатухоку

@fatuhoku цього не знав. Чи можете ви дати зрозуміти, чому це збільшує час побудови?
Qw4z1

2
Ну а кожна згадка про стручок - це мета у вашому Podsпроекті. Згадуючи свої стручки двічі (один раз для тестів і один раз для програми), у вас буде два набори цілей. Це фактично подвоює роботу конфігурації pod install. Це не буде проблемою, поки у вас не буде> 15 стручків, хоча до цього часу не переживайте занадто сильно.
фатухоку

1
Це єдине рішення, яке працює для мене з Cocoapods 1.0
Вільям Ентрікен

Станом на 1.x, це офіційний метод для тестів, що успадковують залежності додатків: stackoverflow.com/a/40866889/2799670
Darren Black

4

У мене було подібне явище, коли я втрачав деякі бібліотечні файли під час контролю версій. Я все ще бачив бібліотечний файл у своїх Pods, але при відсутності фактичного коду, XCode сказав, що його немає. На превеликий жаль, запуск програми «pod install» не відразу повертав втрачені файли.

Мені довелося видалити та замінити стручок вручну, виконавши наступне:

  1. Видаліть бібліотеку з Podfile
  2. Запустіть "pod install", щоб повністю видалити бібліотеку
  3. Помістіть бібліотеку назад у Podfile
  4. Запустіть "pod install" ще раз

Це повинно поставити під сумнів бібліотеку в оригінальному вигляді.


2

Також варто зазначити, що якщо ви libPods.aдодали двічі, ви отримаєте подібну неприємну помилку:

232 duplicate symbols for architecture i386

Щоб виправити це, просто видаліть одне з libPods.aпосилань у своєму Провіднику проектів.


2

Як і для CocoaPods 1.x, існує новий спосіб оголосити спільні залежності між ціллю та відповідною тестовою ціллю. Я до цього часу використовував прийняте рішення Марка Струзінського, але використання цього методу дало величезну кількість попереджень під час виконання моїх тестів, які:

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 матиме доступ до залежностей цілі програми без безлічі двійкових копій. Це серйозно прискорило час складання тесту для мене.


2

Спробуйте це працює для мене,

Нам потрібно встановити Pods у конфігураціях,

Проект-> Інформація-> Конфігурації в проекті Xcode (ваш проект) слід встановити на основний проект "Pods" для налагодження, випуску (і що ще у вас є). Див. "Заголовки не знайдено - шляхи пошуку не включені"

введіть тут опис зображення

Сподіваюся, це допомога комусь.


1

Я працюю з інтеграцією PODMagle-Objective-C POD на iOS за допомогою свого додатка Swift, тому для мене проблема полягала в тому, що тестова ціль не мала посилання на файл заголовка моста ( SWIFT_OBJC_BRIDGING_HEADER ) у Налаштуваннях збірки. Переконайтесь, що і ваш, і тестовий націлені програми вказують на це, щоб сторонні виклики API (API API тощо) могли використовуватися в тестових тестових одиницях.


1
У мене аналогічна установка, як і ви. Я вже додав головний мост до тестової цілі, однак я отримую помилку "Немає такого модуля" GoogleMaps "" import GoogleMaps.
Nicolas Miari

0

Наступний синтаксис дає найкращий результат для мене (тестується під cocoapod v.1.2.1):

https://github.com/CocoaPods/CocoaPods/isissue/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

У мене виникли проблеми з використанням OpenCV під XCTest. Це дало мені помилки лінкера Undefined symbols for architecture arm64для таких класів cv::Mat. Я встановлюю OpenCV через CocoaPods, використовуючи pod 'OpenCV', '~> 2.0'під основною ціллю. Як би важко я не намагався поставити залежність 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.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.