2021/06/7

Salesforceテストクラスって何?設定方法や注意点をサンプルを用いてご紹介

 
  

Salesforceにおけるテストクラスとは

Salesforceにおけるテストクラスの概要について、サンプルコードを用いて説明します。今回のサンプルコードでは、テストカバー率が100%になるようにします。まず、サンプルコードを作成する前の手順から説明します。 「設定」という項目から「Quick Find (クイック検索)」というボックスに「Apex Classes (Apex クラス)」と入力し、「Apex Classes (Apex クラス)」を選びます。「New (新規)」を選択し、クラスエディタでクラスを定義しましょう。

Salesforceのテストクラスの概要

Salsforceにおけるテストクラスとは、作成したApexクラスが正しく動くのかどうか確認する機能のことです。テストクラスで品質を確認するときは、コードカバー率が100%になるようにします。 単体テストでもコードカバー率が100%を超えていて、テストクラスのすべてのメソッドを正しく動かせれば、リリースが可能です。Salesforceでは、Apexクラスを書ければ、テストクラスを書くことができます。 テストクラスは、開発の品質保証のために行うものです。本番適応の際に異常が出ないかどうか確認します。例を用いた説明はサンプルコードを使用し、概要の章で説明します。

サンプルコードの説明とコード

サンプルコードでは、最初にテストクラスで使う@setupアノテーションが含まれているメソッドで、テストデータを作ります。次にテストデータを自由に追加できるテストメソッド1を作ります。3つ目のメソッドでテストデータを更新です。
@isTest
private class testclass{

    // テストデータを作成するメソッド
    @testSetup
    static void setup() {

        List testAccts = new List();
        for ( Integer i=0;i<2;i++ ) {
            testAccts.add(new Account(Name = 'MyTestAccount'+i, Phone ='333-878'+i));
        }
        insert testAccts;
    }

// テストメソッド1
    @isTest
    static void testMethod1() {

        //更新後の電話番号を確認
        Account acc0 = [SELECT Id,Phone FROM Account WHERE Name ='MyTestAccount0' LIMIT 1];
        acc0.Phone = '888-1515';
        update acc0;

        Account acc1 = [SELECT Id,Phone FROM Account WHERE Name ='MyTestAccount1' LIMIT 1];
        acc1.Phone = '999-1515';
        update acc1;

        System.debug('●acc0.Phone● = '+ acc0.Phone);
        System.debug('●acc1.Phone● = '+ acc1.Phone);

    }

テストメソッド2

次にテストメソッド2を作成します。@setupで作成したテストデータを5つ目のメソッドで取得するのです。最後のメソッドで、Test.startTest〜Test.stopTest間でガバナ制限がリセットされているか確認します。以下サンプルコードになります。
 //テストメソッド2
    @isTest
    static void testMethod2() {

        List accList = new List();

        Account acc0 = [SELECT Id, Phone FROM Account WHERE Name ='MyTestAccount0' LIMIT 1];
        Account acc1 = [SELECT Id, Phone FROM Account WHERE Name ='MyTestAccount1' LIMIT 1];

テストデータ取得

テストデータを取得します。
//テストデータを取得
        System.debug('Account0.Phone='+ acc0.Phone +', Account1.Phone='+acc1.Phone);

        accList.add(acc0);
        accList.add(acc1);

        //getDMLStatementsでDML実行回数を確認
        System.debug('●Start前●' + Limits.getDMLStatements() + '/' + Limits.getLimitDMLStatements());

        System.Test.startTest();
        System.debug('●Start後●' + Limits.getDMLStatements() + '/' + Limits.getLimitDMLStatements());
        Database.DeleteResult[] results = Database.delete(accList, false);
        System.Test.stopTest();

        System.debug('●Stop後●' + Limits.getDMLStatements() + '/' + Limits.getLimitDMLStatements());

    }
}

単体テスト作成

