LoginSignup
26
19

More than 3 years have passed since last update.

Apexテストデータ作成の汎用化

Last updated at Posted at 2019-03-06

1.テストメソッドの雛形


@isTest
private class BatchAddressMasterTest {
    @isTest
    static void testXXX() {
        // テストユーザ作成
        User testUser = TestUtil.createUser('testUser');

        // ユーザモード
        System.runAs(testUser){
            /* ======テストデータ準備====== */
            // 各SObjectデータ作成

            /* ======テストメソッド起動====== */
            Test.startTest();
            // 対象メソッドを呼び出す
            Test.stopTest();

            /* ======結果検証====== */      
            // 実行結果と期待値の検証
        }
    }
}

2.テストデータ作成の汎用化イメージ図

image.png

3.TestUtility


/**
 * テストクラスの共通処理
 * 
 */
@isTest
public class TestUtility {
    /* ==================== */
    /*         雛形テストデータ作成
    /* ==================== */
    /** TestDataFactoryNewの共通処理 */
    /** テストデータパータン宣言 */
    public enum TestDataPattern {INIT_REQUIRED, INIT_ALL}

    /** カスタム例外 */
    private class TestDataFactoryException extends Exception {}

    /** 初期値設定 */
    public static InitValueSetting initValue = new InitValueSetting();
    public class InitValueSetting {
        public String nameValue; // Name:String
        public String urlValue; // URL:URL
        public Boolean checkboxValue; // チェックボックス:Boolean
        public String textValue; // テキスト:String
        public String textencryptedValue; // テキスト(暗号化):EncryptedString
        public String textareaValue; // テキストエリア:TextArea、リッチテキストエリア:TextArea、ロングテキストエリア:TextArea
        public Decimal percentValue; // パーセント:Percent
        public String mailValue; // メール:Email
        public Time timeValue; // 時間:TIME
        public Decimal numberValue; // 数値:Double、地理位置情報(Latitude):Double、地理位置情報(Longitude):Double
        public Decimal currencyValue; // 通貨:Currency
        public String phoneValue; // 電話:Phone
        public Date dateValue; // 日付:Date
        public Datetime datetimeValue; // 日付/時間:DateTime

        // インスタンス変数初期化
        {
            nameValue = '1';
            urlValue = 'https://www.salesforce.com';
            checkboxValue = FALSE;
            textValue = '1';
            textencryptedValue = '1';
            textareaValue = '1';
            percentValue = 1;
            mailValue = 'xxxxx@test.co.jp';
            timeValue = Time.newInstance(0, 0, 0, 0);
            numberValue = 1;
            currencyValue = 1;
            phoneValue = '03-5255-3410';
            dateValue = system.today();
            datetimeValue = Datetime.now();
        }
    }

    /**
     * @description オブジェクトインスタンスの初期化
     * @parameter Schema.SObjectType
     * @parameter TestDataPattern
     * @return sObject
     */
    public static sObject getInitSObjectInstance(Schema.SObjectType sObjectType, TestDataPattern ptn) {
        // テストデータパータンにの有効性チェック
        if (ptn != TestDataPattern.INIT_REQUIRED && ptn != TestDataPattern.INIT_ALL) {
            throw new TestDataFactoryException('テストデータパターン不明のため雛形データを作成できません。');
        }

        // sObjectのインスタンス作成
        sObject sObj = sObjectType.newSObject();

        Map<String, Schema.SObjectField> mapField = sObjectType.getDescribe().fields.getMap();
        for (SObjectField sObjField : mapField.values()) {
            Schema.DescribeFieldResult dfr = sObjField.getDescribe();

            // 現在のユーザが項目を編集できる場合、またはカスタムオブジェクトの主従関係項目である子レコードの親を別の親レコードに変更できる場合は true、できない場合は、false を返します。
            if (dfr.isUpdateable()) {
                // デフォルト値なし
                if (sObj.get(dfr.getSobjectField()) == null) {
                    // 必須項目のみ判定
                    if (ptn == TestDataPattern.INIT_REQUIRED && dfr.isNillable()) {
                        continue;
                    }

                    // 項目の初期値設定
                    initFieldValue(sObj, dfr);
                }
            }
        }

        return sObj;
    }

