15
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[Angular] AoT Compile結果を単体テスト時に利用する

Posted at

@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のリンク貼っておきますが、下記あたりです。

どのようなメリットがあるのか

この機能を活用すると、以下のメリットがあります。

  • 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あり)
1fb3c956b2c0d41d51ab149c7cd92a5b.png

Karmaの実行時間が9分台から2分台まで削減されました3。爆速!

どうやって適用するの?

@angular/cliにおけるAoTビルド(ng build --aot)のように、ng test コマンドにオプションが用意されていればよいのですが、この機能はまだ実装されていません4
まぁそのうち使えるようになるとは思うのですが、どうしてもすぐに使いたい!という人向けに雑なスクリプトを組んでみました。

test-aot.sh
#!/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結果を読み込む必要がある
test.ts
getTestBed().initTestEnvironment(
  BrowserDynamicTestingModule,
  platformBrowserDynamicTesting(),
  () => [AppModuleNgSummary] // こいつが重要
);

テスト時間が爆増して困っている!という方はお試しください。

参考・脚注

  1. 節タイトルはDesign Docからパチっています

  2. Three Ways to Test Angular Components

  3. 実のところ、4.1.xまででも散々テスト実行時間には苦労していて、自分でCompile時間を削減する仕組みを作ったりしていました。 https://speakerdeck.com/quramy/haunted-house-of-angular-unit-testing

  4. https://github.com/angular/angular-cli/issues/6650 triageされているので、そのうち使えるようにはなるはず。

15
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?