テスト用のデータを生成する
学習の目的
この単元を完了すると、次のことができるようになります。
- テスト用のデータを作成することがベストプラクティスである理由を説明する。
- 単体テスト専用のデータを作成する。
テストデータを作成する理由
多数の開発者がテストデータを重要視していますが、それにはもっともな理由があります。有用な単体テストを記述する際、テストデータを作成することは最も重要な要素の 1 つです。次の動画で、単体テストの一環としてテストデータを作成する理由を確認してください。
有用なテストの 2 つの重要点は、記述的であることと、テストの実行時の結果が毎回同じになることです。根本的なコードを変更しない限り、テストは何度実行しても常に失敗か合格のいずれかになるはずです。同様に、テストが失敗した理由が常に明確でなければなりません。
このような理由から、テストを実行する際に、取引先や取引先責任者などの既存のデータを使いたくなりますが、得策ではありません。Lightning プラットフォームでは、開発者が本番環境で Apex クラスを編集できないため、テストを作成または編集するためには開発環境を使用する必要があります。つまり、本番組織の Sandbox のスナップショットか Developer Edition 組織を使用しなければなりません。
本番環境のデータは当然ながら時間と共に変化し、開発環境のデータと異なるものになります。開発者環境または本番環境でテストを実行するときは、その組織のデータにしかアクセスできません。つまり、既存のデータを使用してテストを記述すれば、リリースの問題が生じる可能性があります。ある環境で利用可能なデータを、別の環境でも利用できるとは限らないためです。
そのため、テストごとに独自のレコードを作成することが重要です。テストデータは数種の方法で作成できます。この単元では、そのうちの 4 つについて説明します。
- ブルートフォース
- テストファクトリ
- @TestSetup メソッド
- CSV データファイル
VS Code をインストールして Trailhead Playground に接続する
ブルートフォース
この方法では、各テストで必要なレコードを手動で作成して挿入します。
-
VS Code を開きます。
- [Explorer (エクスプローラー)] サイドバーで、
classes
フォルダーを右クリックし、[SFDX: Create Apex Class (SFDX: Apex クラスを作成)] を選択します。[New File (新規ファイル)] コマンドは選択しないでください。このコマンドでは必要なメタデータの .xml ファイルが作成されません。
- 名前に
DataGenerationTests
と入力し、デフォルトのディレクトリを受け入れます。
- クラスの内容を次のコードに置き換えます。
-
[File (ファイル)] > [Save (保存)] をクリックします。
- 作業中の
DataGenerationTests
ファイルを右クリックして、[SFDX: Deploy Source To Org (SFDX: 組織にソースをリリース)] を選択します。[SFDX: Deploy Source To Org (SFDX: 組織にソースをリリース)] オプションを使用できない場合は、前のステップに従って Salesforce CLI で Trailhead Playground を組織に承認したことを確認します。
- 先ほど作成してリリースした Apex クラスの
testBruteForceAccountCreation
メソッドに表示される [Run Test (テストを実行)] ボタンをクリックします。
- [Output (出力)] パネルにテスト結果が表示されます。残念ながら Apex テストに失敗しました。😯
このテストで取引先が作成されないため、テスト実行に失敗します。この点を修正するために、テストでどのようなことが行われるのか見てみましょう。
Test.startTest() の注意点
Salesforce プラットフォームの優れている点の 1 つは、ガバナ制限が組み込まれていることです。ガバナ制限により、1 人のユーザーまたは 1 つの組織がシステムリソースを使い切ることがありません。たとえば、この制限により、Apex コードの実行時間が 10 秒に制限されます。
ガバナ制限は単体テストの実行にも適用されるため、実行に支障がでることがあります。たとえば、テストの設定時に多数のレコードを挿入して照会する必要がある場合、テストするコードを実際にコールするときにガバナ制限に達するおそれがあります。このために、コードは間違っていないのにテストに失敗するという偽失敗が生じる可能性があります。
Test.startTest()
メソッドと Test.stopTest()
メソッドを使用すると、テストするコードをいつコールするかをプラットフォームに指示できます。機能上は、この方法によって startTest()
コールから stopTest()
コールまでのガバナ制限がリセットされ、テストするコードが切り離されます。ガバナ制限についての詳細は、「リソース」セクションのリンク先を参照してください。
テストに合格するためには、取引先を作成する必要があります。
- VS Code のテストクラスに戻ります。
-
List<Account> accts;
の後に新しい行を挿入し、この行に次のコードを配置します。 - クラスを保存して、ステップ 5 ~ 8 を繰り返します。
これでテストに合格するはずです。
実質的にソリューションをブルートフォースすることになります。テストする基本コードをコールする前に、オブジェクトを作成して挿入し、必要なデータを作成します。ブルートフォースは適切に機能しますが、テストが長くなり、追跡しにくくなることがあります。この点は、他のレコードに関連し、多数の項目の詳細を伴うレコードの生成を開始する場合に顕著です。
テストファクトリ
テストを簡潔にし、実行しやすくするために、データの作成を再利用可能なクラスに移すこともできます。データファクトリというこの再利用可能なクラスには、1 つ以上のオブジェクトの作成をモデル化するメソッドが設定されています。また、独自のテストファクトリを作成する必要がありません。オンラインでさまざまなオープンソースのデータファクトリを利用できます。
基本的なテストファクトリがどのようなもので、どのように使用するのか見てみましょう。
-
VS Code を開きます。
- [Explorer (エクスプローラー)] サイドバーで、
classes
フォルダーを右クリックし、[SFDX: Create Apex Class (SFDX: Apex クラスを作成)] を選択します。
- クラスに
TestFactory
と名前を付け、デフォルトのディレクトリを受け入れます。
- TestFactoryclass の内容を次のコードに置き換えます。
-
[File (ファイル)] > [Save (保存)] をクリックします。
- 作業中のファイルを右クリックして、[SFDX: Deploy Source To Org (SFDX: 組織にソースをリリース)] を選択します。
コードのポイント
このテストファクトリはさほど洗練されたものではありませんが、概要をつかむことができます。このテストファクトリクラスは、テストで使用するデータを生成し、必要に応じて挿入する一連のメソッドから構築されます。1 行目が @IsTest
になっていますよね? このクラスとメソッドは、単体テストのコンテキストでのみ使用できるということです。さらに、@IsTest
アノテーションが付いているクラスは、使用可能な Apex の量に関する組織の制限にカウントされません。
クラスには、取引先や取引先責任者と、さらに重要な 5 人の取引先責任者がいる取引先を作成するメソッドが設定されています。データファクトリがその本領を発揮するのは、1 行のコードで関連オブジェクトのネットワークを作成するときです。
テストファクトリを使用する場合は、DataGenerationTests
を変更します。
-
VS Code を開きます。
- [Explorer (エクスプローラー)] サイドバーで、
classes
フォルダーをクリックします。
-
DataGenerationTests
クラスを選択して開きます。
- 最初のテストの後に、次のコードスニペットを配置します。
-
[File (ファイル)] > [Save (保存)] をクリックします。
- 作業中のファイルを右クリックして、[SFDX: Deploy Source To Org (SFDX: 組織にソースをリリース)] を選択します。
- 先ほど作成してリリースした Apex クラスの
testUseTestFactoryToCreateAccountsWithContacts
メソッドに表示される [Run Test (テストを実行)] ボタンをクリックします。
コードのポイント
最初のテストと同様に、テストでテストデータが作成されていることを確認します。ただし、この場合は、テストファクトリクラスを使用してデータを作成します。
TestSetup メソッド
私たちはテストを作成する際、できるだけ簡潔にして、実行しやすくしたいと考えます。データの作成をテストファクトリに切り離せばわかりやすくなりますが、さらに一歩進めることができます。
通常、同じクラスの複数のテストメソッドにはよく似たデータ要件が設定されています。このため、Lightning プラットフォームでは、テストクラスのメソッドに @TestSetup
メソッドというアノテーションを付ける方法が用意されています。プラットフォームは、個々のテストメソッドの前にこうしたメソッドを自動的にコールします。クラスの各テストメソッドの前にこのメソッドがコールされるため、テストデータを作成する場合は極めて有用です。ただし、各テストメソッドの実行後にデータがリセットされます。
では、testSetup メソッドを作成しましょう。
- VS Code の
DataGenerationTests
クラスに戻ります。
- ファイルの上部の private という行のすぐ下に、次の設定メソッドを追加します。
-
[File (ファイル)] > [Save (保存)] をクリックします。
- 作業中のファイルを右クリックして、[SFDX: Deploy Source To Org (SFDX: 組織にソースをリリース)] を選択します。
- 前のステップと同様に、
testUseTestFactoryToCreateAccountsWithContacts
メソッドに表示される [Run Test (テストを実行)] ボタンをクリックします。
おっと、この @TestSetup
メソッドを追加したら、2 つ目のテストメソッドが破損してしまいました。具体的には、アサーションに失敗し、「Assertion Failed: Was expecting to find 5 contacts. (アサーションに失敗しました: 5 人の取引先責任者が見つかると想定していました)」というエラーメッセージが表示されます。
プラットフォームがテストメソッドを実行する前に、@TestSetup
メソッドが取引先責任者を作成したため、テストに失敗しました。テストのクエリで、5 人ではなく、その取引先責任者にテストメソッドが作成した 5 人の取引先責任者を加算した 6 人の取引先責任者が見つかったためです。レコードが増えていることから、実際にテストメソッドを実行する前に、プラットフォームが @TestSetup
メソッドを実行したことがわかります。また、@TestSetup
メソッドでテスト用のレコードを作成可能であることも示されています。
失敗したテストを修正するには、アサーションを 5 ではなく 6 に変更します。
- VS Code の
DataGenerationTests
クラスに戻ります。
-
Assert.areEqual(5, contacts.size(), 'Was expecting to find 5 contacts');
というコード行を見つけます。 - このコード行を次のように変更して、取引先責任者数を 6 人に指定します。
Assert.areEqual(6, contacts.size(), 'Was expecting to find 6 contacts');
-
[File (ファイル)] > [Save (保存)] をクリックします。
- 作業中のファイルを右クリックして、[SFDX: Deploy Source To Org (SFDX: 組織にソースをリリース)] を選択します。
- 前のステップと同様に、
testUseTestFactoryToCreateAccountsWithContacts
メソッドに表示される [Run Test (テストを実行)] ボタンをクリックします。
コードのポイント
この testSetup
メソッドはごく基本的なものですが、すでに実行したこと、つまり、テストファクトリを使用してデータを生成することが組み込まれています。
では、新しい testMethod
を追加して、商談を見つけましょう。
- VS Code の
DataGenerationTests
クラスに戻ります。
- 次のコードで新しいテストメソッドを作成します。
-
[File (ファイル)] > [Save (保存)] をクリックします。
- 作業中のファイルを右クリックして、[SFDX: Deploy Source To Org (SFDX: 組織にソースをリリース)] を選択します。
-
testAtTestSetupMethodsRule
メソッドに表示される [Run Test (テストを実行)] ボタンをクリックします。
コードのポイント
この 3 つ目のテストメソッドは、データを作成していないのに合格します。このテストメソッドでは、プラットフォームによって @TestSetup
メソッドが事前に実行され、テストに合格するために必要な商談が作成されるためです。@TestSetup
メソッドでテストデータが作成される場合も、テスト内でそのデータを照会する必要があります。@TestSetup
メソッドを初めて使用するときに、この点で混乱することがあります。
CSV データファイル
testSetup
メソッドを使用すると、簡潔で的を絞ったテストになりますが、テストデータを使用してさらに一歩進めることができます。CSV ファイルを静的リソースとして作成してアップロードし、その CSV から直接テストデータを生成できます。
コードを 1 行も変更しなくても、テストの範囲を拡張できるシナリオを想像してみてください。CSV データを使用すれば、コードをリリースせずに、コードで処理するデータ入力を追加または変更できます。
- Visual Studio Code を使用して、次のコードをファイルに貼り付け、
accountData.csv
として保存します。 - [Setup (設定)] で、[Quick Find (クイック検索)] ボックスに
Static Resources
(静的リソース) と入力し、[Static Resources (静的リソース)] を選択します。
-
[New (新規)] をクリックします。
- 静的リソースに
accountData
という名前を付けます。
-
[Choose File (ファイルを選択)] をクリックし、[accountData.csv] を選択します。
-
[Cache Control (キャッシュコントロール)] に [Public (公開)] を選択します。
-
[Save (保存)] をクリックします。
次に、VS Code で新しいテストクラスを作成します。
-
VS Code を開きます。
- [Explorer (エクスプローラー)] サイドバーで、classes フォルダーを右クリックし、[SFDX: Create Apex Class (SFDX: Apex クラスを作成)] を選択します。クラスに
CSVTests
と名前を付け、その内容を次のコードに置き換えます。 -
[File (ファイル)] > [Save (保存)] をクリックします。
- 作業中のファイルを右クリックして、[SFDX: Deploy Source To Org (SFDX: 組織にソースをリリース)] を選択します。
-
testLoadAccountsFromStaticResource
メソッドに表示される [Run Test (テストを実行)] ボタンをクリックします。
コードのポイント
このコードも @TestSetup
メソッドを使用します。ただし、testFactory を使用したり、ブルートフォースしたりするのではなく、CSV ファイルを読み込むだけです。このため、テストが極めてクリーンになり、コードをリリースしなくても、テストデータを追加または変更できます。
リソース
- GitHub: Example Test Factory Class (テストファクトリクラスの例)
- Apex 開発者ガイド: テスト設定メソッドの使用
- Apex 開発者ガイド: テストデータ作成用の共通テストユーティリティクラス
- Apex 開発者ガイド: テストデータの読み込み