Apex の単体テスト
堅牢で、エラーのないコードの開発を促進するため、Apex は単体テストの作成と実行をサポートします。単体テストは、コード内の特定の部分が正しく機能していることを確認するクラスメソッドです。単体テストのメソッドは引数を取らず、データベースにデータをコミットせず、メールを送信しません。このメソッドは、メソッド定義内で @IsTest アノテーションでフラグ付けされます。単体テストメソッドは、テストクラス (@IsTest アノテーションが付加されているクラス) で定義されている必要があります。
1@IsTest
2private class myClass {
3 @IsTest
4 static void myTest() {
5 // code_block
6 }
7}アプリケーションのテストに使用するコードのみを含むクラスおよびメソッドを定義するには @IsTest アノテーションを使用します。@IsTest アノテーションでは、括弧で囲まれ空白で区切られた複数の修飾子を使用できます。
次のテストクラスの例には、2 つのテストメソッドが含まれています。
1@IsTest
2private class MyTestClass {
3
4 // Methods for testing
5 @IsTest
6 static void test1() {
7 // Implement test code
8 }
9
10 @IsTest
11 static void test2() {
12 // Implement test code
13 }
14
15}@IsTest として定義されたクラスとメソッドは private または public のいずれかと宣言する必要があります。テストクラスメソッドのアクセスレベルを考慮する必要はありません。テストクラスまたはテストメソッドを定義するときにアクセス修飾子を追加する必要はありません。Apex のデフォルトのアクセスレベルは非公開です。このテストフレームワークでは、アクセスレベルを問わず、常にテストメソッドを検索して、実行することができます。
@IsTest として定義されたクラスは最上位クラスである必要があるため、インターフェースまたは列挙値とすることはできません。
テストクラスのメソッドは、テストメソッドまたはテストメソッドから呼び出されるコードからのみコールすることができます。テスト以外の要求から呼び出すことはできません。
この例では、テストするクラスおよび対応するテストクラスを示します。この例には、2 つのメソッドとコンストラクターが含まれています。
1public class TVRemoteControl {
2 // Volume to be modified
3 Integer volume;
4 // Constant for maximum volume value
5 static final Integer MAX_VOLUME = 50;
6
7 // Constructor
8 public TVRemoteControl(Integer v) {
9 // Set initial value for volume
10 volume = v;
11 }
12
13 public Integer increaseVolume(Integer amount) {
14 volume += amount;
15 if (volume > MAX_VOLUME) {
16 volume = MAX_VOLUME;
17 }
18 return volume;
19 }
20
21 public Integer decreaseVolume(Integer amount) {
22 volume -= amount;
23 if (volume < 0) {
24 volume = 0;
25 }
26 return volume;
27 }
28
29 public static String getMenuOptions() {
30 return 'AUDIO SETTINGS - VIDEO SETTINGS';
31 }
32
33}この例には、4 つのテストメソッドを持つ対応するテストクラスが含まれています。前のクラスの各メソッドがコールされています。テストカバー率は十分ですが、テストクラスのテストメソッドでは、追加のテストを実行して境界の条件を確認します。
1@IsTest
2class TVRemoteControlTest {
3 @IsTest
4 static void testVolumeIncrease() {
5 TVRemoteControl rc = new TVRemoteControl(10);
6 Integer newVolume = rc.increaseVolume(15);
7 System.assertEquals(25, newVolume);
8 }
9
10 @IsTest
11 static void testVolumeDecrease() {
12 TVRemoteControl rc = new TVRemoteControl(20);
13 Integer newVolume = rc.decreaseVolume(15);
14 System.assertEquals(5, newVolume);
15 }
16
17 @IsTest
18 static void testVolumeIncreaseOverMax() {
19 TVRemoteControl rc = new TVRemoteControl(10);
20 Integer newVolume = rc.increaseVolume(100);
21 System.assertEquals(50, newVolume);
22 }
23
24 @IsTest
25 static void testVolumeDecreaseUnderMin() {
26 TVRemoteControl rc = new TVRemoteControl(10);
27 Integer newVolume = rc.decreaseVolume(100);
28 System.assertEquals(0, newVolume);
29 }
30
31 @IsTest
32 static void testGetMenuOptions() {
33 // Static method call. No need to create a class instance.
34 String menu = TVRemoteControl.getMenuOptions();
35 System.assertNotEquals(null, menu);
36 System.assertNotEquals('', menu);
37 }
38}単体テストの考慮事項
単体テストでは、次の点に留意してください。
- Salesforce API 28.0 からは、テストメソッドは非テストクラスに含めることができなくなります。また、IsTest アノテーションが付加されているクラスの一部である必要があります。テストクラスから private クラスのメンバーにアクセスする方法については、TestVisible アノテーションを参照してください。
- テストメソッドは、Web サービスコールアウトのテストには使用できません。代わりに、疑似コールアウトを使用します。「Web サービスコールアウトのテスト」および「HTTP コールアウトのテスト」を参照してください。
- テストメソッドからメールメッセージを送信することはできません。
- テストメソッドはテストで作成したデ���タをコミットしないため、完了時にテストデータを削除する必要はありません。
- テストクラスの静的メンバー変数の値が testSetup またはテストメソッドで変更されている場合は、新しい値が保持されません。このクラスの他のテストメソッドは、静的メンバー変数の元の値を取得します。この動作は、静的メンバー変数が別のクラスで定義され、テストメソッドでアクセスされる場合にも適用されます。
- 一意制約のある項目を含む一部の sObject では、重複する sObject レコードを挿入するとエラーになります。たとえば、同じ名前の複数の CollaborationGroup sObject を挿入すると、CollaborationGroup レコードには一意の名前が必要なためエラーになります。
- Chatter フィードのレコードの追跡変更 (FeedTrackedChange レコード) は、テストメソッドが関連レコードを変更すると、使用できません。FeedTrackedChange レコードでは、作成される前に、関連付けられている親レコードへの変更がデータベースにコミットされている必要があります。テストメソッドではデータをコミットしないため、FeedTrackedChange レコードの作成はできません。同様に、項目履歴管理レコードは、他の sObject レコードを最初にコミットする必要があるため、テストメソッドでは作成できません。たとえば、AccountHistory レコードは、Account レコードを最初にコミットする必要があるため、テストメソッドでは作成できません。
- テストに DML が含まれている場合、絶対に MAX_DML_ROWS の制限を超えないでください。「実行ガバナと制限」の「その他の Apex の制限」を参照してください。