単体テストの場合、通常のテストクラスと同様に「設定」から「Quick Find (クイック検索)」というボックスに「Apex Classes (Apex クラス)」と入力し、「Apex Classes (Apex クラス)」を選びます。「New (新規)」を選択し、クラスエディタでクラスを定義しましょう。 単体テストの際は、1つ目のメソッド内が、public with sharingになっていた場合、privateにします。サンプルコードでは、入力値の華氏温度を摂氏温度に変換して結果を返すのです。今回は、3つのテストクラスで行います。以下サンプルコードになります。
@isTest
private class TaskUtilTest {
    @isTest static void testTaskPriority() {
        String pri = TaskUtil.getTaskPriority('NY');
        System.assertEquals('Normal', pri);
    }

    @isTest static void testTaskHighPriority() {
        String pri = TaskUtil.getTaskPriority('CA');
        System.assertEquals('High', pri);
    }

    @isTest static void testTaskPriorityInvalid() {
        String pri = TaskUtil.getTaskPriority('Montana');
        System.assertEquals(null, pri);
    }
}

Salesforceにおけるテストクラスの注意点

Salesforceのテストクラスについていくつか注意点を説明します。テストクラスでは、小さな単位のメソッドの呼び出しをメインとし、テストデータの登録の際、トリガはスキップできるものにすることが大切です。 テストクラスで、テストデータを作ることを避けることはできません。しかし、テストクラス用のデータ作成時のトリガがエラーを起こすなど邪魔になることがあります。トリガの処理テストでない場合は、トリガをスキップする処理を書きましょう。 また、カスタムウェブサービスのときはメソッドを実行し、トリガの場合は必要なマスタを用意します。対象となるオブジェクトレコードを作成、更新、削除などを実行します。 コントローラーはVisualforceページでパラメータを指定して、コントローラーのメソッドを実行するなどの手順でテストしていくことが多いですが、コードはできるだけ簡単にするとよいでしょう。

Salesforceのテストクラスに関する注意点のサンプルコード

サンプルです。

public class SampleController {

    public Case caseObj {get; set;}
    String caseId;

    public APC_CUS_200_ShinchokuDetailCtrl(){
      caseId =  ApexPages.currentPage().getParameters().get('caseId');
    }

    public void doinit(){
      caseObj = [Select Id  ,Type ,Origin ,Subject ,Priority ,ParentId ,AccountId
                 From Case where id = :caseId ];
    }

    public PageReference doSomething() {
      Account acc        = getAccount();
      Case    parentcase = getParentCase();

      doCheck(acc, parentcase);
    }



コントロールクラス

コントロールクラスの続きになります。
private Account getAccount(){
      if( caseObj.AccountId == nul ){
        return null;
      } else {
          return [Select  Id ,Name ,Industry
                  From Account where ID =:caseObj.AccountId][0];
      }
    }

    private Case getParentCase(){
      if( caseObj.ParentId == nul ){
        return null;
      } else {
          return [Select  Id  ,Type ,Origin ,Subject ,Priority
                  From Case where ID =:caseObj.ParentId][0];
      }
    }

コントロールクラスの続き

コントロールクラスの続きになります。
@TestVisible
    private void doCheck(Account acc,Case parentcase){

      if( caseObj.Origin != parentcase.Origin ){
        ・・・・・
      }

      if( acc.Industry == 'Education' && parentcase.Origin == 'Phone' ){
        ・・・・・
      }
    }
}

テストクラスのサンプルコード

テストクラスに関するサンプルコードになります。簡略化をしたコードの作成例です。
//テストクラス
@isTest
private class SampleControllerTest {

  static testMethod void testMethod01() {
    SampleController ctrl = new SampleController();

    Case caseobj    = new Case();
    Case parentcase = new Case();
    Account acc     = new Account();
    //必要なマスタの値のセットをする。

    ctrl.caseObj = caseobj;
    ctrl.doCheck(acc, parentcase);
  }
}

トリガスキップのサンプルコード