    /**
     * @description 項目の初期値設定
     * @parameter sObject
     * @parameter DescribeFieldResult
     * @return void
     */
    private static void initFieldValue(sObject sObj, DescribeFieldResult dfr) {
        // Name:String
        if (dfr.isNameField()) {
            sObj.put(dfr.getSObjectField(), initValue.nameValue);
            return;
        }

        // URL:URL
        if(dfr.getType()==Schema.DisplayType.URL){
            sObj.put(dfr.getSObjectField(), initValue.urlValue);
            return;
        }

        // チェックボックス:Boolean
        if(dfr.getType()==Schema.DisplayType.Boolean){
            sObj.put(dfr.getSObjectField(), initValue.checkboxValue);
            return;
        }

        // テキスト:String
        if(dfr.getType()==Schema.DisplayType.String){
            sObj.put(dfr.getSObjectField(), initValue.textValue);
            return;
        }

        // テキスト(暗号化):EncryptedString
        if(dfr.getType()==Schema.DisplayType.EncryptedString){
            sObj.put(dfr.getSObjectField(), initValue.textencryptedValue);
            return;
        }

        // テキストエリア:TextArea、リッチテキストエリア:TextArea、ロングテキストエリア:TextArea
        if(dfr.getType()==Schema.DisplayType.TextArea){
            sObj.put(dfr.getSObjectField(), initValue.textareaValue);
            return;
        }

        // パーセント:Percent
        if(dfr.getType()==Schema.DisplayType.Percent){
            sObj.put(dfr.getSObjectField(), initValue.percentValue);
            return;
        }

        // メール:Email
        if(dfr.getType()==Schema.DisplayType.Email){
            sObj.put(dfr.getSObjectField(), initValue.mailValue);
            return;
        }

        // 時間:Time
        if(dfr.getType()==Schema.DisplayType.Time){
            sObj.put(dfr.getSObjectField(), initValue.timeValue);
            return;
        }

        // 数値:Double、地理位置情報:(Latitude):Double、地理位置情報:(Longitude):Double
        if(dfr.getType()==Schema.DisplayType.Double){
            sObj.put(dfr.getSObjectField(), initValue.numberValue);
            return;
        }

        // 通貨:Currency
        if(dfr.getType()==Schema.DisplayType.Currency){
            sObj.put(dfr.getSObjectField(), initValue.currencyValue);
            return;
        }

        // 電話:Phone
        if(dfr.getType()==Schema.DisplayType.Phone){
            sObj.put(dfr.getSObjectField(), initValue.phoneValue);
            return;
        }

        // 日付:Date
        if(dfr.getType()==Schema.DisplayType.Date){
            sObj.put(dfr.getSObjectField(), initValue.dateValue);
            return;
        }

        // 日付/時間:DateTime
        if(dfr.getType()==Schema.DisplayType.DateTime){
            sObj.put(dfr.getSObjectField(), initValue.datetimeValue);
            return;
        }

        // 選択リスト:Picklist
        if(dfr.getType()==Schema.DisplayType.Picklist){
            List<Schema.PicklistEntry> picklistEntries = dfr.getPicklistValues();
            for (Schema.PicklistEntry item : picklistEntries) {
                if (item.isActive()) {
                    sObj.put(dfr.getSObjectField(), item.getValue());
                    break;
                }
            }
            return;
        }

        // 複数選択リスト:MultiPicklist
        if(dfr.getType()==Schema.DisplayType.MultiPicklist){
            List<Schema.PicklistEntry> picklistEntries = dfr.getPicklistValues();
            for (Schema.PicklistEntry item : picklistEntries) {
                if (item.isActive()) {
                    sObj.put(dfr.getSObjectField(), item.getValue());
                    break;
                }
            }
            return;
        }
    }

    /* ==================== */
    /*         テストデータ取得
    /* ==================== */
    /** SOQL文Template */
    private static String strQueryTemplate = 'select {fields} from {sobject} {where} order by id asc';

    /** 部分的な項目を取得 */
    public static List<sObject> getTesDataSelectFields(Schema.SObjectType sObjType) {
        return getTesDataSelectFields(sObjType, null, null);
    }

