Подтвердить что ты не робот

Как перенести из SenTestingKit/OCUnit в XCTest?

Я переношу свой проект с Xcode 4.6.3 на Xcode 5.0.2. Испытания блока проекта были разработаны с помощью SenTestingKit/OCUnit. Теперь, когда я запускаю тесты в Xcode 5, я получаю сообщение об ошибке от RunUnitTests script, говоря мне, что

RunUnitTests устарел.

Возможно, это связано с примечаниями к выпуску Xcode 5:

SenTestingKit и OCUnit устарели. Используйте миграцию для перехода к XCTest.

К сожалению, я не смог больше узнать об этом загадочном "мигрирующем". Возможно, у моего google-fu нет [снова], поэтому мой главный вопрос: как перенести модульные тесты из SenTestingKit/OCUnit в новый XCTest (с или без "migrator" )?

Вторичный вопрос, если миграция - сложный бизнес: возможно ли получить Xcode 5 для запуска модульных тестов, которые все еще основаны на SenTestingKit/OCUnit? После всего этого они просто устарели, поэтому они все равно должны быть рядом и функциональными.

4b9b3361

Ответ 1

Благодаря ответу Shaggy Frog мы знаем, что загадочный "мигрирующий", упомянутый в примечаниях к выпуску Xcode, - это мастер, запускаемый при выборе "Редактировать > Рефакторинг > Преобразовать в XCTest". Я собираюсь написать о своем опыте с этим мастером в двух частях. Первая часть - неполный ответ на основной вопрос, вторая часть отвечает второму вопросу.


Часть 1: переход с OCUnit на XCTest

Первое, что вам нужно понять, это то, что для работы мастера вам нужно выбрать цель unit test. Если вы выбрали основную цель, мастер просто не перечисляет цели для конвертации.

Как только я узнал об этом, я смог пройти через волшебник, но в моем случае конечный результат был по-прежнему впечатляющим провалом! Мастер утверждал, что никаких изменений источника не требуется, и что для настройки на XCTest необходимо обновить только необходимые настройки. В конце концов, мастер даже не успел сделать это правильно: он удалил ссылку на структуру SenTestingKit, но не применил ссылку на инфраструктуру XCTest.

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

  • Удалите фазу "Запустить Script" из unit test target
  • Измените базовый класс всех классов тестовых примеров с SenTestCase на XCTestCase
  • Измените импортированный заголовок с <SenTestingKit/SenTestingKit.h> на <XCTest/XCTest.h>
  • В тестовой задаче "Настройки сборки" измените расширение Wrapper с octest на xctest.
  • Переименуйте все макросы assert от ST* до XCT* (например, STAssertTrue становится XCTAssertTrue)
  • Исключение из вышеизложенного: STAssertEquals необходимо переименовать в XCTAssertEqual (обратите внимание на недостающие "s" в конце). Вы узнаете, что вы забыли об этом, если вы получите предупреждение этого компилятора: warning: implicit declaration of function 'XCTAssertEquals' is invalid in C99
  • Новые макросы утверждения XCTest не позволяют передавать nil в качестве описания сбоя. Например, XCTAssertNotNil(anObject, nil) невозможен и должен быть изменен на XCTAssertNotNil(anObject). Вы узнаете, что у вас есть эта проблема, когда вы получаете эту ошибку компилятора: error: called object type 'NSString *' is not a function or function pointer.
  • Если вам нужно передать описание сбоя, для новых макросов утверждения XCTest требуется константное выражение для спецификатора формата, как это делает метод NSString class stringWithFormat:. Вы узнаете, что у вас есть эта проблема, когда вы получаете эту ошибку компилятора: error: expected ')'. Некоторые примеры:
NSString* formatSpecifier = @"%@";
NSString* failureDescription = @"foo";
// These are OK
XCTAssertNotNil(anObject, @"foo")
XCTAssertNotNil(anObject, @"%@", failureDescription)
// These are not OK
XCTAssertNotNil(anObject, failureDescription);
XCTAssertNotNil(anObject, formatSpecifier, failureDescription);

И последнее, но не менее важное: как уже упоминалось выше, ссылка на раму XCTest должна быть добавлена ​​к цели unit test. Вы узнаете, что вы забыли это, если вы получаете ошибки компоновщика, такие как Undefined symbols for architecture i386: "_OBJC_CLASS_$_XCTestCase", referenced from: foo.

Обновление Xcode 6. Связывание с XCTest больше не требуется в Xcode 6 (на самом деле XCTest больше не отображается в качестве доступной структуры). Вместо этого установите для параметра сборки CLANG_ENABLE_MODULES значение ДА (отображается в пользовательском интерфейсе как "Включить модули (C и Objective-C)" ). Это приведет к тому, что clang автоматически свяжется с XCTest, когда увидит оператор #import <XCTest/XCTest.h>. Подробности доступны в разделе "Модули" документации clang.


Часть 2: Как запустить тесты OCUnit в Xcode 5

В этот момент я получил ошибку компоновщика, которая заставила меня понять, что моя миссия перехода на XCTest потерпела неудачу. Причина: XCTest не является частью SDK 6.1, но я все еще строю свой проект с базовым SDK iOS 6.1 (этот ответ SO объясняет, как интегрировать SDK 6.1 в Xcode 5).

Так как я не могу продолжить миграцию, поэтому мое решение на данный момент состоит в том, чтобы сохранить мои модульные тесты на основе SenTestingKit/OCUnit, пока не найду время для обновления моего приложения до iOS 7. Это то, что я должен был сделать, чтобы запустить единичные тесты:

  • Удалите фазу сборки "Запускать Script" из цели unit test. Это все, что требуется для того, чтобы Xcode выполнял модульные тесты посредством действия "Test" ( + U), в то время как цель unit test выбрана.
  • Это не идеально, хотя я не хочу переключать цели только для выполнения модульных тестов. Вместо этого я хочу выполнить модульные тесты, пока выбран основной объект. Таким образом, вторым шагом является изменение основной целевой схемы Xcode, так что, когда я запускаю действие "Тест", вместо этого выполняются целевые тесты unit test.

Окончательное решение не так хорошо, как в Xcode 4.x, где модульные тесты выполнялись автоматически каждый раз, когда я запускал основное действие "Run" или "Build". К сожалению, кажется, что я не могу заставить это работать без фазы выполнения "Run Script".

Ответ 2

Изменить → Рефакторинг → Преобразовать в XCTest

Тесты OCUnit по-прежнему будут работать, но вы также можете переносить. Изменения в конечном итоге весьма минимальны.