トリガスキップのサンプルコードになります。
//トリガスキップの例
//カスタム表示ラベルを制御する
trigger SampleiTrigger on Sample__c (after delete, after insert, after undelete, after update,
        before delete, before insert, before update) {


  if(System.Label.IKOFLAG == 'TRUE'){
    return;
  }
  //処理

ユーザプロファイルを制御するサンプルコード

ユーザプロファイルを制御する部分のサンプルコードです。
//ユーザプロファイルを制御する
trigger SampleiTrigger on Sample__c (after delete, after insert, after undelete, after update,
        before delete, before insert, before update) {

  User u = [select Profile.Name from User where Id =:Userinfo.getUserId()];

  if(u.Profile.Name == '移行'){
    return;
  }

カスタムオブジェクトの項目を制御するサンプルコード

カスタムオブジェクト項目の制御する処理になります。
//カスタムオブジェクト項目の制御する
trigger SampleiTrigger on Sample__c (after delete, after insert, after undelete, after update,
        before delete, before insert, before update) {

  Boolean triggerskip = false;

   for(   Sample__c s : Trigger.New ){
    if( s.TriggerSkipFlag__c ){
      triggerskip = true;
      //trueの場合、更新したトリガがスキップすることを防ぐため、フラグは常にfalseに戻す
      s.TriggerSkipFlag__c = false;
    }
  }

カスタムオブジェクトの項目を制御するサンプルコードの続き

フラグをたてて、トリガのスキップを細かく設定しましょう。
if ( triggerskip ){
    //afterトリガ用にstatic変数にトリガスキップのフラグをたてる。
    Cls_StaticValue.triggerskip = true;
  }

  if( triggerskip || Cls_StaticValue.triggerskip ){
    return;
  }

単体テストを作成する場合

単体テストを行う場合でもSalesforceで開発したApexクラスは単体テスト用のクラスで作成する必要があります。テストコードを作成しないと、本番でリリースできません。 開発したApexクラスは、単体テストでカバー率75%を超えるようにしなくてはなりません。また、Apexトリガはテストコードを用意する必要があります。単体テストに限らず、テストデータはユーティリティクラスか静的リソースを使用するとよいでしょう。 単体テストに限らず、System.debugはApexコードカバー率から外れます。テストメソッドでは、トランザクションを保持することができません。IsTest(SeeAllData=true)を使うと、組織のデータにアクセスすることも可能です。 しかし、価格表などのデータは他のメソッドを使用しないとアクセスができません。

Salesforceのテストクラスを活用しよう

今回は、Salesforceにおけるテストクラスについて紹介しました。Salesforceでテストクラスを作るときは、Apexを使用することで作成できます。テストクラスは、開発の品質確認をするための機能です。 本番適応の際に異常は出ないかどうか確認でき、トラブルを回避することができます。Apexで製品を開発するのに使用する機会も多いので、理解して活用できるようにしましょう。
]]>

ITエンジニアへのキャリアチェンジならキャリアチェンジアカデミー

この記事の監修者・著者

株式会社オープンアップITエンジニア
株式会社オープンアップITエンジニア
未経験からITエンジニアへのキャリアチェンジを支援するサイト「キャリアチェンジアカデミー」を運営。これまで4500人以上のITエンジニアを未経験から育成・排出してきました。
・AWS、salesforce、LPICの合計認定資格取得件数:2100以上(2023年6月時点)
・AWS Japan Certification Award 2020 ライジングスター of the Year 受賞

おすすめの動画

  • 【未経験からIT業界へ転職するなら】相談窓口とスキルの獲得はここで解決!IT転職が一気に有利に!【キャリアチェンジアカデミー】

  • 【費用一切不要】未経験からIT業界へ転職するならまずはここへ相談!【キャリアチェンジアカデミー】

  • 【何のエンジニアになれるのか?】未経験からITエンジニアを目指すとこんな道がある【キャリアチェンジアカデミー】