TL;DR: Angular テストの Ahead-Of-Time (AOT) コンパイルを有効にして、正確なテンプレート コード カバレッジ、より高速なテスト実行、本番環境の対称性、将来性を確保します。テスト。
このオプションはすでに Vitest ユーザー向けに提供されており、間もなく Karma および Jest (実験的ビルダー) ユーザー向けにも提供される予定です。
Karma、Jest、Vitest のいずれを使用している場合でも、最近まで利用可能な唯一のオプションであったため、おそらく Angular テストにジャストインタイム (JIT) コンパイルを使用していると思います。
問題は、JIT にはいくつかの重大な欠点があることです。
Angular 8 と IVy の導入以来、Angular コンパイラーはテンプレートを命令に変換し始めました。これは、他の多くの利点の中でも特に、コード カバレッジ ツールがこれらの命令をテンプレートにマッピングし、それに応じてコード カバレッジを計算できることも意味します。
理論上、Angular 8 以降、AOT でテストを実行することでコード カバレッジを生成することは可能でしたが、このオプションは Karma または Jest では利用できませんでした。 Analog チームによって Vitest の Angular サポートが追加されて以来、テストで AOT を有効にすることのみが可能になりました。
2024 年 11 月現在:
JIT を使用しているか AOT を使用しているかに関係なく、コンポーネントはある時点でコンパイルされることになります。主な違いは、AOT ではコンパイルが 1 回で完了し、キャッシュできるのに対し、JIT では各テスト モジュールが最終的にコンポーネントを再コンパイルする可能性があることです。
これは、AOT では変換フェーズが少し遅くても、全体のテスト実行時間は速くなるということを意味します。私が見た数字は約 20% 高速な実行を示していますが、これはテストの構造とテスト対象のシステムに大きく依存します。
私たちは通常、信頼性を高めるために、テストを実稼働環境に対して可能な限り対称にすることを望んでいます。これは、テストの速度、テスト対象システムのサイズ、予測可能性などの他の特性とのバランスをとるため、多くの場合困難です。
AOT の興味深い点は、他の特性を損なうことなく生産の対称性を改善できることです。 AOT を使用すると、自信が高まり、より本番環境に近い動作が実現できます。
さらに重要なのは、JIT が限界に達しており、Angular にとって負担になりつつあることです。たとえば、一部の Angular 機能は JIT ではサポートされていません (遅延ビューなど)。 Angular ロードマップの他の潜在的な機能 (セレクターなしのコンポーネントなど) は、おそらく、JIT では使用できません。
実際には、Angular の信号入力 (および同様の関数 API) 以来、JIT が動作するにはすでにいくつかの最小限の変換が必要です。
AOT に切り替えることで、テストを将来にわたって使用できるようになり、あらゆるイノベーションの恩恵を受けられるようになり、JIT の将来に何が起こっても備えられるようになります。
AOT をオンにすると、動的構造に依存する一部のテクニックが機能しなくなります。
たとえば、次のような使用法は機能しなくなります。
// ? This is broken with AOT. const fixture = render(`<app-button></app-button>`, { imports: [Button] }); function render(template, { imports }) { @Component({ template, imports, }) class TestContainer {} return TestBed.createComponent(TestContainer); }
ただし、AOT コンパイルをバイパスすることは依然として可能です (今のところ⚠️ ️⚠️):
function render(template, { imports }) { @Component({ jit: true, template, imports, }) class TestContainer {} return TestBed.createComponent(TestContainer); }
私のアドバイスは、少し冗長になるかもしれませんが、そのような構造はできるだけ避け、必要に応じてテスト固有のコンポーネントを作成することを優先するです。将来的には、Angular チームは、AOT と互換性があり、定型的な要素が少ない代替案を提供する可能性があります。
浅いテストは本番環境との対称性が低いため、主要なテスト戦略にするべきではありませんが、ツールボックスに入れておくと便利な手法です。
AOT では、TestBed#overrideComponent を使用してコンポーネントのインポートをオーバーライドすることは現時点では不可能です。
回避策は、テスト フレームワークの API を使用してコンポーネントの依存関係をモジュール レベルでオーバーライドし、コンポーネントをそのテスト ダブルで置き換えることです。
たとえば、Vitest の場合:
// app.cmp.spec.ts vi.mock('./street-map.cmp', async () => { return { StreetMap: await import('./street-map-fake.cmp').then( (m) => m.StreetMapFake ), }; }); // street-map-fake.cmp.ts @Component({ selector: 'app-street-map', template: 'Fake Street Map', }) class StreetMapFake implements StreetMap { // ... }
この一時的な回避策は AOT と互換性がありますが、次のようなコストがかかります。
現時点では、TestBed#overrideComponent が AOT をサポートするまで、または Angular チームがより良い代替案を提供するまで、浅いテストには JIT を使用することをお勧めします。これを実現するには、*.jit.spec.ts.
のような特定のパターンに一致するテストに JIT を使用する浅いテスト用の別の設定を使用します。vite.config.js ファイルを見つけて、Angular のプラグイン jit オプションを false に設定して AOT を有効にします。
// ? This is broken with AOT. const fixture = render(`<app-button></app-button>`, { imports: [Button] }); function render(template, { imports }) { @Component({ template, imports, }) class TestContainer {} return TestBed.createComponent(TestContainer); }
コード カバレッジには istanbul またはネイティブ v8 を使用するオプションがあります。何らかの理由で、まだ調査中ですが、v8 を使用すると Vitest カバレッジの再マッピングが失敗します。解決策は、代わりに istanbul を使用するように戻すことです。
Vitest のメジャー バージョン
と一致する Vitest Istanbul バージョンをインストールしていることを確認してください。
function render(template, { imports }) { @Component({ jit: true, template, imports, }) class TestContainer {} return TestBed.createComponent(TestContainer); }
vite.config.mts を更新して、イスタンブールを使用したカバレッジを有効にします。
// app.cmp.spec.ts vi.mock('./street-map.cmp', async () => { return { StreetMap: await import('./street-map-fake.cmp').then( (m) => m.StreetMapFake ), }; }); // street-map-fake.cmp.ts @Component({ selector: 'app-street-map', template: 'Fake Street Map', }) class StreetMapFake implements StreetMap { // ... }
これでテストを実行できるようになります:
export default defineConfig({ ... plugins: [ angular({ jit: false }), ... ], ... });
次に、カバレッジ アイコンをクリックして、テンプレートのコード カバレッジを確認します。 ?
(カバレッジ フォルダーにもカバレッジ レポートがあります)
カバレッジはコンパイラによって生成された命令に基づいて計算されることに注意してください。つまり、次のことがわかります。
構造ディレクティブにも機能します。
さて、どうなるでしょうか?
このカバレッジはインライン テンプレートにも適用されます。 ?
コード カバレッジは便利なツールですが、賢明に使用する必要があります。厳密な目標ではなく、指標として保持してください。
観察された統計的規則性は、制御目的で圧力がかかると崩れる傾向があります。
-- チャールズ・グッドハート
言い換えれば、ある対策が目標になると、それは良い対策ではなくなります。
最も単純な指標は、多くの場合、最も誤解を招きやすいことを付け加えておきます。
Karma ユーザーは、簡単なフラグで AOT を有効にできるようになります。
Jest ユーザーには 3 つのオプションがあります:
Vitest ユーザーは今すぐ AOT のメリットを享受できます。 ?
バグや、リファクタリングのたびに壊れるメンテナンスの多いテストにうんざりしている場合は、私のビデオ コース「Pragmatic Angular Testing」が役に立ちます。
Angular アプリの安定性と保守性を維持するための、実践的で信頼性の高いテスト戦略を学びましょう。 (今なら期間限定で50%オフ!)
以上がAngular テンプレートのコード カバレッジと将来性のあるテストに欠けている要素の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。