Xcode 4: запускать тесты из командной строки (xcodebuild)? - PullRequest
47 голосов
/ 23 марта 2011

Я создал новый проект iOS в Xcode 4 и включил модульные тесты.Приложение по умолчанию имеет 2 цели: основное приложение и пакет модульных тестов.Использование «Product> Test» (Command-U) создает приложение, создает пакет модульных тестов, запускает симулятор iOS и запускает тесты.Теперь я хотел бы сделать то же самое из командной строки.У инструмента командной строки (xcodebuild) нет действия «test», но кажется, что я должен быть в состоянии создать цель пакета юнит-тестирования напрямую, так как это зависит от самого приложения.Однако при выполнении:

xcodebuild -target TestAppTests -sdk iphonesimulator4.3 -configuration Debug build

выдается следующее сообщение:

/Developer/Platforms/iPhoneSimulator.platform/Developer/Tools/Tools/RunPlatformUnitTests:95: warning: Skipping tests; the iPhoneSimulator platform does not currently support application-hosted tests (TEST_HOST set).

Это выглядит как ложь, поскольку тестовый хост установлен для моей цели связки модульных тестов при запуске Command-Uиз графического интерфейса.Я видел предыдущие посты о разделении между логическими тестами и тестами приложений, но похоже, что Xcode 4 устраняет это различие.Любая подсказка, как я могу запустить свои тесты из командной строки?

Ответы [ 5 ]

48 голосов
/ 31 мая 2012

Важное примечание

С Xcode 5.1 (возможно, и более ранним Xcode) test является допустимым действием сборки.

Мы смогли заменить весь хак, приведенный ниже, вызовом xcodebuild, используя действие сборки test и соответствующие опции -destination. man xcodebuild для получения дополнительной информации.

Информация ниже оставлена ​​здесь для потомков


Я пытался взломать скрипты Apple для запуска модульных тестов, как указано в

Запуск модульных тестов Xcode 4 из командной строки

и

Xcode4: запуск тестов приложений из командной строки в iOS

и множество аналогичных сообщений в Интернете.

Однако я столкнулся с проблемой с этими решениями. Некоторые из наших модульных тестов выполняли брелок для iOS, и эти вызовы, когда они выполнялись в среде, которая происходит от взлома скриптов Apple, завершились с ошибкой (errSecNotAvailable [- 25291] для странно любопытных). В результате тесты всегда терпели неудачу ... нежелательная особенность теста.

Я попробовал несколько решений, основанных на информации, которую я нашел в Интернете. Например, некоторые из этих решений включали в себя попытку запуска демона служб безопасности симулятора iOS. После того, как я с этим боролся, мне показалось, что лучше всего было работать на симуляторе iOS с полным преимуществом среды симулятора.

То, что я сделал, затем взял в руки инструмент запуска iOS Simulator ios-sim . Этот инструмент командной строки использует частные платформы Apple для запуска приложения iOS из командной строки. Однако мне особенно пригодился тот факт, что он позволяет передавать как переменные среды, так и аргументы командной строки в приложение, которое оно запускает.

Несмотря на то, что переменные окружения, мне удалось внедрить свой пакет модульного тестирования в мое приложение. Через аргументы командной строки я могу передать «-SenTest All», необходимый для того, чтобы приложение запустило модульные тесты и завершило работу.

Я создал схему (которую я назвал «CommandLineUnitTests») для моего пакета модульного тестирования и проверил действие «Выполнить» в разделе сборки, как описано в постах выше.

Однако вместо того, чтобы взламывать скрипты Apple, я заменил скрипт на тот, который запускает приложение с помощью ios-sim и настраивает среду для добавления моего пакета модульного тестирования в приложение отдельно.

Мой сценарий написан на Ruby, который мне более знаком, чем сценарии BASH. Вот этот скрипт:

