9 Oracle JETアプリケーションのテストおよびデバッグ
Oracle JETアプリケーションのテスト
テストは、回帰を防ぎ、テスト可能な関数、モジュール、クラスおよびコンポーネントで構成されるアプリケーションの作成を促すことによって、複雑なOracle JETアプリケーションを迅速かつ確実に構築するのに役立ちます。
アプリケーションの開発サイクルで、できるだけ早くテストを記述することをお薦めします。 テストを遅らせるほど、アプリケーションの依存関係が増え、テストを開始するのが難しくなります。
テスト・タイプ
Oracle JETアプリケーションをテストする際に考慮する必要がある主なテスト・タイプは3つあります。
- ユニット・テスト
-
ユニット・テストでは、指定された関数またはクラスへのすべての入力が、予想される出力またはレスポンスを生成することをチェックします。
-
これらのテストは、通常、自己完結型のビジネス・ロジック、クラス、モジュール、またはUIレンダリング、ネットワーク・リクエスト、その他の環境上の懸念を伴わない機能に適用されます。
RESTサービスAPIは個別にテストする必要があることに注意してください。
-
ユニット・テストでは、特定のファンクションまたはクラスの実装の詳細および依存関係を認識し、テストされたファンクションまたはクラスの分離に重点を置きます。
-
- コンポーネント・テスト
-
コンポーネント・テストでは、個々のコンポーネントが操作可能で、期待どおりに動作できることを確認します。 これらのテストでは、ユニット・テストよりも多くのコードがインポートされ、より複雑になり、実行に時間がかかります。
-
コンポーネント・テストでは、コンポーネントのプロパティ、イベント、提供されるスロット、スタイル、クラス、ライフサイクル・フックなどに関連する問題を捕捉します。
-
これらのテストは、コンポーネントの実装の詳細を認識しません。コンポーネントとシステム全体の統合をテストするために、モックアップは最小限に抑えます。
コンポーネント・テストで子コンポーネントをモックアップしないでください。かわりに、ユーザーがコンポーネントを操作する(たとえば、要素をクリックするなど)ようにコンポーネントと相互作用するテストで、コンポーネントとその子の間の相互作用をチェックします。
-
- エンドツーエンド・テスト
- エンドツーエンドのテスト(データベースまたはその他のバックエンド・サービスの設定を含むことが多い)では、複数のページにまたがる機能を確認し、本番構築されたJETアプリケーションに対して実際のネットワーク・リクエストを行います。
エンドツーエンドのテストは、個々のコンポーネントだけでなく、アプリケーション全体の機能をテストすることを目的としています。 したがって、Oracle JETアプリケーションの特定のコンポーネントをテストする場合は、コンポーネント・テストを使用します。
ユニット・テスト
ユニット・テストは、最初に実行する最も包括的なテスト形式です。
ユニット・テストの目的は、ソフトウェア・コードの各ユニットが正しくコーディングされ、期待どおりに動作し、関連するすべての入力に対して予想される出力を返すことを確認することです。 単位は、アプリケーションのソース・コード内の関数、メソッド、モジュール、オブジェクトまたはその他のエンティティです。
ユニット・テストは、コードの最下位レベルを実行および検証し、個々のエンティティを分離してテストするために作成された小規模で効率的なテストです。 機能を分離することで、テスト対象のユニットに関連しない外部依存関係を削除し、障害の原因の可視性を高めます。
作成するユニット・テストは、次の原則に従う必要があります:
- 記述しやすい: ユニット・テストはテストの中心です。したがって、多くのテストが記述されるため、通常は簡単に記述できる必要があります。 標準のテスト・テクノロジ・スタックと推奨される開発環境を組み合せることで、テストが簡単かつ迅速に記述されます。
- 読みやすい: 各テストの意図はコメントのみでなく明確に文書化する必要がありますが、コードもその目的を簡単に解釈できるようにする必要があります。 障害が発生し、デバッグが必要な場合に備えて、テストを読みやすくしておくことが重要です。
- 信頼できる: テストは、コンポーネント・コードにバグがない場合は常に合格し、真のバグや未実装の新しい動作がある場合にのみ失敗するようにする必要があります。 また、テストは、実行順序に関係なく確実に実行される必要もあります。
- 高速: テストは迅速に実行され、問題をすぐに開発者に報告できる必要があります。 テストの実行が遅い場合は、外部システムに依存しているか、外部システムと対話していることを示している可能性があります。
- 個別: テストでは、すべてのユニットが正しく検証されていることを確認するだけでなく、障害発生時のバグの検出を支援するために、可能なかぎり小さな作業単位を実行する必要があります。 各ユニット・テストでは、個々のテスト・ケースで、検証するコードの単一の属性を個別にターゲットとする必要があります。
- 独立: 何よりも、ユニット・テストは相互に独立しており、外部の依存関係がなく、実行される環境に関係なく一貫して実行できる必要があります。
ユニット・テストは、結果に影響を及ぼす可能性のある外部変更からユニット・テストを保護するために、コンポーネントによって完全に所有されているコードの検証のみに焦点を当て、そのコンポーネントの外部の動作を検証しないようにします。 外部の依存関係が必要な場合は、モックを使用してそのかわりにすることを検討してください。
コンポーネント・テスト
コンポーネント・テストの目的は、個々のコンポーネントが仕様どおりに動作し、操作できることを確認することです。 コンポーネントが正しい入力を受け入れ、正しい出力を生成していることの検証に加えて、コンポーネント・テストには、コンポーネントのプロパティ、イベント、スロット、スタイル、クラス、ライフサイクル・フックなどに関連する問題のチェックも含まれます。
コンポーネントは多数のコード単位で構成されているため、コンポーネント・テストは複雑で、ユニット・テストよりも実行に時間がかかります。 しかし、避けることはできません。コンポーネント内の個々のユニットは単独では機能しても、一緒に使用すると問題が発生する可能性があるからです。
コンポーネント・テストはクローズボックス・テストの一種です。つまり、テストでは基礎となるコードの詳細を考慮せずにプログラムの動作を評価します。 開発後すぐにコンポーネントのテストを開始する必要がありますが、テスト対象のコンポーネントは、まだ開発されていない他のコンポーネントに依存する場合があります。 開発ライフサイクル・モデルに応じて、外部の影響を防ぐために、コンポーネント・テストをシステム内の他のコンポーネントから分離して実行できます。
コンポーネントが依存するコンポーネントがまだ開発されていない場合は、実際のコンポーネントではなくダミー・オブジェクトを使用します。 これらのダミー・オブジェクトはスタブ(関数と呼ばれます)とコントローラ(関数と呼ばれます)です。
テスト・レベルの深さに応じて、小規模コンポーネント・テストと大規模コンポーネント・テストの2つのタイプのコンポーネント・テストがあります。
コンポーネント・テストを他のコンポーネントから分離して実行する場合、小規模コンポーネント・テストと呼ばれます。 小規模コンポーネント・テストでは、コンポーネントの他のコンポーネントとの統合は考慮されません。
コンポーネントを他のコンポーネントから分離せずにコンポーネント・テストを実行する場合、一般に、大規模コンポーネント・テストまたはコンポーネント・テストと呼ばれます。 これらのテストは、コンポーネントの機能のフローに依存関係があり、分離できない場合に実行されます。
エンドツーエンド・テスト
エンドツーエンド・テストは、ソフトウェア製品の動作を最初から最後まで調べることで評価する方法です。 このアプローチでは、アプリケーションが意図したとおりに動作することを検証し、すべての統合コンポーネントが相互に正しく機能することを確認します。 また、エンドツーエンドのテストでは、最適なパフォーマンスを実現するために、製品のシステムの依存関係が定義されます。
エンドツーエンド・テストの主な目的は、実世界のシナリオをシミュレートし、システムとそのコンポーネントが適切に統合されているか、データの一貫性が保たれているかを評価することで、エンド・ユーザー・エクスペリエンスを再現することです。 この方法では、ユーザーの視点からシステムのパフォーマンスを検証できます。
- 包括的なテスト・カバレッジ
- アプリケーションの正確性の保証
- 市場投入までの時間の短縮
- コストの削減
- バグの特定
- システムのフローの確認
- テスト領域のカバレッジの増加
- サブシステムに関連する問題の特定
- 開発者は、テストの責任を軽減できるため、エンドツーエンド・テストを高く評価しています。
- テスターは、実世界のシナリオをシミュレートして潜在的な問題を回避するテストを作成できるため、有用性を実感しています。
- マネージャは、エンドツーエンドのテストによって、失敗するテストがエンド・ユーザーに与える影響を理解できるので、メリットがあります。
- テストの計画: 必要な主要タスク、スケジュールおよびリソースの概説
- テストの設計: テスト仕様の作成、テスト・ケースの識別、リスクの評価、使用状況の分析およびテストのスケジューリング
- テストの実行: テスト・ケースの実行および結果の文書化
- 結果の分析: テスト結果のレビュー、テスト・プロセスの評価、および必要に応じて追加のテストの実行
- 水平テスト: この方法は複数のアプリケーションでのテストを伴い、多くの場合、単一のERP(エンタープライズ・リソース・プランニング)システムで使用されます。
- 垂直テスト: このアプローチでは、テストが階層順に実行されるレイヤーでのテストが行われます。 この方法は、複雑なコンピューティング・システムの重要なコンポーネントをテストするために使用され、通常はユーザーやインタフェースは関与しません。
エンドツーエンド・テストは通常、完成品およびシステムで行われ、各レビューは完成したシステムのテストとして機能します。 システムが予期した出力を生成しない場合、または問題が検出された場合は、2回目のテストが実行されます。 この場合、チームはデータを記録して分析し、問題の原因を特定して修正し、再テストする必要があります。
- テスト・ケース準備ステータス: このメトリックは、計画されたテスト・ケースと比較して、現在準備されているテスト・ケースの進行状況を追跡するために使用されます。
- テストの進捗追跡: テスト完了率およびテスト・ケースの合格/不合格、実行/未実行および有効/無効のステータスの最新情報を提供するために、テストの進捗状況を週単位で定期的にモニタリングします。
- 不具合のステータスおよび詳細: 未解決およびクローズ済不具合のパーセントと、重大度および優先度別の不具合の内訳を毎週提供します。
- 環境可用性: 毎日の稼働時間数とテスト予定時間に関する情報。
Oracle JETテスト・テクノロジ・スタックについて
Oracle JETアプリケーションをテストするための推奨スタックには、JestおよびPreactテスト・ライブラリが含まれます。
Jestは、独自のテスト・ランナーおよびアサーション機能が付属するJavaScript/Typescriptの一般的なテスト・フレームワークです。 これは、コード・カバレッジとスナップショット・テストをサポートしており、モックを簡単に作成し、テストをパラレルに実行できるため、分離の維持が保証されます。
Jestは、シミュレートされたブラウザ環境としてjsdomを使用したNodeJSで実行されます。 環境では何もレンダリングする必要がないため、これらのテストは非常に迅速に実行されます。これは、ヘッドレスで実行されるDOMの軽量なインメモリー実装です。 Jestテストは、スタイル設定にCSSが必要なものを除き、コンポーネント・クラスのほぼすべての側面を検証するのに適しています。jsdomはCSSを処理しないため、これらのテストを使用してCSSを検証しないでください。 jsdomのブラウザ環境は実際のブラウザではなくシミュレーションであるため、アプリケーション内のコンポーネントのカスタム要素レンダリングのテストにも適していません。
Preact Testingライブラリには、実装の詳細に依存することなく、Preactコンポーネント・クラスの動作をアサートするテストを簡単に記述できる一連のユーティリティ関数が用意されています。 UI中心のテスト・アプローチを促進します。コンポーネント・クラスは完全なレンダリング・ライフサイクルを通過でき、ライブラリはDOM内の要素を見つけるための問合せ関数と、それらと対話するためのユーザー・イベント・シミュレーション・ライブラリを提供します。
Preactテスト・ライブラリの関数は、仮想DOMではなく、Preactによってレンダリングされる実際のDOM要素と連携動作するため、テストはユーザーがアプリケーションと対話し、ページ上の要素を検出する方法に類似します。
UI自動化テストでは、Selenium WebDriverをOracle® JavaScript Extension Toolkit (Oracle JET) WebDriverとともに使用することをお薦めします。
テスト用のOracle JETアプリケーションの構成
Oracle JET CLIのadd testingコマンドを使用して、Oracle JET仮想DOMアプリケーションおよびVComponentコンポーネントをテストするために、JestおよびPreact Testingライブラリを含む依存関係およびライブラリを追加および構成します。
このコマンドをアプリケーションで実行した後、JestおよびPreact Testingライブラリを使用して、アプリケーションのテストを作成および実行できます。 add testingコマンドは、test-configディレクトリをアプリケーションのルート・ディレクトリに追加します。 このディレクトリには、テストの設定に必要な2つのファイル(jest.config.jsおよびtestSetup.ts)が含まれています。 testSetup.tsファイルは、コンパイルおよびトランスパイルされたasync関数のランタイム・サポートをインポートしますが、jest.config.jsはJestの構成ファイルです。
「仕様ファイル」と呼ばれるテストを含むファイルの拡張子は、Oracle JETツールおよびJestテスト構成で認識されるように、.spec.tsxにする必要があります。 仕様ファイルがコンポーネントにない場合は、add testingコマンドによって作成されます。 仕様ファイルは、./src/components/<component-name>/__tests__など、componentsディレクトリ内の__tests__ディレクトリ内にあります。 このディレクトリには、コンポーネントに書き込むテスト・ファイルが保持され、デフォルトでは、add testingコマンドによって、<component-name>.spec.tsxというファイル名パターンを持つ仕様ファイルが作成されます。
ノート:
プロジェクトでadd testingコマンドを実行した後にコマンドラインから新しいコンポーネントまたはJETパックを作成する場合、コンポーネントの作成時に__tests__ディレクトリおよびspecファイルが作成されます。
次のステップでは、テスト用のOracle JETアプリケーションの設定方法、およびユニット・テストとコンポーネント・テストの実行方法を示します。
-
任意のディレクトリでターミナル・ウィンドウを開き、
basicテンプレートを使用して新しいOracle JETアプリケーションを作成します:npx @oracle/ojet-cli create vdomTestApp --template=basic --vdom -
新しく作成したアプリケーションのルート・ディレクトリに移動し、新しいVComponentコンポーネントを作成します。
cd vdomTestApp npx ojet create component hello-world -
./vdomTestApp/src/components/content/index.tsxファイルを開いて、新しく作成したHelloWorldコンポーネントをインポートおよび表示します。import { HelloWorld } from "hello-world/loader" export function Content() { return ( <div class="oj-web-applayout-max-width oj-web-applayout-content"> <HelloWorld /> </div> ); };ノート:
Jestではカスタム要素の代替(import "hello-world/loader" . . . and <hello-world></hello-world>)をテストできないため、Preactコンポーネント・クラス構文(import {HelloWorld} . . . and <HelloWorld />)を使用してHelloWorldコンポーネントをレンダリングします。 -
ブラウザでアプリケーションを実行し、新しく作成された
HelloWorldコンポーネントをアプリケーションがレンダリングすることを確認するには、アプリケーションのルート・ディレクトリのターミナル・ウィンドウで次のコマンドを入力します:npx ojet serveこれはテストの必須ステップでもあります。 コンポーネントをテストする前に、Oracle JET CLIを使用してコンポーネントを構築する必要があります。

