@Quramy です。
さて、先日 ng-japan というイベントに登壇し、Angularとテストについて喋らせてもらいました。
実は時間があまったら追加で喋ろうかな、と思っていたコンテンツがあったのですが、結果的には完全に時間オーバーしていたため、Qiitaの方に書いておきます。
Use AOT in JIT and AOT unit testing
「AoTなのか、JiTなのかどっちだよ!」という突っ込みが聞こえてきそうですね1。
Angular v4.2系から TestBed#initTestEnvironmentにオプショナルな引数として aotSummaries
というのが追加されました。
AoT Compile済みのNgFactoryを単体テストからも利用できるようになるという素敵野郎です。
今日(2017.06.19)時点では、殆どドキュメントも無いので、対応するcommitのリンク貼っておきますが、下記あたりです。
- https://github.com/angular/angular/commit/547c363
- https://github.com/angular/angular/commit/ed73d4f3ac6b542bf5ea3eb73fbe91e2ceabcdb4
どのようなメリットがあるのか
この機能を活用すると、以下のメリットがあります。
- ComponentのCompileをすっ飛ばせる
- より本番に近しいコードでテストを実行可能
特に嬉しいのが1番目の**「ComponentのCompileをすっ飛ばせる」**です。
AngularのComponent 単体テストでComponentFixture
を用いてテスト対象のComponentをマウントする場合、各spec毎でテスト対象ComponentのCompileが実行されます。
特にIntegration Testing Pattern2 を利用している場合、テスト対象のComponentでは必要のないComponentであっても、依存Moduleとしてimportsに登録していると、当該Moduleのdeclarationsに指定された全てのComponentに対してCompileが実行されます。
ComponentのCompileがテストの実行時間にどの程度効いてくるかについては、以前 Performance Angular unit testing - Mediumで測定や改善について記載しているため、詳細は省きますが、酷いと「Karma実行時間中の70%以上がCompileに要する時間だった」ということもザラです。
下図は実際にプロジェクトで使っているAngularを4.2系にupgradeした際に計測した比較です(左: AoTなし / 右: AoTあり)
Karmaの実行時間が9分台から2分台まで削減されました3。爆速!
どうやって適用するの?
@angular/cli
におけるAoTビルド(ng build --aot
)のように、ng test
コマンドにオプションが用意されていればよいのですが、この機能はまだ実装されていません4。
まぁそのうち使えるようになるとは思うのですが、どうしてもすぐに使いたい!という人向けに雑なスクリプトを組んでみました。
#!/bin/sh
# 1. Create ngsummary.ts
cat << EOF > tsconfig.aottest.json
{
"extends": "./tsconfig.json",
"angularCompilerOptions": {
"genDir": ".",
"debug": false,
"enableSummariesForJit": true
}
}
EOF
./node_modules/.bin/ngc -p ./tsconfig.aottest.json
# 2. Create an entry file for AOT testing
echo "import { AppModuleNgSummary } from './app/app.module.ngsummary';" > src/test_aot.ts
sed -E "s/platformBrowserDynamicTesting\(\)/platformBrowserDynamicTesting(), () => [AppModuleNgSummary],/g" src/test.ts >> src/test_aot.ts
mv src/test.ts src/test.ts.bk && mv src/test_aot.ts src/test.ts
# 3. Run karma
ng test --single-run
CODE=$?
# 4. Cleanup temp files
mv src/test.ts.bk src/test.ts
rm tsconfig.aottest.json
node node_modules/rimraf/bin.js src/**/*.ngfactory.* src/**/*.ngsummary.* src/**/*.shim.ngstyle.ts
node node_modules/rimraf/bin.js e2e/**/*.ngfactory.* e2e/**/*.ngsummary.* e2e/**/*.shim.ngstyle.ts
exit $CODE
※ レポジトリは https://github.com/Quramy/test-with-aot-summary にあります。
ポイントは下記あたりでしょうか:
- AoT Compile時に
enableSummariesForJit
を有効にする必要がある - test.tsでCompile結果を読み込む必要がある
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting(),
() => [AppModuleNgSummary] // こいつが重要
);
テスト時間が爆増して困っている!という方はお試しください。
参考・脚注
-
節タイトルはDesign Docからパチっています ↩
-
実のところ、4.1.xまででも散々テスト実行時間には苦労していて、自分でCompile時間を削減する仕組みを作ったりしていました。 https://speakerdeck.com/quramy/haunted-house-of-angular-unit-testing ↩
-
https://github.com/angular/angular-cli/issues/6650 triageされているので、そのうち使えるようにはなるはず。 ↩