import logging
from copy import deepcopy
from unittest.mock import MagicMock, patch

import pytest
from src import controller
from src.config.objects import (FetchTargetObjects, LastFetchDatetime,
                                TargetObject)
from src.error.exceptions import MeDaCaCRMDataFetchException
from src.system_var.constants import (CHK_JP_NAME, CONV_JP_NAME, CSVBK_JP_NAME,
                                      DATE_JP_NAME, END_JP_NAME, FETCH_JP_NAME,
                                      PRE_JP_NAME, RESBK_JP_NAME, UPD_JP_NAME,
                                      UPLD_JP_NAME)
from src.util.execute_datetime import ExecuteDateTime

from .test_utils.log_message import generate_log_message_tuple

COMMON_OBJECT_INFOS = {
    'objects': [
        {
            'object_name': 'Account',
            'columns': ['Id'],
            'upload_file_name': 'Account_YYYYMMDDHHMMSS'
        },
        {
            'object_name': 'Contact',
            'columns': ['Id'],
            'upload_file_name': 'Contact_YYYYMMDDHHMMSS'
        },
        {
            'object_name': 'Call2_vod__c',
            'columns': ['Id'],
            'upload_file_name': 'Call2_vod__c_YYYYMMDDHHMMSS'
        }
    ]
}

COMMON_EXECUTE_DATETIME = ExecuteDateTime()

COMMON_FETCH_TARGET_OBJECTS = FetchTargetObjects(COMMON_OBJECT_INFOS)

COMMON_TARGET_OBJECTS_1 = TargetObject(COMMON_OBJECT_INFOS['objects'][0], COMMON_EXECUTE_DATETIME)
COMMON_TARGET_OBJECTS_2 = TargetObject(COMMON_OBJECT_INFOS['objects'][1], COMMON_EXECUTE_DATETIME)
COMMON_TARGET_OBJECTS_3 = TargetObject(COMMON_OBJECT_INFOS['objects'][2], COMMON_EXECUTE_DATETIME)

COMMON_LAST_FETCH_DATETIME = LastFetchDatetime({
    'last_fetch_datetime_from': '1900-01-01T00:00:00.000Z',
    'last_fetch_datetime_to': ''
}, COMMON_EXECUTE_DATETIME)


class ForTestMeDaCaCRMDataFetchException(MeDaCaCRMDataFetchException):
    def __init__(self, error_id: str, func_name: str, message: str) -> None:
        super().__init__(error_id, func_name, message)


class ForTestException(Exception):
    # カスタム例外とインタフェースを合わせるための引数
    def __init__(self, error_id: str, func_name: str, message: str) -> None:
        super().__init__(message)