ノート:
HelloWorldコンポーネントは、messageプロパティを介して"Hello from hello world"をアプリケーションに渡します。 これにより、アプリケーションとコンポーネントが期待どおりに機能することが確認されます。 -
アプリケーションのルート・ディレクトリのターミナル・ウィンドウで、テスト・ライブラリを追加します。
npx ojet add testingこれにより、
test-configディレクトリがアプリケーションのルート・ディレクトリに、__tests__ディレクトリがcomponentディレクトリ(./src/components/hello-world)に追加されます。__tests__ディレクトリには、レンダリングを検証するHelloWorldコンポーネントのコンポーネント・テストを含む仕様ファイル(hello-world.spec.tsx)が含まれています。 Jestでは、テスト・ケースとアサーション(describe()、test()およびexpect(true).not.toBeUndefined;)が提供され、Preact Testingライブラリのrender()ファンクションでは、コンポーネントがアプリケーションでレンダリングされることがテストされます。./vdomTest/test-config jest.config.js testSetup.tsまた、
add testingコマンドは、JestテストでOracle JET Web要素を使用できるJestプリセットや、testおよびtest:debugという2つの便利なスクリプトなど、package.jsonファイルをテスト依存関係で更新します。 -
ユニット・テストでテストするファンクションを提供するには、前に作成した
HelloWorldコンポーネントの./VDOMTestApp/src/components/hello-world/hello-world.tsxファイルを開き、ファイルの最後にsumファンクションを追加します。. . . >> = registerCustomElement("hello-world", HelloWorldImpl); // function for doc example export const sum = (a: number, b: number) => { return a + b; }; -
このファンクションのユニット・テストを記述するには、
./src/components/hello-world/__tests__/hello-world.spec.tsxファイルを開き、次のエントリを追加します。import { render } from "@testing-library/preact"; import { HelloWorld } from "hello-world/hello-world"; import { sum } from "hello-world/hello-world"; describe("Test description", () => { test("Your test title", async () => { const content = render( <div data-oj-binding-provider="preact"> <HelloWorld /> </div> ); expect(true).not.toBeUndefined; }); it("The sum is 10", () => { expect(sum(6, 4)).toBe(10); }); }); -
アプリケーションのルート・ディレクトリのターミナル・ウィンドウで、次のコマンドを入力してOracle JETアプリケーションをビルドし、テストを実行します。
npx ojet build npm run test端末ウィンドウにテスト結果が表示されます。
vdomTest $ npm run test > vdomTestJET15@1.0.0 test > jest -c test-config/jest.config.js vdomTest $ npm run test > vdomTestJET15@1.0.0 test > jest -c test-config/jest.config.js PASS src/components/hello-world/__tests__/hello-world.spec.tsx Test description â Your test title (5 ms) â The sum is 10 (1 ms) Test Suites: 1 passed, 1 total Tests: 2 passed, 2 total Snapshots: 0 total Time: 1.966 s, estimated 3 s Ran all test suites. PASS src/components/hello-world/__tests__/hello-world.spec.tsx Test description â Your test title (5 ms) â The sum is 10 (1 ms) Test Suites: 1 passed, 1 total Tests: 2 passed, 2 total Snapshots: 0 total Time: 1.966 s, estimated 3 s Ran all test suites.
Oracle JETアプリケーションのデバッグ
Oracle JET WebアプリケーションはJavaScriptまたはTypescriptで記述されたクライアント側のHTML5アプリケーションであるため、好みのブラウザのデバッグ機能を使用できます。
Webアプリケーションのデバッグ
Oracle JETアプリケーションをデバッグするには、ソース・コード・エディタおよびブラウザの開発者ツールを使用します。
Chrome、Edge、Firefoxなどの広く使用されているブラウザ用の開発者ツールには、ブラウザで実行されるOracle JETアプリケーションの検査およびデバッグに役立つ様々な機能が備わっています。 これらの開発者ツールの使用方法の詳細は、ご使用のブラウザのドキュメントを参照してください。
デフォルトでは、ojet buildおよびojet serveコマンドはOracle JETライブラリのデバッグ・バージョンを使用します。 (ojet buildまたはojet serveコマンドに--releaseパラメータを追加して) Oracle JETアプリケーションをリリース・モードで構築または提供する場合、アプリケーションでは縮小バージョンのOracle JETライブラリが使用されます。 リリース・モードで構築したOracle JETアプリケーションをデバッグする場合、--optimize=noneパラメータを使用すると、改行と空白が保持されて、縮小された出力が読みやすくなります:
ojet build --release --optimize=none
ojet serve --release --optimize=none--optimize=noneパラメータを使用しない場合、ブラウザの開発者ツールには、縮小されたソース・ファイルを「プリティ・プリント」して読みやすくするためのオプションが用意されています。
デバッグ・エクスペリエンスを向上させるもう1つの方法は、oraclejetconfig.jsonファイルのgenerateSourceMapsを、デフォルト値のfalseからtrueに設定することです。 trueの場合、Oracle JETアプリケーションのビルド時に、Oracle JET CLIによってTerserおよびRequireJSパッケージが構成され、ソース・マップ・ファイルが生成されます。
また、アプリケーションのデバッグにさらに役立つブラウザ拡張機能をインストールできる場合もあります。
最後に、Visual Studio Codeなどのソース・コード・エディタを使用する場合は、Oracle JETアプリケーションの開発およびデバッグを支援するために提供されているデバッグ・ツールについてよく理解してください。
Preact開発者ツールの使用
Preactブラウザ拡張機能をインストールすると、仮想DOMアプリケーションのデバッグ時に、ご使用のブラウザの開発ツールに追加のデバッグ・ツールを提供できます。
Preactは、https://preactjs.github.io/preact-devtools/で様々なブラウザ拡張機能のダウンロード・リンクを提供しています。
appRootDir/src/index.tsファイルに1行目としてpreact/debugのインポート文を含める必要があります:import 'preact/debug';
import './components/app';仮想DOMアプリケーションの作成時に次のインジェクタ・トークンを含めることで、仮想DOMアプリケーションがデバッグ・モード(ojet buildおよびojet serveのデフォルト・オプション)でビルドまたは提供される際、Oracle JETによってこのインポートを含める処理が行われます:
// injector:preactDebugImport
// endinjector
import './components/app';その結果、Oracle JETのインジェクタ・トークンによってインポート文がデバッグ・モードでのみ含まれることが保証されるため、デバッグ・モードでアプリケーションをビルドまたは提供するときにimport 'preact/debug'文を含めたり、リリース用にビルドまたは提供するときに削除したりする必要はありません。
仮想DOMアプリケーションをデバッグ・モードで提供する場合(ojet serveのデフォルト・オプション)、ブラウザの開発者ツールに追加のタブ「Preact」が表示されます。 次のイメージでは、ChromeブラウザのDevToolsに「Preact」タブが表示されています。
コンポーネントの階層を表示し、コンポーネントを選択して検査し、仮想DOMアプリケーションに関する問題のデバッグに役立つ他のアクションを実行できます。

