Skip to main content
3 月 5 日~ 6 日にサンフランシスコで開催される TDX (Salesforce+ でも配信) で「Developer Conference for the AI Agent Era (AI エージェント時代に向けた開発者向けカンファレンス)」にぜひご参加ください。お申し込みはこちら

テスト用のデータを生成する

学習の目的

この単元を完了すると、次のことができるようになります。

  • テスト用のデータを作成することがベストプラクティスである理由を説明する。
  • 単体テスト専用のデータを作成する。
メモ

メモ

日本語で受講されている方へ
Challenge は日本語の Trailhead Playground で開始し、かっこ内の翻訳を参照しながら進めていってください。Challenge での評価は英語データを対象に行われるため、英語の値のみをコピーして貼り付けるようにしてください。日本語の組織で Challenge が不合格だった場合は、(1) この手順に従って [Locale (地域)] を [United States (米国)] に切り替え、(2) [Language (言語)] を [English (英語)] に切り替えてから、(3) [Check Challenge (Challenge を確認)] ボタンをクリックしてみることをお勧めします。

翻訳版 Trailhead を活用する方法の詳細は、自分の言語の Trailhead バッジを参照してください。

テストデータを作成する理由

多数の開発者がテストデータを重要視していますが、それにはもっともな理由があります。有用な単体テストを記述する際、テストデータを作成することは最も重要な要素の 1 つです。次の動画で、単体テストの一環としてテストデータを作成する理由を確認してください。

有用なテストの 2 つの重要点は、記述的であることと、テストの実行時の結果が毎回同じになることです。根本的なコードを変更しない限り、テストは何度実行しても常に失敗か合格のいずれかになるはずです。同様に、テストが失敗した理由が常に明確でなければなりません。 

このような理由から、テストを実行する際に、取引先や取引先責任者などの既存のデータを使いたくなりますが、得策ではありません。Lightning プラットフォームでは、開発者が本番環境で Apex クラスを編集できないため、テストを作成または編集するためには開発環境を使用する必要があります。つまり、本番組織の Sandbox のスナップショットか Developer Edition 組織を使用しなければなりません。 

本番環境のデータは当然ながら時間と共に変化し、開発環境のデータと異なるものになります。開発者環境または本番環境でテストを実行するときは、その組織のデータにしかアクセスできません。つまり、既存のデータを使用してテストを記述すれば、リリースの問題が生じる可能性があります。ある環境で利用可能なデータを、別の環境でも利用できるとは限らないためです。

そのため、テストごとに独自のレコードを作成することが重要です。テストデータは数種の方法で作成できます。この単元では、そのうちの 4 つについて説明します。

  • ブルートフォース
  • テストファクトリ
  • @TestSetup メソッド
  • CSV データファイル

VS Code をインストールして Trailhead Playground に接続する

メモ

このモジュールで記述したテストは、VS Code を使用して実行します。「クイックスタート: Salesforce 開発のための Visual Studio Code」を受講して、VS Code のインストール方法、プロジェクトの作成方法、プロジェクトを Trailhead Playground に接続する方法を確認してください。

ブルートフォース

この方法では、各テストで必要なレコードを手動で作成して挿入します。 

  1. VS Code を開きます。
  2. [Explorer (エクスプローラー)] サイドバーで、classes フォルダーを右クリックし、[SFDX: Create Apex Class (SFDX: Apex クラスを作成)] を選択します。[New File (新規ファイル)] コマンドは選択しないでください。このコマンドでは必要なメタデータの .xml ファイルが作成されません。
  3. 名前に DataGenerationTests と入力し、デフォルトのディレクトリを受け入れます。
  4. クラスの内容を次のコードに置き換えます。
    @IsTest
    private class DataGenerationTests {
      @IsTest
      static void testBruteForceAccountCreation() {
        // GIVEN
        List<Account> accts;
        // WHEN
        Test.startTest();
          accts = [SELECT Id FROM Account];
        Test.stopTest();
        // THEN
        Assert.isTrue(accts.size() > 0, 'Was expecting to find at least one account');
      }
    }
  5. [File (ファイル)] > [Save (保存)] をクリックします。
  6. 作業中の DataGenerationTests ファイルを右クリックして、[SFDX: Deploy Source To Org (SFDX: 組織にソースをリリース)] を選択します。[SFDX: Deploy Source To Org (SFDX: 組織にソースをリリース)] オプションを使用できない場合は、前のステップに従って Salesforce CLI で Trailhead Playground を組織に承認したことを確認します。
  7. 先ほど作成してリリースした Apex クラスの testBruteForceAccountCreation メソッドに表示される [Run Test (テストを実行)] ボタンをクリックします。
    [Run Test (テストを実行)] ボタン
  8. [Output (出力)] パネルにテスト結果が表示されます。残念ながら Apex テストに失敗しました。😯