if ENV['SL_RUN_UNIT_TESTS'] then
    launcher_path = File.join(ENV['SRCROOT'], "Scripts", "ios-sim")
    test_bundle_path= File.join(ENV['BUILT_PRODUCTS_DIR'], "#{ENV['PRODUCT_NAME']}.#{ENV['WRAPPER_EXTENSION']}")

    environment = {
        'DYLD_INSERT_LIBRARIES' => "/../../Library/PrivateFrameworks/IDEBundleInjection.framework/IDEBundleInjection",
        'XCInjectBundle' => test_bundle_path,
        'XCInjectBundleInto' => ENV["TEST_HOST"]
    }

    environment_args = environment.collect { |key, value| "--setenv #{key}=\"#{value}\""}.join(" ")

    app_test_host = File.dirname(ENV["TEST_HOST"])
    system("#{launcher_path} launch \"#{app_test_host}\" #{environment_args} --args -SenTest All #{test_bundle_path}")
else
    puts "SL_RUN_UNIT_TESTS not set - Did not run unit tests!"
end

Запуск этого из командной строки выглядит так:

xcodebuild -sdk iphonesimulator -workspace iPhoneApp.xcworkspace/ -scheme "CommandLineUnitTests" clean build SL_RUN_UNIT_TESTS=YES

После поиска переменной среды SL_RUN_UNIT_TESTS сценарий находит «панель запуска» (исполняемый файл iOS-sim) в дереве исходного кода проекта. Затем он создает путь к моему пакету модульного тестирования на основе параметров сборки, которые XCode передает в переменных среды.

Затем я создаю набор переменных среды выполнения для моего работающего приложения, которые внедряют пакет модульного тестирования. Я установил эти переменные в хэш environment в середине скрипта, а затем использовал рубиновый гранж, чтобы объединить их в серию аргументов командной строки для приложения ios-sim.

Внизу я извлекаю TEST_HOST из среды как приложение, которое я хочу запустить, и команда system фактически выполняет ios-sim, передавая приложение, аргументы команды для настройки среды и аргументы -SenTest All и путь к тестовому пакету с запущенным приложением.

Преимущество этой схемы в том, что она запускает модульные тесты в среде симулятора так же, как я полагаю, сам Xcode. Недостаток схемы в том, что она использует внешний инструмент для запуска приложения. Этот внешний инструмент использует частные фреймворки Apple, поэтому он может быть хрупким при последующих выпусках ОС, но пока работает.

P.S. Я много использовал «я» в этом посте по повествовательным причинам, но большая заслуга принадлежит моему преступному партнеру Павлу, который работал со мной над этими проблемами.

9 голосов
/ 17 апреля 2011

Я был вдохновлен постом Ионы и нашел способ сделать это:

http://longweekendmobile.com/2011/04/17/xcode4-running-application-tests-from-the-command-line-in-ios/

По сути, вам нужен Xcode 4, и вы должны взломать скрипт, чтобы он работал,но это так.

Ключевым моментом является убедить Xcode 4 запустить ваш тестовый пакет iOS, как если бы это был пакет MacOS X - это проблема с платформой, Xcode не хочет запускать тесты приложений изокно в командной строке.Забавно, потому что это похоже на работу.

На сайте также есть пример проекта.

8 голосов
/ 10 сентября 2012

вы ищете этот недокументированный аргумент (вам также нужен sdk и target) для запуска ваших тестов OCUnit из терминала

xcodebuild  -target MyTarget -sdk iphonesimulator   TEST_AFTER_BUILD=YES
5 голосов
/ 07 апреля 2011

Это неполное решение, но я смог запустить сборки логических тестов в командной строке по их собственной схеме и цели сборки: http://blog.carbonfive.com/2011/04/06/running-xcode-4-unit-tests-from-the-command-line/

3 голосов
/ 21 июня 2013

xctool решает эту проблему: https://github.com/facebook/xctool

мы используем его на нашем сервере непрерывной интеграции без проблем

...