--release引数を使用して仮想DOMアプリケーションをリリース・モードでビルドまたは提供する場合、Oracle JETはPreact DevToolsをインポートしません。 デバッグ・モードでPreact DevToolsを使用しない場合は、トークンを削除します。
また、Oracle JETでは、アプリケーションが作成されるとき、アプリケーションのappRootDir/src/path_mapping.jsonファイルに次のエントリが含められます。 ここで説明されているPreact拡張機能を使用するには、これらのエントリが必要です。
. . .
"preact/debug": {
"cdn": "3rdparty",
"cwd": "node_modules/preact/debug/dist",
"debug": {
"src": [
"debug.umd.js",
"debug.umd.js.map"
],
"path": "libs/preact/debug/dist/debug.umd.js",
"cdnPath": "preact/debug/dist/debug.umd"
},
"release": {
"src": [
"debug.umd.js",
"debug.umd.js.map"
],
"path": "libs/preact/debug/dist/debug.umd.js",
"cdnPath": "preact/debug/dist/debug.umd"
}
},
"preact/devtools": {
"cdn": "3rdparty",
"cwd": "node_modules/preact/devtools/dist",
"debug": {
"src": [
"devtools.umd.js",
"devtools.umd.js.map"
],
"path": "libs/preact/devtools/dist/devtools.umd.js",
"cdnPath": "preact/devtools/dist/devtools.umd"
},
"release": {
"src": [
"devtools.umd.js",
"devtools.umd.js.map"
],
"path": "libs/preact/devtools/dist/devtools.umd.js",
"cdnPath": "preact/devtools/dist/devtools.umd"
}
},