このテストで取引先が作成されないため、テスト実行に失敗します。この点を修正するために、テストでどのようなことが行われるのか見てみましょう。 

Test.startTest() の注意点

Salesforce プラットフォームの優れている点の 1 つは、ガバナ制限が組み込まれていることです。ガバナ制限により、1 人のユーザーまたは 1 つの組織がシステムリソースを使い切ることがありません。たとえば、この制限により、Apex コードの実行時間が 10 秒に制限されます。 

ガバナ制限は単体テストの実行にも適用されるため、実行に支障がでることがあります。たとえば、テストの設定時に多数のレコードを挿入して照会する必要がある場合、テストするコードを実際にコールするときにガバナ制限に達するおそれがあります。このために、コードは間違っていないのにテストに失敗するという偽失敗が生じる可能性があります。 

Test.startTest() メソッドと Test.stopTest() メソッドを使用すると、テストするコードをいつコールするかをプラットフォームに指示できます。機能上は、この方法によって startTest() コールから stopTest() コールまでのガバナ制限がリセットされ、テストするコードが切り離されます。ガバナ制限についての詳細は、「リソース」セクションのリンク先を参照してください。

テストに合格するためには、取引先を作成する必要があります。

  1. VS Code のテストクラスに戻ります。
  2. List<Account> accts; の後に新しい行を挿入し、この行に次のコードを配置します。
    Account a = new Account(name='McTesterson LLC');
    insert a;
  3. クラスを保存して、ステップ 5 ~ 8 を繰り返します。

これでテストに合格するはずです。 

実質的にソリューションをブルートフォースすることになります。テストする基本コードをコールする前に、オブジェクトを作成して挿入し、必要なデータを作成します。ブルートフォースは適切に機能しますが、テストが長くなり、追跡しにくくなることがあります。この点は、他のレコードに関連し、多数の項目の詳細を伴うレコードの生成を開始する場合に顕著です。 

テストファクトリ

テストを簡潔にし、実行しやすくするために、データの作成を再利用可能なクラスに移すこともできます。データファクトリというこの再利用可能なクラスには、1 つ以上のオブジェクトの作成をモデル化するメソッドが設定されています。また、独自のテストファクトリを作成する必要がありません。オンラインでさまざまなオープンソースのデータファクトリを利用できます。 