    public static List<sObject> getTesDataSelectFields(Schema.SObjectType sObjType, List<Schema.SObjectField> selectFields) {
        return getTesDataSelectFields(sObjType, selectFields, null);
    }

    public static List<sObject> getTesDataSelectFields(Schema.SObjectType sObjType, List<Id> idList) {
        return getTesDataSelectFields(sObjType, null, idList);
    }

    public static List<sObject> getTesDataSelectFields(Schema.SObjectType sObjType, List<Schema.SObjectField> selectFields, List<Id> idList) {
        // SOQLの取得項目セット
        Set<String> fieldNameSet = new Set<String>();

        if (selectFields != null && selectFields.size() > 0) {
            for (Schema.SObjectField item : selectFields) {
                fieldNameSet.add(item.getDescribe().getName().toLowerCase());
            }
        }

        // SOQL取得項目が存在しない場合、Idを設定する
        if (fieldNameSet.isEmpty()) {
            fieldNameSet.add('Id');
        }

        // 検索用SOQL文作成
        String strQuery = strQueryTemplate;

        // オブジェクト設定
        strQuery = strQuery.replace('{sobject}', sObjType.getDescribe().getName());

        // 取得項目設定
        strQuery = strQuery.replace('{fields}', String.join(new List<String>(fieldNameSet), ','));

        // where条件設定
        if (idList != null && idList.size() > 0) {
            strQuery = strQuery.replace('{where}', 'where id=:idList');
        } else {
            strQuery = strQuery.replace('{where}', '');
        }

        // SOQL発行
        return Database.Query(strQuery);
    }

    /** 全項目を取得 */
    public static List<sObject> getTesDataAllFields(Schema.SObjectType sObjectType) {
        return getTesDataAllFields(sObjectType, null, null);
    }

    public static List<sObject> getTesDataAllFields(Schema.SObjectType sObjType, List<Schema.SObjectField> referenceFields) {
        return getTesDataAllFields(sObjType, referenceFields, null);
    }

    public static List<sObject> getTesDataAllFields(Schema.SObjectType sObjType, List<Id> idList) {
        return getTesDataAllFields(sObjType, null, idList);
    }

    public static List<sObject> getTesDataAllFields(Schema.SObjectType sObjType, List<Schema.SObjectField> referenceFields, List<Id> idList) {
        // SOQLの取得項目セット
        Set<String> fieldNameSet = new Set<String>();

        // SObjectのすべて項目を取得する
        Map< String, Schema.sObjectField > sObjectFieldMap = sObjType.getDescribe().fields.getMap();
        for(String fieldName : sObjectFieldMap.keySet()){
            fieldNameSet.add(fieldName.toLowerCase());
        }

        // 参照先項目
        if (referenceFields != null && referenceFields.size() > 0) {
            for (Schema.SObjectField item : referenceFields) {
                fieldNameSet.add(item.getDescribe().getName().toLowerCase());
            }
        }

        // 検索用SOQL文作成
        String strQuery = strQueryTemplate;

        // オブジェクト設定
        strQuery = strQuery.replace('{sobject}', sObjType.getDescribe().getName());

        // 取得項目設定
        strQuery = strQuery.replace('{fields}', String.join(new List<String>(fieldNameSet), ','));

        // where条件設定
        if (idList != null && idList.size() > 0) {
            strQuery = strQuery.replace('{where}', 'where id=:idList');
        } else {
            strQuery = strQuery.replace('{where}', '');
        }

        system.debug(strQuery);

        // SOQL発行
        return Database.Query(strQuery);
    }
}

4.TestDataFactory


/**
 * 各オブジェクトのテストデータ生成Factory
 * 
 */
@isTest
public class TestDataFactory {
    /**
     * テストデータ:XXXXXX
     */
    public static XXXXXX__c getTestDataXXXXXX(TestUtility.TestDataPattern testDataPattern) {
        // テストデータのTemplateデータを取得する
        XXXXXX__c testData = (XXXXXX__c)TestUtility.getInitSObjectInstance(XXXXXX__c.sObjectType, testDataPattern);

        // テストデータの個別設定部分
        // 例:文字列(YYYYMMDD,YYYYMM,YYYYなど)、制御項目と連動項目、範囲データ等

        return testData;
    }
}
26
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
19