重要な注意点
Xcode 5.1 (おそらく以前の Xcode も同様)testでは、有効なビルド アクションです。
-destination以下のハック全体を、test のビルド アクションと適切なオプション を使用した xcodebuild の呼び出しに置き換えることができました。man xcodebuild詳細については。
以下の情報は、後世のためにここに残されています
で述べたように、単体テストを実行するためにAppleのスクリプトをハッキングしてみました
コマンドラインから Xcode 4 単体テストを実行する
と
Xcode4: iOS のコマンドラインからアプリケーション テストを実行する
および多数の同様の投稿がウェブ上で行われています。
ただし、これらのソリューションで問題が発生しました。単体テストの一部は iOS キーチェーンを実行し、それらの呼び出しは、Apple のスクリプトをハッキングした環境で実行すると、エラー ( errSecNotAvailable[-25291] 病的好奇心) で失敗しました。その結果、テストは常に失敗しました... テストの望ましくない機能です。
Web 上の他の場所で見つけた情報に基づいて、いくつかの解決策を試しました。これらの解決策のいくつかには、たとえば、iOS シミュレーターのセキュリティ サービス デーモンを起動しようとする試みが含まれていました。それらに苦労した後、私の最善の策は、シミュレーターの環境を最大限に活用して iOS シミュレーターで実行することであると思われました。
私がしたことは、iOS シミュレータ起動ツールios-simを理解することでした。このコマンド ライン ツールは、Apple のプライベート フレームワークを使用して、コマンド ラインから iOS アプリケーションを起動します。しかし、私にとって特に役に立ったのは、環境変数とコマンド ライン引数の両方を起動中のアプリに渡すことができるという事実でした。
環境変数を使用して、単体テスト バンドルをアプリケーションに挿入することができました。コマンド ライン引数を使用して、アプリで単体テストを実行して終了するために必要な "-SenTest All" を渡すことができます。
上記の投稿で説明されているように、単体テスト バンドル用のスキーム (「CommandLineUnitTests」と呼びます) を作成し、ビルド セクションで「実行」アクションを確認しました。
ただし、Apple のスクリプトをハッキングするのではなく、ios-sim を使用してアプリケーションを起動し、単体テスト バンドルをアプリケーションに個別に挿入する環境をセットアップするスクリプトに置き換えました。
私のスクリプトは、BASH スクリプトよりも慣れ親しんだ Ruby で書かれています。そのスクリプトは次のとおりです。
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 自体が実行していると私が信じているのと同じように、シミュレーター環境で単体テストを実行できることです。この方式の欠点は、アプリケーションの起動を外部ツールに依存することです。この外部ツールはプライベートな Apple フレームワークを使用するため、その後の OS リリースでは壊れやすいかもしれませんが、現時点では機能します。
PS この投稿では、物語上の理由から「私」を多用しましたが、多くの功績は、私と一緒にこれらの問題を解決してくれた犯罪のパートナーであるパウエルに捧げられています。