web-dev-qa-db-ja.com

Xcode 4:コマンドライン(xcodebuild)からテストを実行しますか?

Xcode 4で新しいiOSプロジェクトを作成し、単体テストを含めました。デフォルトアプリには、メインアプリケーションと単体テストバンドルの2つのターゲットがあります。 [製品]> [テスト](Command-U)を使用して、アプリケーションをビルドし、ユニットテストバンドルをビルドし、iOSシミュレーターを起動して、テストを実行します。ここで、コマンドラインから同じことを実行できるようにしたいと思います。コマンドラインツール(xcodebuild)には「テスト」アクションがありませんが、アプリケーション自体に依存するため、ユニットテストバンドルターゲットを直接ビルドできるはずです。ただし、実行中:

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).

GUIからCommand-Uを実行すると、テストホストがユニットテストバンドルターゲットに設定されるため、それは嘘のようです。ロジックテストとアプリケーションテストの分離に関する以前の投稿を見てきましたが、Xcode 4はその区別を排除しているようです。コマンドラインからテストを実行する方法はありますか?

47
Steven Wisener

重要な注意点

Xcode 5.1では(おそらく以前のXcodeも)testは有効なビルドアクションです。

Testのビルドアクションと適切な-destinationオプションを使用して、以下のハック全体をxcodebuildの呼び出しに置き換えることができました。詳細については、man xcodebuild

以下の情報は後世のためにここに残されています


Appleのスクリプトをハッキングしてユニットテストを実行してみました

コマンドラインからXcode 4ユニットテストを実行する

そして

Xcode4:iOSのコマンドラインからのアプリケーションテストの実行

また、ウェブ全体に多数の同様の投稿があります。

しかし、私はそれらのソリューションで問題に遭遇しました。ユニットテストの一部はiOSキーチェーンを実行し、それらの呼び出しは、Appleのスクリプトをハッキングすることから来る環境で実行すると、エラーで失敗しました(病的な好奇心のためのerrSecNotAvailable [-25291])。その結果、テストは常に失敗しました...テストの望ましくない機能です。

ウェブ上の他の場所で見つけた情報に基づいて、いくつかのソリューションを試しました。たとえば、iOSシミュレータのセキュリティサービスデーモンを起動しようとするソリューションが含まれていました。それらに苦労した後、私の最善の策は、シミュレータの環境を最大限に活用してiOSシミュレータで実行することでした。

その後、iOSシミュレーター起動ツール ios-sim を入手しました。このコマンドラインツールは、private 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ハッシュにこれらの変数を設定し、いくつかのRubyグランジを使用して、ios-simアプリケーションの一連のコマンドライン引数に結合します。

最下部近くで、起動するアプリとして環境からTEST_Hostを取得し、systemコマンドが実際にios-simを実行し、アプリケーション、環境をセットアップするコマンド引数、および引数-SenTest Allとテストバンドルを渡します実行中のアプリケーションへのパス。

このスキームの利点は、Xcode自体と同じように、シミュレーター環境で単体テストを実行できることです。このスキームの短所は、外部ツールに依存してアプリケーションを起動することです。その外部ツールはprivate Appleフレームワークを使用しているため、以降のOSリリースでは脆弱になる可能性がありますが、現時点では機能します。

追伸この記事では、物語的な理由で「私」をよく使いましたが、多くの功績は、犯罪のパートナーであるパウエルにあります。

48
Scott Thompson

私はジョナの投稿に触発され、それを行う方法を見つけました。

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

基本的に、Xcode 4が必要であり、スクリプトをハッキングして機能させる必要がありますが、必要です。

重要な点は、Xcode 4がiOSテストバンドルをMacOS Xバンドルであるかのように説得することです。これはプラットフォームの問題であり、Xcodeはコマンドラインですぐにアプリケーションテストを実行したくありません。おかしい、うまくいくようだから。

サイトにはサンプルプロジェクトもあります。

9
makdad

あなたが探しているのは、ターミナルからOCUnitテストを実行するためのこの文書化されていない引数です(sdkとtargetも必要です)

xcodebuild  -target MyTarget -sdk iphonesimulator   TEST_AFTER_BUILD=YES
8
bigkm

不完全なソリューションですが、独自のスキームでロジックテストのコマンドラインビルドを実行し、ターゲットをビルドすることができました: http://blog.carbonfive.com/2011/04/06/running-xcode-4-コマンドラインからのユニットテスト/

5
Jonah

xctoolはこの問題を解決します: https://github.com/facebook/xctool

継続的インテグレーションサーバーで問題なく使用します

3
skrusche