より堅牢な Apex テストの作成およびより柔軟なテストの実行

Apex テストおよびテストの実行方法に多くの改善が加えられました。

よく使用される Apex テストクラスのテストスイートの作成

多くの場合、定期的にまとめて実行する Apex テストクラスのセットがあります。たとえば、リリースの準備をするたび、または Salesforce が新しいバージョンをリリースするたびに実行するテストクラスなどがあります。これらのクラスのセットを含むテストスイートを作成できるようになりました。テスト実行を開始するたびにすべての関連クラスを選択する代わりに、単に 1 つ以上のテストスイートを実行できます。この機能は、Lightning ExperienceSalesforce Classic の両方で使用できます。

開発者コンソールでのテストスイートの作成と実行

開発者コンソールを使用してテストスイートを作成するには、[Test (テスト)] | [New Suite (新規スイート)] を選択します。テストスイートに含めるクラスを選択するには、[Test (テスト)] | [Suite Manager (スイートマネージャ)] | Your Test Suite (あなたのテストスイート) | [Edit Suite (スイートを編集)] を選択します。開発者コンソールを使用して、最大 200 個のテストクラスを含むテストスイートを作成または変更できます。

開発者コンソールから 1 つ以上のテストスイートのメンバークラスを実行するには、[Test (テスト)] | [New Suite Run (新規スイートの実行)] を選択します。

API でのテストスイートの作成と実行

各テストスイートは、TestSuiteName と ID を含む ApexTestSuite オブジェクトによって SOAP、REST、および Tooling API で表されます。それぞれに ApexTestSuiteIdApexClassId が含まれる TestSuiteMembership オブジェクトのセットによって、テストスイートのメンバーシップが決まります。各テストスイートに追加するクラスごとに 1 つの TestSuiteMembership オブジェクトを作成します。テストスイートからテストクラスを削除するには、その TestSuiteMembership オブジェクトを削除します。

次の SOQL クエリは、この Apex クラスをこのテストスイートに関連付けるメンバーシップオブジェクトを返します。
SELECT Id FROM TestSuiteMembership WHERE ApexClassId = '01pD0000000Fhy9IAC'
    AND ApexTestSuiteId = '05FD00000004CDBMA2'

Tooling REST API を使用してテストスイートを実行するには、suiteids リストを runTestsAsynchronous REST リソースに POST します。suiteids リストと classids リストの両方を runTestsAsynchronous に POST できます。ただし、tests 配列を送信する場合、suiteidsclassids は送信できません。

Tooling SOAP API を使用してテストスイートを実行するには、スイート ID を runTestsAsynchronous() SOAP コールに渡します。runTestsAsynchronous には classids または suiteids パラメータが必須ですが、2 つのうちいずれかのみが必要です。1 つのみを提供するには、もう一方を null として指定します。

失敗するテスト実行の停止

多数の Apex テストを実行すると、予想以上に時間がかかることがあります。実行の終了を待ってから、多くのテストに失敗したことが判明することは望ましくありません。指定した数のテストに失敗したら新しいテストの実行を停止するように、テスト実行を設定できるようになりました。テストの実行結果を待ち、無駄な時間を費やす必要がなくなりました。後日組織で問題を修正した後に、テストを再実行することになるわけですから。開発者コンソールTooling API の両方で実行するテスト実行で、テストの失敗が許容される回数を設定できます。この機能は、Lightning ExperienceSalesforce Classic の両方で使用できます。

テスト失敗しきい値の選択

組織ですべてのテストを実行できるようにするには、テスト失敗しきい値を設定しないか、しきい値を -1 に設定します。指定した数のテストに失敗した後に新しいテストの実行を停止するには、失敗しきい値を 01,000,000 の整数値に設定します。この整数値で、許容されるテスト失敗の最大数を設定します。値を 0 に設定すると、1 回の失敗でテスト実行が停止されます。値を 1 に設定すると、2 回目の失敗でテスト実行が停止されます。以降も同様に処理されます。

同期テスト実行は、失敗しきい値を超えたときに停止します。ただし、非同期テスト実行ではテストが並列実行されるため、停止するまでに若干時間がかかります。非同期テスト実行は、失敗しきい値を超えたときに進行中のテストの実行が終了した後に停止します。

大きい値にすると、パフォーマンスが低下する可能性があることに注意してください。失敗が許容される 1,000 件のテストごとに約 3 秒がテスト実行に追加されます。これにはテストの実行にかかる時間は含まれません。

開発者コンソールでの許容されるテスト失敗数の設定

開発者コンソールのテスト実行設定ペインには、新しい [Settings (設定)] ボタンがあります。テスト実行またはテストスイート実行がキャンセルされる前に許容されるテスト失敗数を指定するには、[Settings (設定)] をクリックし、[Number of failures allowed (許容可能な失敗回数)] に値を入力してから [OK] をクリックします。この値は、開発者コンソールを閉じるか新しい値を設定するまで、すべてのテスト実行に適用されます。

