Skip to main content

Apex テストのテストデータを作成する

学習の目的

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

  • テストユーティリティクラスを作成する。
  • テストユーティリティメソッドを使用してさまざまなテストケースのテストデータを設定する。
  • クラスのすべてのテストメソッドを実行する。
メモ

メモ

このバッジのハンズオン Challenge は日本語、スペイン語 (LATAM)、ポルトガル語 (ブラジル) に対応しています。Playground の言語を変更するには、こちらの指示に従ってください。日本語等、翻訳された言語と英語に差異がある可能性があります。英語以外の言語での指示に従って Challenge に合格できなかった場合は、[言語] と [地域] をそれぞれ [English]、[アメリカ合衆国] に切り替えてからもう一度お試しください。

Apex テストのテストデータを作成する

テストユーティリティクラスを使用して、テストデータ設定のために再利用可能なメソッドを追加します。

前提条件

前の単元の「Apex トリガーをテストする」の前提条件の操作を完了します (まだ完了していない場合)。

テストユーティリティクラスを追加する

テストデータ作成をユーティリティクラスメソッドへのコールに置き換えて、前のテストメソッドをリファクタリングしましょう。最初に、テストユーティリティクラスを作成する必要があります。

TestDataFactory クラスは、特殊な種類のクラスです。@isTest アノテーションが付加された公開クラスで、実行中のテストからのみアクセスできます。テストユーティリティクラスには、テストメソッドからコールしてテストデータの設定などの便利なタスクを実行できるメソッドが含まれます。テストユーティリティクラスは、組織のコードサイズ制限から除外されます。

TestDataFactory クラスを追加する手順は、次のとおりです。

  1. 開発者コンソールで、[File (ファイル)] | [New (新規)] | [Apex Class (Apex クラス)] をクリックし、クラス名に TestDataFactory と入力し、[OK] をクリックします。
  2. デフォルトのクラス本文を次のコードで置き換えます。
    @isTest
    public class TestDataFactory {
      public static List<Account> createAccountsWithOpps(Integer numAccts, Integer numOppsPerAcct) {
        List<Account> accts = new List<Account>();
        for(Integer i=0;i<numAccts;i++) {
          Account a = new Account(Name='TestAccount' + i);
          accts.add(a);
        }
        insert accts;
        List<Opportunity> opps = new List<Opportunity>();
        for(Integer j=0;j<numAccts;j++) {
          Account acct = accts[j];
          // For each account just inserted, add opportunities
          for(Integer k=0;k<numOppsPerAcct;k++) {
            opps.add(new Opportunity(Name=acct.Name + ' Opportunity ' + k,
              StageName='Prospecting',
              CloseDate=System.today().addMonths(1),
              AccountId=acct.Id));
          }
        }
        // Insert all opportunities for all accounts.
        insert opps;
        return accts;
      }
    }

このテストユーティリティクラスには 1 つの静的メソッド createAccountsWithOpps() が含まれます。このメソッドは取引先数 (numAccts パラメーターに保持) と取引先ごとに作成する関連商談数 (numOppsPerAcct パラメーターに保持) を受け入れます。メソッドの最初のループでは、指定された数の取引先を作成し、accts リスト変数に保存します。最初のループの後、insert() DML ステートメントがコールされて、リスト内のすべての取引先をデータベース内に作成します。

2 つ目のループでは商談を作成します。各商談グループは、1 つの取引先にリンクしているため、外部ループは取引先を反復処理し、その中にネストされたループでは、現在の取引先の関連商談を作成します。次回ネストループが実行されるとき、add() メソッドを使用して商談が同じリストに追加されます。商談は、AccountId 項目を使用して親取引先にリンクされます。作成されるすべての商談の合計数は、商談数と取引先数の積 (numOppsPerAcct*numAccts) になります。次に、insert() DML ステートメントをループ外で効率的にコールし、すべての取引先についてコレクション内のすべての商談を 1 回のコールのみで作成します。

最後に、このメソッドは新規取引先のリストを返します。

メモ

このメソッドでは関連商談は返されませんが、それらのレコードを取得するには、「Apex トリガーのテスト」のトリガーで使用したクエリのような、Account と Opportunity 間の既存のリレーションを利用する SOQL クエリを作成します。

テストデータ作成用のユーティリティメソッドをコールする

テストユーティリティクラスを追加したところで、次はこのクラスを利用するように TestAccountDeletion テストクラスを変更します。TestDataFactory.createAccountsWithOpps(1,1) コールから返される配列には 1 つの Account sObject が含まれます。

変更されたテストメソッドは次のようになります。より短いバージョンです。

