import logging from unittest.mock import MagicMock, patch import pytest from src import controller from src.config.objects import (FetchTargetObjects, LastFetchDatetime, TargetObject) from src.util.execute_datetime import ExecuteDateTime class TestController: @pytest.fixture() def call_all_processes(self, s3_client, monkeypatch, caplog): """ コントローラー処理内ですべてのプロセス関数が呼ばれることのテストで使用するフィクスチャ 各種プロセス関数をモック化し、正常終了させるように動く Yields: dict: プロセス関数呼び出し後のモックの辞書 """ def _func(): monkeypatch.setattr(FetchTargetObjects, '_FetchTargetObjects__validate', lambda x: None) monkeypatch.setattr(TargetObject, '_TargetObject__validate', lambda x: None) monkeypatch.setattr(LastFetchDatetime, '_LastFetchDatetime__validate', lambda x: None) mock_execute_datetime = ExecuteDateTime() mock_target_objects = FetchTargetObjects({ 'objects': [ { 'object_name': 'Account' }, { 'object_name': 'Contact' }, { 'object_name': 'Call2_vod__c' } ] }) mock_target_object = TargetObject({'object_name': 'Account'}, mock_execute_datetime) mock_last_fetch_datetime = LastFetchDatetime({ 'last_fetch_datetime_from': '1900-01-01T00:00:00.000Z', 'last_fetch_datetime_to': '9999-12-31T59:59:59.000Z' }, mock_execute_datetime) mock_prepare_data_fetch_process = MagicMock(return_value=(mock_target_objects, mock_execute_datetime, {})) mock_check_object_info_process = MagicMock(return_value=mock_target_object) mock_set_datetime_period_process = MagicMock(return_value=mock_last_fetch_datetime) mock_fetch_crm_data_process = MagicMock(return_value=[{}]) mock_backup_crm_data_process = MagicMock() mock_convert_crm_csv_data_process = MagicMock() mock_backup_crm_csv_data_process = MagicMock() mock_copy_crm_csv_data_process = MagicMock() mock_upload_last_fetch_datetime_process = MagicMock() mock_upload_result_data_process = MagicMock() should_call_processes = { 'prepare_data_fetch_process': mock_prepare_data_fetch_process, 'check_object_info_process': mock_check_object_info_process, 'set_datetime_period_process': mock_set_datetime_period_process, 'fetch_crm_data_process': mock_fetch_crm_data_process, 'backup_crm_data_process': mock_backup_crm_data_process, 'convert_crm_csv_data_process': mock_convert_crm_csv_data_process, 'backup_crm_csv_data_process': mock_backup_crm_csv_data_process, 'copy_crm_csv_data_process': mock_copy_crm_csv_data_process, 'upload_last_fetch_datetime_process': mock_upload_last_fetch_datetime_process, 'upload_result_data_process': mock_upload_result_data_process } with patch('src.controller.prepare_data_fetch_process', mock_prepare_data_fetch_process),\ patch('src.controller.check_object_info_process', mock_check_object_info_process),\ patch('src.controller.set_datetime_period_process', mock_set_datetime_period_process),\ patch('src.controller.fetch_crm_data_process', mock_fetch_crm_data_process),\ patch('src.controller.backup_crm_data_process', mock_backup_crm_data_process),\ patch('src.controller.convert_crm_csv_data_process', mock_convert_crm_csv_data_process),\ patch('src.controller.backup_crm_csv_data_process', mock_backup_crm_csv_data_process),\ patch('src.controller.copy_crm_csv_data_process', mock_copy_crm_csv_data_process),\ patch('src.controller.upload_last_fetch_datetime_process', mock_upload_last_fetch_datetime_process),\ patch('src.controller.upload_result_data_process', mock_upload_result_data_process): controller.controller() return should_call_processes yield _func def test_controller_call_all_processes(self, call_all_processes): """ Cases: コントローラー処理からすべてのプロセスが呼ばれること Arranges: - call_all_processesフィクスチャで、コントローラー処理を実行しておく Expects: - データ取得準備処理が1回のみ実行される - オブジェクト情報形式チェック処理が複数回実行される - データ取得期間設定処理が複数回実行される - CRMデータ取得処理が複数回実行される - CRM電文データバックアップ処理が複数回実行される - CSV変換処理が複数回実行される - CSVバックアップ処理が複数回実行される - CSVアップロード処理が複数回実行される - 前回取得日時ファイル更新処理が複数回実行される - 取得処理実施結果アップロード処理が1回のみ実行される """ processes = call_all_processes() processes['prepare_data_fetch_process'].assert_called_once(), 'データ取得準備処理が1回のみ実行されること' assert processes['check_object_info_process'].call_count == 3, 'オブジェクト情報形式チェック処理が複数回実行されること' assert processes['set_datetime_period_process'].call_count == 3, 'データ取得期間設定処理が複数回実行されること' assert processes['fetch_crm_data_process'].call_count == 3, 'CRMデータ取得処理が複数回実行されること' assert processes['backup_crm_data_process'].call_count == 3, 'CRM電文データバックアップ処理が複数回実行されること' assert processes['convert_crm_csv_data_process'].call_count == 3, 'CSV変換処理が複数回実行されること' assert processes['backup_crm_csv_data_process'].call_count == 3, 'CSVバックアップ処理が複数回実行されること' assert processes['copy_crm_csv_data_process'].call_count == 3, 'CSVアップロード処理が複数回実行されること' assert processes['upload_last_fetch_datetime_process'].call_count == 3, '前回取得日次ファイル更新処理が複数回実行されること' processes['upload_result_data_process'].assert_called_once(), '取得処理実施結果アップロード処理が1回のみ実行されること' def test_controller_print_normal_logs(self, call_all_processes, caplog): """ Cases: コントローラー処理の正常系ログがすべての出力されていること Arranges: - call_all_processesフィクスチャで、コントローラー処理を実行しておく Expects: - コントローラー処理の正常系ログがすべて出力されている """ call_all_processes() # シングルトンなロガーを引き回しているので、rootロガーになる assert ('root', logging.INFO, 'I-CTRL-01 CRMデータ取得処理を開始します') in caplog.record_tuples def test_controller_do_not_call_upload_process_result_process(self, s3_client, monkeypatch, caplog): """ Cases: 処理対象オブジェクトが0件の場合、取得処理実施結果アップロード処理が実行されないこと Arranges: - データ取得準備処理で返される取得対象オブジェクト情報を0件にする - 各種プロセスメソッドと内部で使用している値オブジェクトをモック化する Expects: - データ取得準備処理が1回のみ実行されること - 取得処理実施結果アップロード処理が実行されないこと - 処理対象が存在しない旨を示すログメッセージが出力されていること """ mock_execute_datetime = ExecuteDateTime() mock_prepare_data_fetch_process = MagicMock(return_value=([], mock_execute_datetime, {})) mock_check_object_info_process = MagicMock() mock_set_datetime_period_process = MagicMock() mock_fetch_crm_data_process = MagicMock() mock_backup_crm_data_process = MagicMock() mock_convert_crm_csv_data_process = MagicMock() mock_backup_crm_csv_data_process = MagicMock() mock_copy_crm_csv_data_process = MagicMock() mock_upload_last_fetch_datetime_process = MagicMock() mock_upload_result_data_process = MagicMock() with patch('src.controller.prepare_data_fetch_process', mock_prepare_data_fetch_process),\ patch('src.controller.check_object_info_process', mock_check_object_info_process),\ patch('src.controller.set_datetime_period_process', mock_set_datetime_period_process),\ patch('src.controller.fetch_crm_data_process', mock_fetch_crm_data_process),\ patch('src.controller.backup_crm_data_process', mock_backup_crm_data_process),\ patch('src.controller.convert_crm_csv_data_process', mock_convert_crm_csv_data_process),\ patch('src.controller.backup_crm_csv_data_process', mock_backup_crm_csv_data_process),\ patch('src.controller.copy_crm_csv_data_process', mock_copy_crm_csv_data_process),\ patch('src.controller.upload_last_fetch_datetime_process', mock_upload_last_fetch_datetime_process),\ patch('src.controller.upload_result_data_process', mock_upload_result_data_process): controller.controller() mock_prepare_data_fetch_process.assert_called_once(), 'データ取得準備処理が1回のみ実行されること' mock_upload_result_data_process.call_count == 0, '取得処理実施結果アップロード処理が実行されないこと' # シングルトンなロガーを引き回しているので、rootロガーになる assert ('root', logging.INFO, 'I-CTRL-21 処理対象のデータが存在しませんでした') in caplog.record_tuples, '処理対象が存在しない旨を示すログメッセージが出力されていること'