Xcode 4: запустить тесты из командной строки (xcodebuild)? - программирование
Подтвердить что ты не робот

Xcode 4: запустить тесты из командной строки (xcodebuild)?

Я создал новый проект iOS в Xcode 4 и включил модульные тесты. Приложение по умолчанию имеет 2 цели, основное приложение и пакет unit test. Использование "Product > Test" (Command-U) создает приложение, создает пакет unit test, запускает симулятор iOS и запускает тесты. Теперь я хотел бы иметь возможность сделать то же самое из командной строки. Инструмент командной строки (xcodebuild) не имеет "тестового" действия, но похоже, что я должен иметь возможность напрямую компоновать цель пакета unit 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).

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

4b9b3361

Ответ 1

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

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

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

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


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

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

и

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

и многочисленные подобные публикации в Интернете.

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

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

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

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

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

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

Мой script написан в Ruby, который мне больше знаком, чем BASH scripting. Здесь script:

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, script находит "пусковую установку" (исполняемый файл iOS-sim) в дереве исходных текстов проекта. Затем он конструирует путь к моему модульному пакетному тестированию на основе параметров сборки, которые Xcode передает в переменных среды.

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

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

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

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

Ответ 2

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

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

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

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

Там также пример проекта на сайте.

Ответ 3

то, что вы ищете, - это недокументированный аргумент (вам тоже нужны sdk и target), чтобы запустить тесты OCUnit с терминала

xcodebuild  -target MyTarget -sdk iphonesimulator   TEST_AFTER_BUILD=YES

Ответ 5

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

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