@isTest

private class TestAccountDeletion {

  @isTest

  static void TestDeleteAccountWithOneOpportunity() {

    // Test data setup

    // Create one account with one opportunity by calling a utility method

    Account[] accts = TestDataFactory.createAccountsWithOpps(1,1);

    // Perform test

    Test.startTest();

      Database.DeleteResult result = Database.delete(accts[0], false);

    Test.stopTest();

    // Verify that the deletion should have been stopped by the trigger,

    // so check that we got back an error.

    System.assert(!result.isSuccess());

    System.assert(result.getErrors().size() > 0);

    System.assertEquals('Cannot delete account with related opportunities.',

      result.getErrors()[0].getMessage());

  }

}

さまざまな条件でテストする

トリガーに対して可能性のあるすべての入力をテストするには、1 つのテストメソッドでは不十分です。商談のない取引先が削除される場合など、他の条件もテストする必要があります。また、1 件のレコードだけでなく、大量のレコードで同じシナリオをテストする必要もあります。3 つのテストメソッドが追加されたテストクラスの更新バージョンを次に示します。この更新バージョンのクラスを保存します。

@isTest

private class TestAccountDeletion {

  @isTest

  static void TestDeleteAccountWithOneOpportunity() {

    // Test data setup

    // Create one account with one opportunity by calling a utility method

    Account[] accts = TestDataFactory.createAccountsWithOpps(1,1);

    // Perform test

    Test.startTest();

      Database.DeleteResult result = Database.delete(accts[0], false);

    Test.stopTest();

    // Verify that the deletion should have been stopped by the trigger,

    // so check that we got back an error.

    System.assert(!result.isSuccess());

    System.assert(result.getErrors().size() > 0);

    System.assertEquals('Cannot delete account with related opportunities.',

      result.getErrors()[0].getMessage());

  }

  @isTest

  static void TestDeleteAccountWithNoOpportunities() {

    // Test data setup

    // Create one account with no opportunities by calling a utility method

    Account[] accts = TestDataFactory.createAccountsWithOpps(1,0);

    // Perform test

    Test.startTest();

      Database.DeleteResult result = Database.delete(accts[0], false);

    Test.stopTest();

    // Verify that the deletion was successful

    System.assert(result.isSuccess());

  }

  @isTest

  static void TestDeleteBulkAccountsWithOneOpportunity() {

    // Test data setup

    // Create accounts with one opportunity each by calling a utility method

    Account[] accts = TestDataFactory.createAccountsWithOpps(200,1);

    // Perform test

    Test.startTest();

      Database.DeleteResult[] results = Database.delete(accts, false);

    Test.stopTest();

    // Verify for each record.

    // In this case the deletion should have been stopped by the trigger,

    // so check that we got back an error.

    for(Database.DeleteResult dr : results) {

      System.assert(!dr.isSuccess());

      System.assert(dr.getErrors().size() > 0);

      System.assertEquals('Cannot delete account with related opportunities.',

        dr.getErrors()[0].getMessage());

    }

  }

  @isTest

  static void TestDeleteBulkAccountsWithNoOpportunities() {

    // Test data setup

    // Create accounts with no opportunities by calling a utility method

    Account[] accts = TestDataFactory.createAccountsWithOpps(200,0);

    // Perform test

    Test.startTest();

      Database.DeleteResult[] results = Database.delete(accts, false);

    Test.stopTest();

    // For each record, verify that the deletion was successful

    for(Database.DeleteResult dr : results) {

      System.assert(dr.isSuccess());

    }

  }

}

すべてのテストメソッドを実行する

最後のステップでは、テストクラスのテストメソッドを実行します。クラスはより包括的なテストが含み、テストデータファクトリを使用するようにリファクタリングされています。TestAccountDeletion クラスのテストはすでに実行済みであるため、このテストクラスを再実行して、そのテストメソッドをすべて実行するだけです。

  1. 同じテストを実行するには、[Tests (テスト)] タブをクリックし、テスト実行を選択して、[Test (テスト)] | [Rerun (再実行)] をクリックします。
  2. [Tests (テスト)] タブで最新のテスト実行を展開して結果を確認します。テスト実行で 4 つのテストがすべて合格したとレポートされます。

リソース

無料で学習を続けましょう!
続けるにはアカウントにサインアップしてください。
サインアップすると次のような機能が利用できるようになります。
  • 各自のキャリア目標に合わせてパーソナライズされたおすすめが表示される
  • ハンズオン Challenge やテストでスキルを練習できる
  • 進捗状況を追跡して上司と共有できる
  • メンターやキャリアチャンスと繋がることができる