基本的なテストファクトリがどのようなもので、どのように使用するのか見てみましょう。

  1. VS Code を開きます。
  2. [Explorer (エクスプローラー)] サイドバーで、classes フォルダーを右クリックし、[SFDX: Create Apex Class (SFDX: Apex クラスを作成)] を選択します。
  3. クラスに TestFactory と名前を付け、デフォルトのディレクトリを受け入れます。
  4. TestFactoryclass の内容を次のコードに置き換えます。
    @isTest
    public class TestFactory {
      public static Account getAccount(String name, Boolean doInsert) {
        Account a = new Account(name = name);
        if(doInsert) {
          insert a;
        }
        return a;
      }
      public static Contact getContact(
        Id accountId,
        String fname,
        String lname,
        Boolean doInsert
      ) {
        Contact c = new Contact(firstName = fname, lastName = lname, accountId = accountId);
        if(doInsert) {
          insert c;
        }
        return c;
      }
      public static void generateAccountWithContacts(Integer numContacts) {
        Account a = getAccount('default account ltd', true);
        List<Contact> contacts = new List<Contact>();
        for(Integer i = 0; i < numContacts; i++) {
          String contactName = 'contact' + i;
          contacts.add(getContact(a.id, contactName, contactName, false));
        }
        insert contacts;
      }
      public static Opportunity[] generateOppsForAccount(
        id accountId,
        Decimal amount,
        Integer numOpps
      ) {
        List<Opportunity> opps = new List<Opportunity>();
        for(Integer i = 0; i < numOpps; i++) {
          Opportunity o = new Opportunity();
          o.name = 'Account ' + i;
          o.accountId = accountid;
          o.amount = amount;
          o.closeDate = Date.today().addDays(5);
          o.stageName = 'Prospecting';
          opps.add(o);
        }
        return opps;
      }
      public static User generateUser(String profileName) {
        UserRole userRole = new UserRole(
          DeveloperName = 'TestingTeam',
          Name = 'Testing Team'
        );
        insert userRole;
        User u = new User(
          ProfileId = [SELECT Id FROM Profile WHERE Name = :profileName].Id,
          LastName = 'last',
          Email = 'Cpt.Awesome@awesomesauce.com',
          Username = 'Cpt.Awesome.' + DateTime.now().getTime() + '@awesomesauce.com',
          CompanyName = 'Testing Co',
          Title = 'Captian',
          Alias = 'alias',
          TimeZoneSidKey = 'America/Los_Angeles',
          EmailEncodingKey = 'UTF-8',
          LanguageLocaleKey = 'en_US',
          LocaleSidKey = 'en_US',
          UserRoleId = userRole.Id
        );
        insert u;
        return u;
      }
    }
  5. [File (ファイル)] > [Save (保存)] をクリックします。
  6. 作業中のファイルを右クリックして、[SFDX: Deploy Source To Org (SFDX: 組織にソースをリリース)] を選択します。

コードのポイント

このテストファクトリはさほど洗練されたものではありませんが、概要をつかむことができます。このテストファクトリクラスは、テストで使用するデータを生成し、必要に応じて挿入する一連のメソッドから構築されます。1 行目が @IsTest になっていますよね? このクラスとメソッドは、単体テストのコンテキストでのみ使用できるということです。さらに、@IsTest アノテーションが付いているクラスは、使用可能な Apex の量に関する組織の制限にカウントされません。 

クラスには、取引先や取引先責任者と、さらに重要な 5 人の取引先責任者がいる取引先を作成するメソッドが設定されています。データファクトリがその本領を発揮するのは、1 行のコードで関連オブジェクトのネットワークを作成するときです。 

テストファクトリを使用する場合は、DataGenerationTests を変更します。

  1. VS Code を開きます。
  2. [Explorer (エクスプローラー)] サイドバーで、classes フォルダーをクリックします。
  3. DataGenerationTests クラスを選択して開きます。
  4. 最初のテストの後に、次のコードスニペットを配置します。
    @IsTest
    static void testUseTestFactoryToCreateAccountsWithContacts() {
      // GIVEN
      List<Account> accts;
      List<Contact> contacts;
      TestFactory.generateAccountWithContacts(5);
      // WHEN
      Test.startTest();
        accts = [SELECT Id FROM Account];
        contacts = [SELECT Id FROM Contact];
      Test.stopTest();
      // THEN
      Assert.isTrue(accts.size() > 0, 'Was expecting to find at least one account');
      Assert.areEqual(5, contacts.size(), 'Was expecting to find 5 contacts');
    }
  5. [File (ファイル)] > [Save (保存)] をクリックします。
  6. 作業中のファイルを右クリックして、[SFDX: Deploy Source To Org (SFDX: 組織にソースをリリース)] を選択します。
  7. 先ほど作成してリリースした Apex クラスの testUseTestFactoryToCreateAccountsWithContacts メソッドに表示される [Run Test (テストを実行)] ボタンをクリックします。

コードのポイント

最初のテストと同様に、テストでテストデータが作成されていることを確認します。ただし、この場合は、テストファクトリクラスを使用してデータを作成します。 

TestSetup メソッド

私たちはテストを作成する際、できるだけ簡潔にして、実行しやすくしたいと考えます。データの作成をテストファクトリに切り離せばわかりやすくなりますが、さらに一歩進めることができます。