Tooling API を使用した maxFailedTests の設定

Tooling API REST リソースまたは SOAP コールの maxFailedTests 値を設定できます。REST を使用するには、任意の maxFailedTests パラメータを runTestsAsynchronous リソースに POST します。SOAP を使用して同期テスト実行での失敗テスト数を制限するには、RunTestsRequest.maxFailedTests の値を runTests() コールに送信します。SOAP を使用して非同期テスト実行での失敗テスト数を制限するには、-1 より大きい maxFailedTests 値を runTestsAsynchronous() コールに送信します。

Apex テストでの CreatedDate 項目の設定と変更

IdeaExchange でのユーザからのリクエストに応えて、System.Test.setCreatedDate メソッドが追加されました。このメソッドは、テストコンテキスト sObject の CreatedDate 項目の日時値を設定します。
次の例のように、CreatedDate を設定する前にテストレコードを挿入します。
@isTest 
private class SetCreatedDateTest {
    static testMethod void testSetCreatedDate() {
        Account a = new Account(name='myAccount');
        insert a;
        Test.setCreatedDate(a.Id, DateTime.newInstance(2012,12,12));
        Test.startTest();
        Account myAccount = [SELECT Id, Name, CreatedDate FROM Account 
                             WHERE Name ='myAccount' limit 1];
        System.assertEquals(myAccount.CreatedDate, DateTime.newInstance(2012,12,12));
        Test.stopTest();
    }
}

Apex テストで確実に制限をリセットするための Test.startTest() のコール

Test.startTest() メソッドと Test.stopTest() メソッドで囲まれたテストコードのブロックで、ガバナ制限の独自のブロックを確実に受信できるようになりました。Test.startTest() は、トランザクション単位の制限カウンタを保存し、カウンタを一時的に 0 にリセットします。Test.stopTest() は、制限カウンタを Test.startTest() 前の値に戻します。テストメソッドが完了すると、すべてのトランザクション単位の制限は 0 にリセットされます。以前は、SOQL クエリなどの場合の一部の制限は、Test.startTest()/Test.stopTest() ブロック内ではリセットされないことがありました。

Apex テストでの重大な MIXED_DML_OPERATION エラーを回避するための @future の使用

単一トランザクション内の混合データ操作言語 (DML) 操作は許可されていません。同じトランザクション内で設定の sObject と設定以外の sObject に対する DML は実行できません。代わりに、非同期ジョブの一部として 1 つのデータ型の DML を実行し、別の非同期ジョブまたは元のトランザクションで他のデータ型を実行できます。この代替方法は広く使用されています。ただし、この代替方法が Apex テストのコンテキスト内で使用された場合、エラーが発生していました。このバグは修正されました。

この例は、以前はテストコンテキストでは機能しませんでしたが、機能するようになりました。UserAndContactTest.testUserAndContact() で future メソッド InsertFutureUser.insertUser() をコールしてユーザを挿入します。次に、UserAndContactTest.testUserAndContact() で取引先責任者を挿入します。

@isTest
public class UserAndContactTest {
    public testmethod static void testUserAndContact() {
        InsertFutureUser.insertUser();
        Contact currentContact = new Contact(
            firstName = String.valueOf(System.currentTimeMillis()),
            lastName = 'Contact');
        insert(currentContact);
    }
}
public class InsertFutureUser {
    @future
    public static void insertUser() {
        Profile p = [SELECT Id FROM Profile WHERE Name='Standard User'];
        UserRole r = [SELECT Id FROM UserRole WHERE Name='COO'];
        User futureUser = new User(firstname = 'Future', lastname = 'User',
            alias = 'future', defaultgroupnotificationfrequency = 'N',
            digestfrequency = 'N', email = 'test@test.org',
            emailencodingkey = 'UTF-8', languagelocalekey='en_US', 
            localesidkey='en_US', profileid = p.Id, 
            timezonesidkey = 'America/Los_Angeles',
            username = 'futureuser@test.org',
            userpermissionsmarketinguser = false,
            userpermissionsofflineuser = false, userroleid = r.Id);
        insert(futureUser);
    }
}

Apex テストでの通貨と小数の比較

Apex テストで通貨値と小数値を比較するときに例外が発生するバグが修正されました。通貨値と小数値の両方が含まれるデータサイロを使用して、それらのデータ型を関心のあるコンテンツと比較できるようになりました。

WSDL ベースの非同期コールアウトのテスト

以前は、WSDL ベースの同期コールアウトまたは WSDL ベース以外の非同期コールアウトをテストできました。ただし、インポートした WSDL から行われた非同期コールアウトをテストすると、テストが内部 Salesforce エラーで失敗していました。このバグは修正されました。