Xcode Unit Tests - Ошибка связи при создании только для устройства - программирование
Подтвердить что ты не робот

Xcode Unit Tests - Ошибка связи при создании только для устройства

Мои тесты модулей приложений строят и тестируют при запуске в симуляторе, но при создании и тестировании на устройство не удается выполнить ошибку компоновщика.

В моей целевой программе я установил следующие параметры сборки:

DEPLOYMENT_POSTPROCESSING = NO
GCC_SYMBOLS_PRIVATE_EXTERN = NO

На моем unit test я установил следующие настройки сборки:

BUNDLE_LOADER = $(BUILT_PRODUCTS_DIR)/<app name>.app/<app>
TEST_HOST = $(BUNDLE_LOADER)

Ошибка компоновщика:

Undefined symbols for architecture armv7s:
"_<An NSString * const>", referenced from:
      -[UnitTestClassA setUp] in UnitTestClassA.o
"_<Another NSString * const>", referenced from:
      -[UnitTestClassB helperMethod:] in UnitTestClassB.o
      -[UnitTestClassB anotherHelperMethod:] in UnitTestClassB.o
ld: symbol(s) not found for architecture armv7s
clang: error: linker command failed with exit code 1 (use -v to see invocation)

... У меня есть "продолжить после ошибок построения", включенных в настройках Xcode, но я не получаю тонну ошибок компоновщика, жалующихся на NSString * const. Если я делаю что-то не так, тогда ожидаем больше ошибок ссылок, чем кучка, которую я получаю, поскольку я использую строковые константы во всем производственном коде.

Я создаю свои строковые константы следующим образом:

.h файл...

extern NSString * const ReallyGoodString;

.m file...

NSString * const ReallyGoodString = @"This string is great!";

....m файл - это производственный код и часть моего целевого объекта приложения, поэтому мне не нужно связывать его с пакетом unit test.

Итак, что здесь происходит? Почему это отлично работает в симуляторе, а не на устройстве?

Я отправил в Github проект который иллюстрирует проблему. Вы можете увидеть в примере проекта, что эта проблема несовместима: некоторые символы ссылаются только на то, что другие не делают.

4b9b3361

Ответ 1

Когда компоновщик создает исполняемый файл Linker-Error, он отбрасывает FHKViewControllerThisSymbolWontLink, потому что ничего в исполняемом файле не использует. Линкер не знает, что он должен содержать символ вокруг, который будет использоваться пакетом unit test (который динамически загружается во время выполнения).

Вы можете сказать компоновщику, чтобы он не удалял неиспользуемый символ, пометя его атрибутом used, например:

NSString * const FHKViewControllerThisSymbolWontLink __attribute__((used)) = @"name";

Вам нужно будет сделать это для каждого определяемого вами символа, который не используется основным исполняемым файлом, но используется тестовым набором.

Ответ 2

Это, скорее всего, потому, что у вас есть символы, которые используются вашим тестовым набором, которые не используются основным приложением, и Снятие дескриптора кода включено. Вы можете отключить опцию Дефрагментация кодa > для каждой конфигурации. Я установил аналогичную проблему, чтобы тесты могли запускаться на моем устройстве, перевернув опцию Нет только для сборников Debug.

Ответ 3

Некоторые возможности:

  • Вы импортируете заголовок и не связываетесь с соответствующей библиотекой. Это обычное явление, особенно для заголовков таких библиотек, как QuartzCore, поскольку оно не включено в проекты по умолчанию. Чтобы решить:

    а. Добавьте правильные библиотеки в разделе "Связывание двоичных файлов с библиотеками" фаз сборки.

  • Вы копируете файлы в свой проект, но забываете проверить цель, чтобы добавить файлы. Чтобы решить:

    а. Откройте "Фазы сборки" для правильной цели, разверните "Скомпилировать источники" и добавьте отсутствующие файлы .m.

  • Если вы используете логические тесты, они не поддерживаются на устройствах iOS, а только в симуляторе. Однако тесты приложений работают на устройствах. Документы для этого:

iOS: хотя Xcode может запускать логические и прикладные модульные тесты в симуляторы, Xcode не может запускать логические модульные тесты на устройствах iOS. Поэтому, если вы включите и активируете оба типа модульных тестов в схемы, вы не сможете использовать эту схему для запуска модульных тестов на iOS.

Ответ 4

У меня была аналогичная проблема, и решение было так же просто, как очистка проекта, я думаю, вы уже пробовали это, но, возможно, нет. Я бы попробовал хотя бы. Просто перейдите в "Продукт" → "Очистить" в верхней панели навигации или используйте ярлык: "shift" "command" "K"

(Я бы написал это как комментарий, а не ответ, так как это не более чем простое предложение. Но у меня нет достаточного количества баллов для комментариев, извините).