通常、同じクラスの複数のテストメソッドにはよく似たデータ要件が設定されています。このため、Lightning プラットフォームでは、テストクラスのメソッドに @TestSetup メソッドというアノテーションを付ける方法が用意されています。プラットフォームは、個々のテストメソッドの前にこうしたメソッドを自動的にコールします。クラスの各テストメソッドの前にこのメソッドがコールされるため、テストデータを作成する場合は極めて有用です。ただし、各テストメソッドの実行後にデータがリセットされます。 

では、testSetup メソッドを作成しましょう。

  1. VS Code の DataGenerationTests クラスに戻ります。
  2. ファイルの上部の private という行のすぐ下に、次の設定メソッドを追加します。
    @TestSetup
    static void dataCreation() {
      // GIVEN
      Account a = TestFactory.getAccount('Muddy Waters Inc.', true);
      Contact c = TestFactory.getContact(a.id, 'Muddy', 'Waters', true);
      Opportunity opp = New Opportunity();
      opp.name = 'Long lost record';
      opp.accountId = a.id;
      opp.closeDate = Date.today().addDays(14);
      opp.stageName = 'prospecting';
      insert opp;
    }
  3. [File (ファイル)] > [Save (保存)] をクリックします。
  4. 作業中のファイルを右クリックして、[SFDX: Deploy Source To Org (SFDX: 組織にソースをリリース)] を選択します。
  5. 前のステップと同様に、testUseTestFactoryToCreateAccountsWithContacts メソッドに表示される [Run Test (テストを実行)] ボタンをクリックします。

おっと、この @TestSetup メソッドを追加したら、2 つ目のテストメソッドが破損してしまいました。具体的には、アサーションに失敗し、「Assertion Failed: Was expecting to find 5 contacts. (アサーションに失敗しました: 5 人の取引先責任者が見つかると想定していました)」というエラーメッセージが表示されます。 

プラットフォームがテストメソッドを実行する前に、@TestSetup メソッドが取引先責任者を作成したため、テストに失敗しました。テストのクエリで、5 人ではなく、その取引先責任者にテストメソッドが作成した 5 人の取引先責任者を加算した 6 人の取引先責任者が見つかったためです。レコードが増えていることから、実際にテストメソッドを実行する前に、プラットフォームが @TestSetup メソッドを実行したことがわかります。また、@TestSetup メソッドでテスト用のレコードを作成可能であることも示されています。 

失敗したテストを修正するには、アサーションを 5 ではなく 6 に変更します。

  1. VS Code の DataGenerationTests クラスに戻ります。

  2. Assert.areEqual(5, contacts.size(), 'Was expecting to find 5 contacts'); というコード行を見つけます。
  3. このコード行を次のように変更して、取引先責任者数を 6 人に指定します。
    Assert.areEqual(6, contacts.size(), 'Was expecting to find 6 contacts');
  4. [File (ファイル)] > [Save (保存)] をクリックします。
  5. 作業中のファイルを右クリックして、[SFDX: Deploy Source To Org (SFDX: 組織にソースをリリース)] を選択します。
  6. 前のステップと同様に、testUseTestFactoryToCreateAccountsWithContacts メソッドに表示される [Run Test (テストを実行)] ボタンをクリックします。

コードのポイント

この testSetup メソッドはごく基本的なものですが、すでに実行したこと、つまり、テストファクトリを使用してデータを生成することが組み込まれています。 

では、新しい testMethod を追加して、商談を見つけましょう。

  1. VS Code の DataGenerationTests クラスに戻ります。
  2. 次のコードで新しいテストメソッドを作成します。
    @IsTest
    static void testAtTestSetupMethodsRule() {
      // WHEN
      List<Opportunity> opps = [SELECT Id, AccountId FROM Opportunity];
      // THEN
      Assert.areEqual(1, opps.size(), 'Expected test to find a single Opp');
    }
  3. [File (ファイル)] > [Save (保存)] をクリックします。
  4. 作業中のファイルを右クリックして、[SFDX: Deploy Source To Org (SFDX: 組織にソースをリリース)] を選択します。
  5. testAtTestSetupMethodsRule メソッドに表示される [Run Test (テストを実行)] ボタンをクリックします。

コードのポイント

この 3 つ目のテストメソッドは、データを作成していないのに合格します。このテストメソッドでは、プラットフォームによって @TestSetup メソッドが事前に実行され、テストに合格するために必要な商談が作成されるためです。@TestSetup メソッドでテストデータが作成される場合も、テスト内でそのデータを照会する必要があります。@TestSetup メソッドを初めて使用するときに、この点で混乱することがあります。