class TestController:

    @pytest.fixture(autouse=True)
    def setup_teardown(self):
        # setup
        self.mock_prepare_data_fetch_process = MagicMock()
        self.mock_check_object_info_process = MagicMock()
        self.mock_set_datetime_period_process = MagicMock()
        self.mock_fetch_crm_data_process = MagicMock()
        self.mock_backup_crm_data_process = MagicMock()
        self.mock_convert_crm_csv_data_process = MagicMock()
        self.mock_backup_crm_csv_data_process = MagicMock()
        self.mock_copy_crm_csv_data_process = MagicMock()
        self.mock_upload_last_fetch_datetime_process = MagicMock()
        self.mock_upload_result_data_process = MagicMock()

        # run test
        yield

        # teardown
        self.mock_prepare_data_fetch_process.reset_mock()
        self.mock_check_object_info_process.reset_mock()
        self.mock_set_datetime_period_process.reset_mock()
        self.mock_fetch_crm_data_process.reset_mock()
        self.mock_backup_crm_data_process.reset_mock()
        self.mock_convert_crm_csv_data_process.reset_mock()
        self.mock_backup_crm_csv_data_process.reset_mock()
        self.mock_copy_crm_csv_data_process.reset_mock()
        self.mock_upload_last_fetch_datetime_process.reset_mock()
        self.mock_upload_result_data_process.reset_mock()

    @pytest.fixture()
    def run_control_process(self):

        def _func():
            with patch('src.controller.prepare_data_fetch_process', self.mock_prepare_data_fetch_process),\
                    patch('src.controller.check_object_info_process', self.mock_check_object_info_process),\
                    patch('src.controller.set_datetime_period_process', self.mock_set_datetime_period_process),\
                    patch('src.controller.fetch_crm_data_process', self.mock_fetch_crm_data_process),\
                    patch('src.controller.backup_crm_data_process', self.mock_backup_crm_data_process),\
                    patch('src.controller.convert_crm_csv_data_process', self.mock_convert_crm_csv_data_process),\
                    patch('src.controller.backup_crm_csv_data_process', self.mock_backup_crm_csv_data_process),\
                    patch('src.controller.copy_crm_csv_data_process', self.mock_copy_crm_csv_data_process),\
                    patch('src.controller.upload_last_fetch_datetime_process', self.mock_upload_last_fetch_datetime_process),\
                    patch('src.controller.upload_result_data_process', self.mock_upload_result_data_process):
                controller.controller()
        yield _func

    @pytest.fixture()
    def call_all_processes(self, caplog, run_control_process):
        """
        コントロール処理内ですべてのプロセス関数が呼ばれることのテストで使用するフィクスチャ
        各種プロセス関数をモック化し、正常終了させるように動く

        Yields:
            dict: プロセス関数呼び出し後のモックの辞書
        """
        def _func():
            mock_return_values = [COMMON_TARGET_OBJECTS_1, COMMON_TARGET_OBJECTS_2, COMMON_TARGET_OBJECTS_3]
            self.mock_prepare_data_fetch_process = MagicMock(return_value=(deepcopy(COMMON_FETCH_TARGET_OBJECTS), COMMON_EXECUTE_DATETIME, {}))
            self.mock_check_object_info_process = MagicMock(side_effect=mock_return_values)
            self.mock_set_datetime_period_process = MagicMock(return_value=COMMON_LAST_FETCH_DATETIME)
            self.mock_fetch_crm_data_process = MagicMock(return_value=[{'Name': 'Test'}])
            self.mock_backup_crm_data_process = MagicMock()
            self.mock_convert_crm_csv_data_process = MagicMock()
            self.mock_backup_crm_csv_data_process = MagicMock()
            self.mock_copy_crm_csv_data_process = MagicMock()
            self.mock_upload_last_fetch_datetime_process = MagicMock()
            self.mock_upload_result_data_process = MagicMock()

            run_control_process()

        yield _func

    def test_call_all_processes(self, call_all_processes):
        """
        Cases:
            コントロール処理からすべてのプロセスが呼ばれること
        Arranges:
            - call_all_processesフィクスチャで、コントロール処理を実行しておく
        Expects:
            - データ取得準備処理が1回のみ実行される
            - オブジェクト情報形式チェック処理が複数回実行される
            - データ取得期間設定処理が複数回実行される
            - CRMデータ取得処理が複数回実行される
            - CRM電文データバックアップ処理が複数回実行される
            - CSV変換処理が複数回実行される
            - CSVバックアップ処理が複数回実行される
            - CSVアップロード処理が複数回実行される
            - 前回取得日時ファイル更新処理が複数回実行される
            - 取得処理実施結果アップロード処理が1回のみ実行される
        """
        call_all_processes()
        assert self.mock_prepare_data_fetch_process.called is True, 'データ取得準備処理が1回のみ実行されること'
        assert self.mock_prepare_data_fetch_process.call_count == 1, 'データ取得準備処理が1回のみ実行されること'
        assert self.mock_check_object_info_process.call_count == 3, 'オブジェクト情報形式チェック処理が複数回実行されること'
        assert self.mock_set_datetime_period_process.call_count == 3, 'データ取得期間設定処理が複数回実行されること'
        assert self.mock_fetch_crm_data_process.call_count == 3, 'CRMデータ取得処理が複数回実行されること'
        assert self.mock_backup_crm_data_process.call_count == 3, 'CRM電文データバックアップ処理が複数回実行されること'
        assert self.mock_convert_crm_csv_data_process.call_count == 3, 'CSV変換処理が複数回実行されること'
        assert self.mock_backup_crm_csv_data_process.call_count == 3, 'CSVバックアップ処理が複数回実行されること'
        assert self.mock_copy_crm_csv_data_process.call_count == 3, 'CSVアップロード処理が複数回実行されること'
        assert self.mock_upload_last_fetch_datetime_process.call_count == 3, '前回取得日時ファイル更新処理が複数回実行されること'
        assert self.mock_upload_result_data_process.called is True, '取得処理実施結果アップロード処理が1回のみ実行されること'
        assert self.mock_upload_result_data_process.call_count == 1, '取得処理実施結果アップロード処理が1回のみ実行されること'

    def test_print_normal_logs(self, call_all_processes, caplog):
        """
        Cases:
            コントロール処理の正常系ログがすべての出力されていること
        Arranges:
            - call_all_processesフィクスチャで、コントロール処理を実行しておく
        Expects:
            - コントロール処理の正常系ログがすべて出力されている
        """
        call_all_processes()

        assert generate_log_message_tuple(log_message='I-CTRL-01 CRMデータ取得処理を開始します') in caplog.record_tuples
        assert generate_log_message_tuple(log_message='I-CTRL-02 データ取得準備処理呼び出し') in caplog.record_tuples
        assert generate_log_message_tuple(log_message='I-CTRL-03 取得対象オブジェクトのループ処理開始') in caplog.record_tuples
        for name in ['Account', 'Contact', 'Call2_vod__c']:
            object_name = name
            upload_file_name = f'{name}_YYYYMMDDHHMMSS'
            assert generate_log_message_tuple(log_message='I-CTRL-05 オブジェクト情報形式チェック処理呼び出し') in caplog.record_tuples
            assert generate_log_message_tuple(log_message=f'I-CTRL-06 [{object_name}]のデータ取得を開始します') in caplog.record_tuples
            assert generate_log_message_tuple(log_message=f'I-CTRL-08 [{object_name}]のデータ取得期間設定処理呼び出し') in caplog.record_tuples
            assert generate_log_message_tuple(log_message=f'I-CTRL-09 [{object_name}]のデータ取得処理呼び出し') in caplog.record_tuples
            assert generate_log_message_tuple(log_message=f'I-CTRL-10 [{object_name}] の出力ファイル名は [{upload_file_name}] となります') in caplog.record_tuples
            assert generate_log_message_tuple(log_message=f'I-CTRL-11 [{object_name}] CRM電文データバックアップ処理呼び出し') in caplog.record_tuples
            assert generate_log_message_tuple(log_message=f'I-CTRL-12 [{object_name}] CSV変換処理呼び出し') in caplog.record_tuples
            assert generate_log_message_tuple(log_message=f'I-CTRL-13 [{object_name}] CSVデータバックアップ処理呼び出し') in caplog.record_tuples
            assert generate_log_message_tuple(log_message=f'I-CTRL-14 [{object_name}] CSVデータアップロード処理呼び出し') in caplog.record_tuples
            assert generate_log_message_tuple(log_message=f'I-CTRL-15 [{object_name}] 前回取得日時ファイル更新処理呼び出し') in caplog.record_tuples
            assert generate_log_message_tuple(log_message=f'I-CTRL-16 [{object_name}] 処理正常終了') in caplog.record_tuples

        expect_process_result = {
            'Account': 'success',
            'Contact': 'success',
            'Call2_vod__c': 'success'
        }
        assert generate_log_message_tuple(log_message=f'I-CTRL-17 すべてのオブジェクトの処理が終了しました 実行結果：[{expect_process_result}]') in caplog.record_tuples
        assert generate_log_message_tuple(log_message=f'I-CTRL-18 CRM_取得処理実施結果ファイルアップロード処理開始') in caplog.record_tuples
        assert generate_log_message_tuple(log_message=f'I-CTRL-19 すべてのデータの取得に成功しました') in caplog.record_tuples
        assert generate_log_message_tuple(log_message=f'I-CTRL-20 CRMデータ取得処理を終了します') in caplog.record_tuples

    def test_do_not_call_upload_process_result_process(self, caplog, run_control_process):
        """
        Cases:
            処理対象オブジェクトが0件の場合、取得処理実施結果アップロード処理が実行されないこと
        Arranges:
            - データ取得準備処理で返される取得対象オブジェクト情報を0件にする
            - 各種プロセスメソッドと内部で使用している値オブジェクトをモック化する
        Expects:
            - データ取得準備処理が1回のみ実行されること
            - 取得処理実施結果アップロード処理が実行されないこと
            - 処理対象が存在しない旨を示すログメッセージが出力されていること
        """

        self.mock_prepare_data_fetch_process = MagicMock(return_value=([], COMMON_EXECUTE_DATETIME, {}))
        self.mock_check_object_info_process = MagicMock()
        self.mock_set_datetime_period_process = MagicMock()
        self.mock_fetch_crm_data_process = MagicMock()
        self.mock_backup_crm_data_process = MagicMock()
        self.mock_convert_crm_csv_data_process = MagicMock()
        self.mock_backup_crm_csv_data_process = MagicMock()
        self.mock_copy_crm_csv_data_process = MagicMock()
        self.mock_upload_last_fetch_datetime_process = MagicMock()
        self.mock_upload_result_data_process = MagicMock()

        run_control_process()

        # 実行回数の確認
        assert self.mock_prepare_data_fetch_process.called, 'データ取得準備処理が1回のみ実行されること'
        assert self.mock_prepare_data_fetch_process.call_count == 1, 'データ取得準備処理が1回のみ実行されること'
        assert self.mock_upload_result_data_process.called is False, '取得処理実施結果アップロード処理が実行されないこと'
        assert self.mock_upload_result_data_process.call_count == 0, '取得処理実施結果アップロード処理が実行されないこと'

        # ログ出力の確認
        assert generate_log_message_tuple(log_message='I-CTRL-21 処理対象のデータが存在しませんでした') in caplog.record_tuples, '処理対象が存在しない旨を示すログメッセージが出力されていること'
        assert generate_log_message_tuple(log_message=f'I-CTRL-20 CRMデータ取得処理を終了します') in caplog.record_tuples

    def test_do_not_call_upload_csv_process_cause_is_skip_true(self, caplog, run_control_process):
        """
        Cases:
            オブジェクト情報.is_skipがTrueの場合、CSVアップロード処理が実行されないこと
        Arranges:
            - データ取得準備処理で返される取得対象オブジェクト情報のis_skipをTrueにする
            - 各種プロセスメソッドと内部で使用している値オブジェクトをモック化する
        Expects:
            - オブジェクト情報形式チェック処理以降のプロセスが実行されないこと
            - 処理をスキップする旨を示すログメッセージが出力されていること
        """
        mock_check_object_info = {
            'object_name': 'Account',
            'columns': ['id'],
            'is_skip': True
        }
        mock_return_values = [TargetObject(mock_check_object_info, COMMON_EXECUTE_DATETIME)]
        self.mock_prepare_data_fetch_process = MagicMock(return_value=([mock_check_object_info], COMMON_EXECUTE_DATETIME, {}))
        self.mock_check_object_info_process = MagicMock(side_effect=mock_return_values)
        self.mock_set_datetime_period_process = MagicMock()
        self.mock_fetch_crm_data_process = MagicMock()
        self.mock_backup_crm_data_process = MagicMock()
        self.mock_convert_crm_csv_data_process = MagicMock()
        self.mock_backup_crm_csv_data_process = MagicMock()
        self.mock_copy_crm_csv_data_process = MagicMock()
        self.mock_upload_last_fetch_datetime_process = MagicMock()
        self.mock_upload_result_data_process = MagicMock()

        run_control_process()

        # 実行回数の確認

        assert self.mock_check_object_info_process.called is True
        assert self.mock_check_object_info_process.call_count == 1
        # オブジェクト情報形式チェック処理以降のプロセスが実行されないこと
        assert self.mock_set_datetime_period_process.call_count == 0
        assert self.mock_fetch_crm_data_process.call_count == 0
        assert self.mock_backup_crm_data_process.call_count == 0
        assert self.mock_convert_crm_csv_data_process.call_count == 0
        assert self.mock_backup_crm_csv_data_process.call_count == 0
        assert self.mock_copy_crm_csv_data_process.call_count == 0
        assert self.mock_upload_last_fetch_datetime_process.call_count == 0
        # 結果ファイルの出力は行う
        assert self.mock_upload_result_data_process.called is True
        assert self.mock_upload_result_data_process.call_count == 1

        # ログ出力の確認
        assert generate_log_message_tuple(log_message='I-CTRL-07 [Account]のデータ取得処理をスキップします') in caplog.record_tuples
        assert generate_log_message_tuple(log_message=f'I-CTRL-20 CRMデータ取得処理を終了します') in caplog.record_tuples

    def test_do_not_call_upload_csv_process_cause_is_skip_true_in_loop(self, caplog, run_control_process):
        """
        Cases:
            オブジェクト情報.is_skipがTrueのものが含まれる場合、対象オブジェクトのCSVアップロード処理が実行されないこと
        Arranges:
            - データ取得準備処理で返される取得対象オブジェクト情報のうち、２つ目をis_skipをTrueにする
            - 各種プロセスメソッドと内部で使用している値オブジェクトをモック化する
        Expects:
            - オブジェクト情報形式チェック処理が2回実行されること
            - 処理をスキップする旨を示すログメッセージが出力されていること
            - オブジェクト情報.is_skipがFalseのものはCSVアップロード処理のログメッセージが出力されていること
        """
        mock_check_object_infos = {
            'objects': [
                {
                    'object_name': 'Account',
                    'columns': ['id'],
                    'is_skip': False
                },
                {
                    'object_name': 'Contact',
                    'columns': ['id'],
                    'is_skip': True
                },
                {
                    'object_name': 'Call2_vod__c',
                    'columns': ['id'],
                    'is_skip': False
                }
            ]
        }
        FetchTargetObjects(mock_check_object_infos)
        mock_return_values = [
            TargetObject(mock_check_object_infos['objects'][0], COMMON_EXECUTE_DATETIME),
            TargetObject(mock_check_object_infos['objects'][1], COMMON_EXECUTE_DATETIME),
            TargetObject(mock_check_object_infos['objects'][2], COMMON_EXECUTE_DATETIME),
        ]
        self.mock_prepare_data_fetch_process = MagicMock(return_value=(FetchTargetObjects(mock_check_object_infos), COMMON_EXECUTE_DATETIME, {}))
        self.mock_check_object_info_process = MagicMock(side_effect=mock_return_values)
        self.mock_set_datetime_period_process = MagicMock()
        self.mock_fetch_crm_data_process = MagicMock(side_effect=[[{"Name": "Test"}], [{"Name": "Test"}]])
        self.mock_backup_crm_data_process = MagicMock()
        self.mock_convert_crm_csv_data_process = MagicMock()
        self.mock_backup_crm_csv_data_process = MagicMock()
        self.mock_copy_crm_csv_data_process = MagicMock()
        self.mock_upload_last_fetch_datetime_process = MagicMock()
        self.mock_upload_result_data_process = MagicMock()

        run_control_process()
        # 実行回数の確認
        assert self.mock_prepare_data_fetch_process.called is True
        assert self.mock_prepare_data_fetch_process.call_count == 1
        assert self.mock_check_object_info_process.call_count == 3
        # オブジェクト情報形式チェック処理以降のプロセスが実行されないこと
        assert self.mock_set_datetime_period_process.call_count == 2
        assert self.mock_fetch_crm_data_process.call_count == 2
        assert self.mock_backup_crm_data_process.call_count == 2
        assert self.mock_convert_crm_csv_data_process.call_count == 2
        assert self.mock_backup_crm_csv_data_process.call_count == 2
        assert self.mock_copy_crm_csv_data_process.call_count == 2
        assert self.mock_upload_last_fetch_datetime_process.call_count == 2
        assert self.mock_upload_result_data_process.called is True
        assert self.mock_upload_result_data_process.call_count == 1

        # ログ出力の確認
        assert generate_log_message_tuple(
            log_message='I-CTRL-14 [Account] CSVデータアップロード処理呼び出し') in caplog.record_tuples, 'オブジェクト情報.is_skipがFalseのものはCSVアップロード処理のログメッセージが出力されていること'
        assert generate_log_message_tuple(
            log_message='I-CTRL-07 [Contact]のデータ取得処理をスキップします') in caplog.record_tuples, '処理をスキップする旨を示すログメッセージが出力されていること'
        assert generate_log_message_tuple(
            log_message='I-CTRL-14 [Call2_vod__c] CSVデータアップロード処理呼び出し'
        ) in caplog.record_tuples, 'オブジェクト情報.is_skipがFalseのものはCSVアップロード処理のログメッセージが出力されていること'
        assert generate_log_message_tuple(log_message=f'I-CTRL-20 CRMデータ取得処理を終了します') in caplog.record_tuples

    def test_do_not_call_upload_csv_process_cause_crm_data_empty(self, caplog, run_control_process):
        """
        Cases:
            CRMデータ取得処理で取得できた件数が0件の場合、CSVアップロード処理が実行されないこと
        Arranges:
            - CRMデータ取得処理で返されるオブジェクトを空のリストにする
            - 各種プロセスメソッドと内部で使用している値オブジェクトをモック化する
        Expects:
            - CRM電文データバックアップ処理以降のプロセスが実行されないこと
            - 処理をスキップする旨を示すログメッセージが出力されていること
        """
        mock_check_object_infos = {
            'objects': [
                {
                    'object_name': 'Account',
                    'columns': ['id'],
                    'is_skip': False
                }
            ]
        }

        FetchTargetObjects(mock_check_object_infos)
        mock_return_values = [
            TargetObject(mock_check_object_infos['objects'][0], COMMON_EXECUTE_DATETIME)
        ]
        self.mock_prepare_data_fetch_process = MagicMock(return_value=(FetchTargetObjects(mock_check_object_infos), COMMON_EXECUTE_DATETIME, {}))
        self.mock_check_object_info_process = MagicMock(side_effect=mock_return_values)
        self.mock_set_datetime_period_process = MagicMock()
        self.mock_fetch_crm_data_process = MagicMock(return_value=[])
        self.mock_backup_crm_data_process = MagicMock()
        self.mock_convert_crm_csv_data_process = MagicMock()
        self.mock_backup_crm_csv_data_process = MagicMock()
        self.mock_copy_crm_csv_data_process = MagicMock()
        self.mock_upload_last_fetch_datetime_process = MagicMock()
        self.mock_upload_result_data_process = MagicMock()

        run_control_process()
        # 実行回数の確認
        assert self.mock_prepare_data_fetch_process.called is True
        assert self.mock_prepare_data_fetch_process.call_count == 1
        assert self.mock_check_object_info_process.call_count == 1
        assert self.mock_set_datetime_period_process.call_count == 1
        assert self.mock_fetch_crm_data_process.call_count == 1
        # CRM電文データバックアップ処理以降のプロセスが実行されないこと
        assert self.mock_backup_crm_data_process.call_count == 0
        assert self.mock_convert_crm_csv_data_process.call_count == 0
        assert self.mock_backup_crm_csv_data_process.call_count == 0
        assert self.mock_copy_crm_csv_data_process.call_count == 0
        assert self.mock_upload_last_fetch_datetime_process.call_count == 0
        assert self.mock_upload_result_data_process.called is True
        assert self.mock_upload_result_data_process.call_count == 1

        # ログ出力の確認
        assert generate_log_message_tuple(
            log_message='I-CTRL-22 [Account]のレコード件数が0件のため、ファイルアップロードをスキップします') in caplog.record_tuples, '処理をスキップする旨を示すログメッセージが出力されていること'

    def test_do_not_call_upload_csv_process_cause_crm_data_empty_in_loop(self, caplog, run_control_process):
        """
        Cases:
            CRMデータ取得処理で取得できた件数が0件のものが含まれる場合、対象オブジェクトのCSVアップロード処理が実行されないこと
        Arranges:
            - CRMデータ取得処理で返されるオブジェクトのうち、２つ目を空のリストにする
            - 各種プロセスメソッドと内部で使用している値オブジェクトをモック化する
        Expects:
            - CRMデータ取得処理が2回実行されること
            - 処理をスキップする旨を示すログメッセージが出力されていること
            - 取得オブジェクトが1件以上取れているものはCSVアップロード処理のログメッセージが出力されていること
        """
        self.mock_prepare_data_fetch_process = MagicMock(return_value=(deepcopy(COMMON_FETCH_TARGET_OBJECTS), COMMON_EXECUTE_DATETIME, {}))
        self.mock_check_object_info_process = MagicMock(side_effect=[COMMON_TARGET_OBJECTS_1, COMMON_TARGET_OBJECTS_2, COMMON_TARGET_OBJECTS_3])
        self.mock_set_datetime_period_process = MagicMock(return_value=COMMON_LAST_FETCH_DATETIME)
        self.mock_fetch_crm_data_process = MagicMock(side_effect=[[{"Name": "Test"}], [], [{"Name": "Test"}]])
        self.mock_backup_crm_data_process = MagicMock()
        self.mock_convert_crm_csv_data_process = MagicMock()
        self.mock_backup_crm_csv_data_process = MagicMock()
        self.mock_copy_crm_csv_data_process = MagicMock()
        self.mock_upload_last_fetch_datetime_process = MagicMock()
        self.mock_upload_result_data_process = MagicMock()

        run_control_process()
        # 実行回数の確認
        assert self.mock_check_object_info_process.call_count == 3
        assert self.mock_set_datetime_period_process.call_count == 3
        assert self.mock_fetch_crm_data_process.call_count == 3
        # CRM電文データバックアップ処理以降のプロセスは件数があるもののみ実行されること
        assert self.mock_backup_crm_data_process.call_count == 2
        assert self.mock_convert_crm_csv_data_process.call_count == 2
        assert self.mock_backup_crm_csv_data_process.call_count == 2
        assert self.mock_copy_crm_csv_data_process.call_count == 2
        assert self.mock_upload_last_fetch_datetime_process.call_count == 2
        assert self.mock_upload_result_data_process.called is True
        assert self.mock_upload_result_data_process.call_count == 1

        # ログ出力の確認
        assert generate_log_message_tuple(
            log_message='I-CTRL-14 [Account] CSVデータアップロード処理呼び出し') in caplog.record_tuples, '取得オブジェクトが1件以上取れているものはCSVアップロード処理のログメッセージが出力されていること'
        assert generate_log_message_tuple(
            log_message='I-CTRL-22 [Contact]のレコード件数が0件のため、ファイルアップロードをスキップします') in caplog.record_tuples, '処理をスキップする旨を示すログメッセージが出力されていること'
        assert generate_log_message_tuple(
            log_message='I-CTRL-14 [Call2_vod__c] CSVデータアップロード処理呼び出し'
        ) in caplog.record_tuples, '取得オブジェクトが1件以上取れているものはCSVアップロード処理のログメッセージが出力されていること'

    @pytest.mark.parametrize(
        'exception, message',
        [
            (ForTestMeDaCaCRMDataFetchException, f'E-ERR-01 [{PRE_JP_NAME}]でエラーが発生したため、処理を終了します'),
            (ForTestException, 'E-ERR-02 予期せぬエラーが発生したため、処理を終了します エラー内容: [例外発生]')
        ])
    def test_raise_prepare_data_fetch_process(self, caplog, exception, message, run_control_process):
        """
        Cases:
            1. データ取得準備処理でシステム例外が発生した場合、エラーで終了すること
            2. データ取得準備処理で想定外の例外が発生した場合、エラーで終了すること
        Arranges:
            - パラメータ１：データ取得準備処理でシステム例外が発生するようにする
            - パラメータ２：データ取得準備処理で想定外の例外が発生するようにする
        Expects:
            - データ取得準備処理で例外が発生すること
            - データ取得準備処理で発生した例外のログメッセージが出力されていること
        """
        expect_exception = exception('E-PRE-01', PRE_JP_NAME, '例外発生')
        self.mock_prepare_data_fetch_process = MagicMock(side_effect=expect_exception)
        self.mock_check_object_info_process = MagicMock()
        with pytest.raises(exception):
            run_control_process()
        assert self.mock_check_object_info_process.called is False
        assert generate_log_message_tuple(
            log_level=logging.ERROR,
            log_message=message) in caplog.record_tuples, 'データ取得準備処理で発生した例外のログメッセージが出力されていること'

    @pytest.mark.parametrize(
        'exception, message',
        [
            (ForTestMeDaCaCRMDataFetchException, f'I-ERR-03 [Account] の[{CHK_JP_NAME}]でエラーが発生しました 次のオブジェクトの処理に移行します'),
            (ForTestException, 'I-ERR-04 [Account] の処理中に予期せぬエラーが発生しました 次のオブジェクトの処理に移行します エラー内容: [例外発生]')
        ])
    def test_raise_check_object_info_process(self, caplog, exception, message, run_control_process):
        """
        Cases:
            1. オブジェクト情報形式チェック処理でシステム例外が発生した場合、エラーログが送出され、後続の終了に移行すること
            2. オブジェクト情報形式チェック処理で想定外の例外が発生した場合、エラーログが送出され、後続の終了に移行すること
        Arranges:
            - パラメータ１：オブジェクト情報形式チェック処理でシステム例外が発生するようにする
            - パラメータ２：オブジェクト情報形式チェック処理で想定外の例外が発生するようにする
        Expects:
            - オブジェクト情報形式チェック処理で例外が発生する
            - オブジェクト情報形式チェック処理で発生した例外のログメッセージが出力されている
            - 例外が発生したオブジェクト以外は正常に終了する
        """
        raise_object = exception('E-PRE-01', CHK_JP_NAME, '例外発生')
        mock_return_values = [raise_object, COMMON_TARGET_OBJECTS_2, COMMON_TARGET_OBJECTS_2]

        self.mock_prepare_data_fetch_process = MagicMock(return_value=(deepcopy(COMMON_FETCH_TARGET_OBJECTS), COMMON_EXECUTE_DATETIME, {}))
        self.mock_check_object_info_process = MagicMock(side_effect=mock_return_values)
        self.mock_set_datetime_period_process = MagicMock(return_value=COMMON_LAST_FETCH_DATETIME)
        self.mock_fetch_crm_data_process = MagicMock(return_value=[{'Name': 'Test'}])
        self.mock_backup_crm_data_process = MagicMock()
        self.mock_convert_crm_csv_data_process = MagicMock()
        self.mock_backup_crm_csv_data_process = MagicMock()
        self.mock_copy_crm_csv_data_process = MagicMock()
        self.mock_upload_last_fetch_datetime_process = MagicMock()
        self.mock_upload_result_data_process = MagicMock()

        run_control_process()
        assert self.mock_check_object_info_process.call_count == 3
        assert self.mock_set_datetime_period_process.call_count == 2
        expect_process_result = {
            'Account': 'fail',
            'Contact': 'success',
            'Call2_vod__c': 'success'
        }
        assert generate_log_message_tuple(log_message=message) in caplog.record_tuples
        assert generate_log_message_tuple(log_message=f'I-CTRL-17 すべてのオブジェクトの処理が終了しました 実行結果：[{expect_process_result}]') in caplog.record_tuples
        assert generate_log_message_tuple(
            log_level=logging.ERROR, log_message=f'E-CTRL-01 一部のデータ取得に失敗しています  詳細はログをご確認ください') in caplog.record_tuples

    @pytest.mark.parametrize(
        'exception, message',
        [
            (ForTestMeDaCaCRMDataFetchException, f'I-ERR-03 [Account] の[{DATE_JP_NAME}]でエラーが発生しました 次のオブジェクトの処理に移行します'),
            (ForTestException, 'I-ERR-04 [Account] の処理中に予期せぬエラーが発生しました 次のオブジェクトの処理に移行します エラー内容: [例外発生]')
        ])
    def test_raise_set_datetime_period_process(self, caplog, exception, message, run_control_process):
        """
        Cases:
            1. データ取得期間設定処理でシステム例外が発生した場合、エラーログが送出され、後続の終了に移行すること
            2. データ取得期間設定処理で想定外の例外が発生した場合、エラーログが送出され、後続の終了に移行すること
        Arranges:
            - パラメータ１：データ取得期間設定処理でシステム例外が発生するようにする
            - パラメータ２：データ取得期間設定処理で想定外の例外が発生するようにする
        Expects:
            - データ取得期間設定チェック処理で例外が発生する
            - データ取得期間設定チェック処理で発生した例外のログメッセージが出力されている
            - 例外が発生したオブジェクト以外は正常に終了する
        """
        mock_return_values = [COMMON_TARGET_OBJECTS_1, COMMON_TARGET_OBJECTS_2, COMMON_TARGET_OBJECTS_3]

        self.mock_prepare_data_fetch_process = MagicMock(return_value=(deepcopy(COMMON_FETCH_TARGET_OBJECTS), COMMON_EXECUTE_DATETIME, {}))
        self.mock_check_object_info_process = MagicMock(side_effect=mock_return_values)
        self.mock_set_datetime_period_process = MagicMock(side_effect=[exception(
            'E-DATE-01', DATE_JP_NAME, '例外発生'), COMMON_LAST_FETCH_DATETIME, COMMON_LAST_FETCH_DATETIME])
        self.mock_fetch_crm_data_process = MagicMock(return_value=[{'Name': 'Test'}])
        self.mock_backup_crm_data_process = MagicMock()
        self.mock_convert_crm_csv_data_process = MagicMock()
        self.mock_backup_crm_csv_data_process = MagicMock()
        self.mock_copy_crm_csv_data_process = MagicMock()
        self.mock_upload_last_fetch_datetime_process = MagicMock()
        self.mock_upload_result_data_process = MagicMock()

        run_control_process()

        assert self.mock_set_datetime_period_process.call_count == 3
        assert self.mock_fetch_crm_data_process.call_count == 2
        expect_process_result = {
            'Account': 'fail',
            'Contact': 'success',
            'Call2_vod__c': 'success'
        }
        assert generate_log_message_tuple(log_message=message) in caplog.record_tuples
        assert generate_log_message_tuple(log_message=f'I-CTRL-17 すべてのオブジェクトの処理が終了しました 実行結果：[{expect_process_result}]') in caplog.record_tuples
        assert generate_log_message_tuple(
            log_level=logging.ERROR, log_message=f'E-CTRL-01 一部のデータ取得に失敗しています  詳細はログをご確認ください') in caplog.record_tuples

    @pytest.mark.parametrize(
        'exception, message',
        [
            (ForTestMeDaCaCRMDataFetchException, f'I-ERR-03 [Account] の[{FETCH_JP_NAME}]でエラーが発生しました 次のオブジェクトの処理に移行します'),
            (ForTestException, 'I-ERR-04 [Account] の処理中に予期せぬエラーが発生しました 次のオブジェクトの処理に移行します エラー内容: [例外発生]')
        ])
    def test_raise_fetch_crm_data_process(self, caplog, exception, message, run_control_process):
        """
        Cases:
            1. CRMデータ取得処理でシステム例外が発生した場合、エラーログが送出され、後続の終了に移行すること
            2. CRMデータ取得処理で想定外の例外が発生した場合、エラーログが送出され、後続の終了に移行すること
        Arranges:
            - パラメータ１：CRMデータ取得処理でシステム例外が発生するようにする
            - パラメータ２：CRMデータ取得処理で想定外の例外が発生するようにする
        Expects:
            - CRMデータ取得処理で例外が発生すること
            - CRMデータ取得処理で発生した例外のログメッセージが出力されていること
        """
        mock_return_values = [COMMON_TARGET_OBJECTS_1, COMMON_TARGET_OBJECTS_2, COMMON_TARGET_OBJECTS_3]

        self.mock_prepare_data_fetch_process = MagicMock(return_value=(deepcopy(COMMON_FETCH_TARGET_OBJECTS), COMMON_EXECUTE_DATETIME, {}))
        self.mock_check_object_info_process = MagicMock(side_effect=mock_return_values)
        self.mock_set_datetime_period_process = MagicMock(return_value=COMMON_LAST_FETCH_DATETIME)
        self.mock_fetch_crm_data_process = MagicMock(side_effect=[exception(
            'E-FETCH-01', FETCH_JP_NAME, '例外発生'), [{'Name': 'Test'}], [{'Name': 'Test'}]])
        self.mock_backup_crm_data_process = MagicMock()
        self.mock_convert_crm_csv_data_process = MagicMock()
        self.mock_backup_crm_csv_data_process = MagicMock()
        self.mock_copy_crm_csv_data_process = MagicMock()
        self.mock_upload_last_fetch_datetime_process = MagicMock()
        self.mock_upload_result_data_process = MagicMock()

        run_control_process()

        assert self.mock_fetch_crm_data_process.call_count == 3
        assert self.mock_backup_crm_data_process.call_count == 2
        expect_process_result = {
            'Account': 'fail',
            'Contact': 'success',
            'Call2_vod__c': 'success'
        }
        assert generate_log_message_tuple(log_message=message) in caplog.record_tuples
        assert generate_log_message_tuple(log_message=f'I-CTRL-17 すべてのオブジェクトの処理が終了しました 実行結果：[{expect_process_result}]') in caplog.record_tuples
        assert generate_log_message_tuple(
            log_level=logging.ERROR, log_message=f'E-CTRL-01 一部のデータ取得に失敗しています  詳細はログをご確認ください') in caplog.record_tuples

    @pytest.mark.parametrize(
        'exception, message',
        [
            (ForTestMeDaCaCRMDataFetchException, f'I-ERR-03 [Account] の[{RESBK_JP_NAME}]でエラーが発生しました 次のオブジェクトの処理に移行します'),
            (ForTestException, 'I-ERR-04 [Account] の処理中に予期せぬエラーが発生しました 次のオブジェクトの処理に移行します エラー内容: [例外発生]')
        ])
    def test_raise_backup_crm_data_process(self, caplog, exception, message, run_control_process):
        """
        Cases:
            1. CRM電文データバックアップ処理でシステム例外が発生した場合、エラーログが送出され、後続の終了に移行すること
            2. CRM電文データバックアップ処理で想定外の例外が発生した場合、エラーログが送出され、後続の終了に移行すること
        Arranges:
            - パラメータ１：CRM電文データバックアップ処理でシステム例外が発生するようにする
            - パラメータ２：CRM電文データバックアップ処理で想定外の例外が発生するようにする
        Expects:
            - CRM電文データバックアップ処理で例外が発生すること
            - CRM電文データバックアップ処理で発生した例外のログメッセージが出力されていること
        """
        mock_return_values = [COMMON_TARGET_OBJECTS_1, COMMON_TARGET_OBJECTS_2, COMMON_TARGET_OBJECTS_3]

        self.mock_prepare_data_fetch_process = MagicMock(return_value=(deepcopy(COMMON_FETCH_TARGET_OBJECTS), COMMON_EXECUTE_DATETIME, {}))
        self.mock_check_object_info_process = MagicMock(side_effect=mock_return_values)
        self.mock_set_datetime_period_process = MagicMock(return_value=COMMON_LAST_FETCH_DATETIME)
        self.mock_fetch_crm_data_process = MagicMock(side_effect=[[{'Name': 'Test'}], [{'Name': 'Test'}], [{'Name': 'Test'}]])
        self.mock_backup_crm_data_process = MagicMock(side_effect=[exception(
            'E-RESBK-01', RESBK_JP_NAME, '例外発生'), None, None])
        self.mock_convert_crm_csv_data_process = MagicMock()
        self.mock_backup_crm_csv_data_process = MagicMock()
        self.mock_copy_crm_csv_data_process = MagicMock()
        self.mock_upload_last_fetch_datetime_process = MagicMock()
        self.mock_upload_result_data_process = MagicMock()

        run_control_process()

        assert self.mock_backup_crm_data_process.call_count == 3
        assert self.mock_convert_crm_csv_data_process.call_count == 2
        expect_process_result = {
            'Account': 'fail',
            'Contact': 'success',
            'Call2_vod__c': 'success'
        }
        assert generate_log_message_tuple(log_message=message) in caplog.record_tuples
        assert generate_log_message_tuple(log_message=f'I-CTRL-17 すべてのオブジェクトの処理が終了しました 実行結果：[{expect_process_result}]') in caplog.record_tuples
        assert generate_log_message_tuple(
            log_level=logging.ERROR, log_message=f'E-CTRL-01 一部のデータ取得に失敗しています  詳細はログをご確認ください') in caplog.record_tuples

    @pytest.mark.parametrize(
        'exception, message',
        [
            (ForTestMeDaCaCRMDataFetchException, f'I-ERR-03 [Account] の[{CONV_JP_NAME}]でエラーが発生しました 次のオブジェクトの処理に移行します'),
            (ForTestException, 'I-ERR-04 [Account] の処理中に予期せぬエラーが発生しました 次のオブジェクトの処理に移行します エラー内容: [例外発生]')
        ])
    def test_raise_convert_crm_csv_data_process(self, caplog, exception, message, run_control_process):
        """
        Cases:
            1. CSV変換処理でシステム例外が発生した場合、エラーログが送出され、後続の終了に移行すること
            2. CSV変換処理で想定外の例外が発生した場合、エラーログが送出され、後続の終了に移行すること
        Arranges:
            - パラメータ１：CSV変換処理でシステム例外が発生するようにする
            - パラメータ２：CSV変換処理で想定外の例外が発生するようにする
        Expects:
            - CSV変換処理で例外が発生すること
            - CSV変換処理で発生した例外のログメッセージが出力されていること
        """
        mock_return_values = [COMMON_TARGET_OBJECTS_1, COMMON_TARGET_OBJECTS_2, COMMON_TARGET_OBJECTS_3]

        self.mock_prepare_data_fetch_process = MagicMock(return_value=(deepcopy(COMMON_FETCH_TARGET_OBJECTS), COMMON_EXECUTE_DATETIME, {}))
        self.mock_check_object_info_process = MagicMock(side_effect=mock_return_values)
        self.mock_set_datetime_period_process = MagicMock(return_value=COMMON_LAST_FETCH_DATETIME)
        self.mock_fetch_crm_data_process = MagicMock(side_effect=[[{'Name': 'Test'}], [{'Name': 'Test'}], [{'Name': 'Test'}]])
        self.mock_backup_crm_data_process = MagicMock()
        self.mock_convert_crm_csv_data_process = MagicMock(side_effect=[exception(
            'E-CONV-01', CONV_JP_NAME, '例外発生'), None, None])
        self.mock_backup_crm_csv_data_process = MagicMock()
        self.mock_copy_crm_csv_data_process = MagicMock()
        self.mock_upload_last_fetch_datetime_process = MagicMock()
        self.mock_upload_result_data_process = MagicMock()

        run_control_process()

        assert self.mock_convert_crm_csv_data_process.call_count == 3
        assert self.mock_backup_crm_csv_data_process.call_count == 2
        expect_process_result = {
            'Account': 'fail',
            'Contact': 'success',
            'Call2_vod__c': 'success'
        }
        assert generate_log_message_tuple(log_message=message) in caplog.record_tuples
        assert generate_log_message_tuple(log_message=f'I-CTRL-17 すべてのオブジェクトの処理が終了しました 実行結果：[{expect_process_result}]') in caplog.record_tuples
        assert generate_log_message_tuple(
            log_level=logging.ERROR, log_message=f'E-CTRL-01 一部のデータ取得に失敗しています  詳細はログをご確認ください') in caplog.record_tuples

    @pytest.mark.parametrize(
        'exception, message',
        [
            (ForTestMeDaCaCRMDataFetchException, f'I-ERR-03 [Account] の[{CSVBK_JP_NAME}]でエラーが発生しました 次のオブジェクトの処理に移行します'),
            (ForTestException, 'I-ERR-04 [Account] の処理中に予期せぬエラーが発生しました 次のオブジェクトの処理に移行します エラー内容: [例外発生]')
        ])
    def test_raise_backup_crm_csv_data_process(self, caplog, exception, message, run_control_process):
        """
        Cases:
            1. CSVバックアップ処理でシステム例外が発生した場合、エラーログが送出され、後続の終了に移行すること
            2. CSVバックアップ処理で想定外の例外が発生した場合、エラーログが送出され、後続の終了に移行すること
        Arranges:
            - パラメータ１：CSVバックアップ処理でシステム例外が発生するようにする
            - パラメータ２：CSVバックアップ処理で想定外の例外が発生するようにする
        Expects:
            - CSVバックアップ処理で例外が発生すること
            - CSVバックアップ処理で発生した例外のログメッセージが出力されていること
        """
        mock_return_values = [COMMON_TARGET_OBJECTS_1, COMMON_TARGET_OBJECTS_2, COMMON_TARGET_OBJECTS_3]

        self.mock_prepare_data_fetch_process = MagicMock(return_value=(deepcopy(COMMON_FETCH_TARGET_OBJECTS), COMMON_EXECUTE_DATETIME, {}))
        self.mock_check_object_info_process = MagicMock(side_effect=mock_return_values)
        self.mock_set_datetime_period_process = MagicMock(return_value=COMMON_LAST_FETCH_DATETIME)
        self.mock_fetch_crm_data_process = MagicMock(side_effect=[[{'Name': 'Test'}], [{'Name': 'Test'}], [{'Name': 'Test'}]])
        self.mock_backup_crm_data_process = MagicMock()
        self.mock_convert_crm_csv_data_process = MagicMock()
        self.mock_backup_crm_csv_data_process = MagicMock(side_effect=[exception(
            'E-CSVBK-01', CSVBK_JP_NAME, '例外発生'), None, None])
        self.mock_copy_crm_csv_data_process = MagicMock()
        self.mock_upload_last_fetch_datetime_process = MagicMock()
        self.mock_upload_result_data_process = MagicMock()

        run_control_process()

        assert self.mock_backup_crm_csv_data_process.call_count == 3
        assert self.mock_copy_crm_csv_data_process.call_count == 2
        expect_process_result = {
            'Account': 'fail',
            'Contact': 'success',
            'Call2_vod__c': 'success'
        }
        assert generate_log_message_tuple(log_message=message) in caplog.record_tuples
        assert generate_log_message_tuple(log_message=f'I-CTRL-17 すべてのオブジェクトの処理が終了しました 実行結果：[{expect_process_result}]') in caplog.record_tuples
        assert generate_log_message_tuple(
            log_level=logging.ERROR, log_message=f'E-CTRL-01 一部のデータ取得に失敗しています  詳細はログをご確認ください') in caplog.record_tuples

    @pytest.mark.parametrize(
        'exception, message',
        [
            (ForTestMeDaCaCRMDataFetchException, f'I-ERR-03 [Account] の[{UPLD_JP_NAME}]でエラーが発生しました 次のオブジェクトの処理に移行します'),
            (ForTestException, 'I-ERR-04 [Account] の処理中に予期せぬエラーが発生しました 次のオブジェクトの処理に移行します エラー内容: [例外発生]')
        ])
    def test_raise_copy_crm_csv_data_process(self, caplog, exception, message, run_control_process):
        """
        Cases:
            1. CSVアップロード処理でシステム例外が発生した場合、エラーログが送出され、後続の終了に移行すること
            2. CSVアップロード処理で想定外の例外が発生した場合、エラーログが送出され、後続の終了に移行すること
        Arranges:
            - パラメータ１：CSVアップロード処理でシステム例外が発生するようにする
            - パラメータ２：CSVアップロード処理で想定外の例外が発生するようにする
        Expects:
            - CSVアップロード処理で例外が発生すること
            - CSVアップロード処理で発生した例外のログメッセージが出力されていること
        """
        mock_return_values = [COMMON_TARGET_OBJECTS_1, COMMON_TARGET_OBJECTS_2, COMMON_TARGET_OBJECTS_3]

        self.mock_prepare_data_fetch_process = MagicMock(return_value=(deepcopy(COMMON_FETCH_TARGET_OBJECTS), COMMON_EXECUTE_DATETIME, {}))
        self.mock_check_object_info_process = MagicMock(side_effect=mock_return_values)
        self.mock_set_datetime_period_process = MagicMock(return_value=COMMON_LAST_FETCH_DATETIME)
        self.mock_fetch_crm_data_process = MagicMock(side_effect=[[{'Name': 'Test'}], [{'Name': 'Test'}], [{'Name': 'Test'}]])
        self.mock_backup_crm_data_process = MagicMock()
        self.mock_convert_crm_csv_data_process = MagicMock()
        self.mock_backup_crm_csv_data_process = MagicMock()
        self.mock_copy_crm_csv_data_process = MagicMock(side_effect=[exception(
            'E-UPLD-01', UPLD_JP_NAME, '例外発生'), None, None])
        self.mock_upload_last_fetch_datetime_process = MagicMock()
        self.mock_upload_result_data_process = MagicMock()

        run_control_process()

        assert self.mock_copy_crm_csv_data_process.call_count == 3
        assert self.mock_upload_last_fetch_datetime_process.call_count == 2
        expect_process_result = {
            'Account': 'fail',
            'Contact': 'success',
            'Call2_vod__c': 'success'
        }
        assert generate_log_message_tuple(log_message=message) in caplog.record_tuples
        assert generate_log_message_tuple(log_message=f'I-CTRL-17 すべてのオブジェクトの処理が終了しました 実行結果：[{expect_process_result}]') in caplog.record_tuples
        assert generate_log_message_tuple(
            log_level=logging.ERROR, log_message=f'E-CTRL-01 一部のデータ取得に失敗しています  詳細はログをご確認ください') in caplog.record_tuples

    @pytest.mark.parametrize(
        'exception, message',
        [
            (ForTestMeDaCaCRMDataFetchException, f'I-ERR-03 [Account] の[{UPD_JP_NAME}]でエラーが発生しました 次のオブジェクトの処理に移行します'),
            (ForTestException, 'I-ERR-04 [Account] の処理中に予期せぬエラーが発生しました 次のオブジェクトの処理に移行します エラー内容: [例外発生]')
        ])
    def test_raise_upload_last_fetch_datetime_process(self, caplog, exception, message, run_control_process):
        """
        Cases:
            1. 前回取得日時ファイル更新処理でシステム例外が発生した場合、エラーログが送出され、後続の終了に移行すること
            2. 前回取得日時ファイル更新処理で想定外の例外が発生した場合、エラーログが送出され、後続の終了に移行すること
        Arranges:
            - パラメータ１：前回取得日時ファイル更新処理でシステム例外が発生するようにする
            - パラメータ２：前回取得日時ファイル更新処理で想定外の例外が発生するようにする
        Expects:
            - 前回取得日時ファイル更新処理で例外が発生すること
            - 前回取得日時ファイル更新処理で発生した例外のログメッセージが出力されていること
        """
        mock_return_values = [COMMON_TARGET_OBJECTS_1, COMMON_TARGET_OBJECTS_2, COMMON_TARGET_OBJECTS_3]

        self.mock_prepare_data_fetch_process = MagicMock(return_value=(deepcopy(COMMON_FETCH_TARGET_OBJECTS), COMMON_EXECUTE_DATETIME, {}))
        self.mock_check_object_info_process = MagicMock(side_effect=mock_return_values)
        self.mock_set_datetime_period_process = MagicMock(return_value=COMMON_LAST_FETCH_DATETIME)
        self.mock_fetch_crm_data_process = MagicMock(side_effect=[[{'Name': 'Test'}], [{'Name': 'Test'}], [{'Name': 'Test'}]])
        self.mock_backup_crm_data_process = MagicMock()
        self.mock_convert_crm_csv_data_process = MagicMock()
        self.mock_backup_crm_csv_data_process = MagicMock()
        self.mock_copy_crm_csv_data_process = MagicMock()
        self.mock_upload_last_fetch_datetime_process = MagicMock(side_effect=[exception(
            'E-UPD-01', UPD_JP_NAME, '例外発生'), None, None])
        self.mock_upload_result_data_process = MagicMock()

        run_control_process()

        assert self.mock_upload_last_fetch_datetime_process.call_count == 3
        expect_process_result = {
            'Account': 'fail',
            'Contact': 'success',
            'Call2_vod__c': 'success'
        }
        assert generate_log_message_tuple(log_message=message) in caplog.record_tuples
        assert generate_log_message_tuple(log_message=f'I-CTRL-17 すべてのオブジェクトの処理が終了しました 実行結果：[{expect_process_result}]') in caplog.record_tuples
        assert generate_log_message_tuple(
            log_level=logging.ERROR, log_message=f'E-CTRL-01 一部のデータ取得に失敗しています  詳細はログをご確認ください') in caplog.record_tuples

    @pytest.mark.parametrize(
        'exception, message',
        [
            (ForTestMeDaCaCRMDataFetchException, f'E-ERR-01 [{END_JP_NAME}]でエラーが発生したため、処理を終了します'),
            (ForTestException, 'E-ERR-02 予期せぬエラーが発生したため、処理を終了します エラー内容: [例外発生]')
        ])
    def test_raise_upload_result_data_process(self, caplog, exception, message, run_control_process):
        """
        Cases:
            1. 取得処理実施結果アップロード処理でシステム例外が発生した場合、エラーで終了すること
            2. 取得処理実施結果アップロード処理で想定外の例外が発生した場合、エラーで終了すること
        Arranges:
            - パラメータ１：取得処理実施結果アップロード処理でシステム例外が発生するようにする
            - パラメータ２：取得処理実施結果アップロード処理で想定外の例外が発生するようにする
        Expects:
            - 取得処理実施結果アップロード処理で例外が発生すること
            - 取得処理実施結果アップロード処理で発生した例外のログメッセージが出力されていること
        """
        mock_return_values = [COMMON_TARGET_OBJECTS_1, COMMON_TARGET_OBJECTS_2, COMMON_TARGET_OBJECTS_3]

        self.mock_prepare_data_fetch_process = MagicMock(return_value=(deepcopy(COMMON_FETCH_TARGET_OBJECTS), COMMON_EXECUTE_DATETIME, {}))
        self.mock_check_object_info_process = MagicMock(side_effect=mock_return_values)
        self.mock_set_datetime_period_process = MagicMock(return_value=COMMON_LAST_FETCH_DATETIME)
        self.mock_fetch_crm_data_process = MagicMock(side_effect=[[{'Name': 'Test'}], [{'Name': 'Test'}], [{'Name': 'Test'}]])
        self.mock_backup_crm_data_process = MagicMock()
        self.mock_convert_crm_csv_data_process = MagicMock()
        self.mock_backup_crm_csv_data_process = MagicMock()
        self.mock_copy_crm_csv_data_process = MagicMock()
        self.mock_upload_last_fetch_datetime_process = MagicMock()
        self.mock_upload_result_data_process = MagicMock(side_effect=[exception(
            'E-END-01', END_JP_NAME, '例外発生'), None, None])

        with pytest.raises(exception):
            run_control_process()

        assert self.mock_upload_result_data_process.called is True
        assert self.mock_upload_result_data_process.call_count == 1
        assert generate_log_message_tuple(
            log_level=logging.ERROR,
            log_message=message) in caplog.record_tuples, '取得処理実施結果アップロード処理で発生した例外のログメッセージが出力されていること'