CSV データファイル

testSetup メソッドを使用すると、簡潔で的を絞ったテストになりますが、テストデータを使用してさらに一歩進めることができます。CSV ファイルを静的リソースとして作成してアップロードし、その CSV から直接テストデータを生成できます。 

コードを 1 行も変更しなくても、テストの範囲を拡張できるシナリオを想像してみてください。CSV データを使用すれば、コードをリリースせずに、コードで処理するデータ入力を追加または変更できます。 

  1. Visual Studio Code を使用して、次のコードをファイルに貼り付け、accountData.csv として保存します。
    Name,Website,Phone,BillingStreet,BillingCity,BillingState,BillingPostalCode,BillingCountry
    sForceTest1,http://www.sforcetest1.com,(415) 901-7000,The Landmark @ One Market,San Francisco,CA,94105,US
    sForceTest2,http://www.sforcetest2.com,(415) 901-7000,The Landmark @ One Market Suite 300,San Francisco,CA,94105,US
    sForceTest3,http://www.sforcetest3.com,(415) 901-7000,1 Market St,San Francisco,CA,94105,US
  2. [Setup (設定)] で、[Quick Find (クイック検索)] ボックスに Static Resources (静的リソース) と入力し、[Static Resources (静的リソース)] を選択します。
  3. [New (新規)] をクリックします。
  4. 静的リソースに accountData という名前を付けます。
  5. [Choose File (ファイルを選択)] をクリックし、[accountData.csv] を選択します。
  6. [Cache Control (キャッシュコントロール)][Public (公開)] を選択します。
  7. [Save (保存)] をクリックします。

次に、VS Code で新しいテストクラスを作成します。

  1. VS Code を開きます。
  2. [Explorer (エクスプローラー)] サイドバーで、classes フォルダーを右クリックし、[SFDX: Create Apex Class (SFDX: Apex クラスを作成)] を選択します。クラスに CSVTests と名前を付け、その内容を次のコードに置き換えます。
    @IsTest
    private class CSVTests {
      @TestSetup
      static void loadTestDataFromStaticResource() {
        // GIVEN
        List<sObject> accounts = Test.loadData(Account.SObjectType, 'accountData');
      }
      @IsTest
      static void testLoadAccountsFromStaticResource() {
        // WHEN
        List<Account> accts = [SELECT ID FROM Account];
        // THEN
        Assert.isTrue(accts.size() == 3, 'Expected 3 accounts');
      }
    }
  3. [File (ファイル)] > [Save (保存)] をクリックします。
  4. 作業中のファイルを右クリックして、[SFDX: Deploy Source To Org (SFDX: 組織にソースをリリース)] を選択します。
  5. testLoadAccountsFromStaticResource メソッドに表示される [Run Test (テストを実行)] ボタンをクリックします。

コードのポイント

このコードも @TestSetup メソッドを使用します。ただし、testFactory を使用したり、ブルートフォースしたりするのではなく、CSV ファイルを読み込むだけです。このため、テストが極めてクリーンになり、コードをリリースしなくても、テストデータを追加または変更できます。

リソース

ハンズオン Challenge

+500 ポイント

準備を始めましょう

この 単元 は各自のハンズオン組織で実行します。[起動] をクリックして開始するか、組織の名前をクリックして別の組織を選びます。

あなたの Challenge

Create tests that load data from a CSV in @TestSetup method
Create and run a test class that uses a @TestSetup method.

To get started

  • Download this CSV file.
  • Upload the CSV file as a static resource named otherAccountData.
  • Create a new Test Class named MyDataGenerationTests.
  • Create a @TestSetup method that loads the otherAccountData CSV into Accounts.
  • Create a test method called testLoadOtherAccountsFromStaticResource that asserts the presence of 15 accounts.
Salesforce ヘルプで Trailhead のフィードバックを共有してください。

Trailhead についての感想をお聞かせください。[Salesforce ヘルプ] サイトから新しいフィードバックフォームにいつでもアクセスできるようになりました。

詳細はこちら フィードバックの共有に進む