From 03458d851a23ea1091f841f0bfea875e656de6ce Mon Sep 17 00:00:00 2001 From: "shimoda.m@nds-tyo.co.jp" Date: Fri, 5 Aug 2022 21:32:04 +0900 Subject: [PATCH 1/8] =?UTF-8?q?feat:=20=E3=83=AD=E3=82=B0=E3=83=A1?= =?UTF-8?q?=E3=83=83=E3=82=BB=E3=83=BC=E3=82=B8=E7=94=9F=E6=88=90=E3=83=A6?= =?UTF-8?q?=E3=83=BC=E3=83=86=E3=82=A3=E3=83=AA=E3=83=86=E3=82=A3=E9=96=A2?= =?UTF-8?q?=E6=95=B0=E8=BF=BD=E5=8A=A0=EF=BC=88=E4=BB=96=E3=83=96=E3=83=A9?= =?UTF-8?q?=E3=83=B3=E3=83=81=E3=81=8B=E3=82=89Cherry-Pick=E3=81=97?= =?UTF-8?q?=E3=81=9F=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ecs/crm-datafetch/tests/test_utils/log_message.py | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 ecs/crm-datafetch/tests/test_utils/log_message.py diff --git a/ecs/crm-datafetch/tests/test_utils/log_message.py b/ecs/crm-datafetch/tests/test_utils/log_message.py new file mode 100644 index 00000000..25ce6e11 --- /dev/null +++ b/ecs/crm-datafetch/tests/test_utils/log_message.py @@ -0,0 +1,7 @@ +"""ログメッセージに関連するテストヘルパー""" + +import logging + + +def generate_log_message_tuple(logger_name='root', log_level=logging.INFO, log_message=''): + return (logger_name, log_level, log_message) From 604a9aa30bf015918c181ace2693c373282148bb Mon Sep 17 00:00:00 2001 From: "shimoda.m@nds-tyo.co.jp" Date: Fri, 5 Aug 2022 22:24:35 +0900 Subject: [PATCH 2/8] =?UTF-8?q?feat:=20=E3=83=87=E3=83=BC=E3=82=BF?= =?UTF-8?q?=E5=8F=96=E5=BE=97=E6=BA=96=E5=82=99=E5=87=A6=E7=90=86=E3=81=AE?= =?UTF-8?q?=E3=83=86=E3=82=B9=E3=83=88=E3=82=92=E8=BF=BD=E5=8A=A0=E3=80=82?= =?UTF-8?q?=E3=81=BE=E3=81=9A=E3=81=AF1=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tests/test_prepare_data_fetch_process.py | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 ecs/crm-datafetch/tests/test_prepare_data_fetch_process.py diff --git a/ecs/crm-datafetch/tests/test_prepare_data_fetch_process.py b/ecs/crm-datafetch/tests/test_prepare_data_fetch_process.py new file mode 100644 index 00000000..8eff4b2a --- /dev/null +++ b/ecs/crm-datafetch/tests/test_prepare_data_fetch_process.py @@ -0,0 +1,94 @@ +import json +import logging +from datetime import datetime + +import pytest +from src.config.objects import FetchTargetObjects +from src.error.exceptions import MeDaCaCRMDataFetchException +from src.prepare_data_fetch_process import prepare_data_fetch_process +from src.system_var.constants import YYYYMMDDTHHMMSSTZ + +from .test_utils.log_message import generate_log_message_tuple + + +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 TestPrepareDataFetchProcess: + + @pytest.fixture + def bucket_name(self): + return 'test-config-bucket' + + @pytest.fixture + def prepare_bucket(self, s3_client, bucket_name): + s3_client.create_bucket(Bucket=bucket_name) + yield + + def test_run_process_success(self, s3_client, prepare_bucket, bucket_name, monkeypatch, caplog): + """ + Cases: + データ取得準備処理が正常終了し、期待通りの結果が返ること + Arranges: + - prepare_bucketフィクスチャで、CRM取得オブジェクト情報ファイルを置くためのモックバケットを作る + - 作成したモックバケットを指すように環境変数を設定する + - CRM取得オブジェクト情報ファイルを置く + Expects: + - CRM取得オブジェクトクラスのインスタンスが返却される + - CRM取得オブジェクトクラスのインスタンスが期待値と一致 + - 実行日時クラスのインスタンスが返却される + - 実行日時クラスが、テスト実行後の日時よりも小さい + - 処理結果出力用の空のdictが返却される + - データ取得準備処理の仕様に沿った正常系ログが出力されること(デバッグログは除く) + """ + # Arrange + target_objects_dict = { + 'objects': [ + { + 'object_name': 'Account', + 'columns': [ + 'Id', + 'Name' + ] + }, + { + 'object_name': 'Contact', + 'columns': [ + 'Id', + 'Name' + ] + } + ] + } + + s3_client.put_object(Bucket=bucket_name, Key='crm/object_info/crm_object_list_diff.json', Body=json.dumps(target_objects_dict)) + # 環境変数を編集 + monkeypatch.setattr('src.aws.s3.CRM_CONFIG_BUCKET', bucket_name) + monkeypatch.setattr('src.aws.s3.OBJECT_INFO_FOLDER', 'crm/object_info') + monkeypatch.setattr('src.aws.s3.OBJECT_INFO_FILENAME', 'crm_object_list_diff.json') + + # Act + actual_fetch_target_objects, actual_execute_datetime, actual_process_result = \ + prepare_data_fetch_process() + + # Assert + + # 返り値の期待値チェック + expect_fetch_target_objects = FetchTargetObjects(target_objects_dict) + assert isinstance(actual_fetch_target_objects, FetchTargetObjects), 'CRM取得オブジェクトクラスのインスタンスが返却される' + assert all([a == e for a, e in zip(actual_fetch_target_objects, expect_fetch_target_objects)]), 'CRM取得オブジェクトクラスのインスタンスが期待値と一致' + assert datetime.strptime(str(actual_execute_datetime), YYYYMMDDTHHMMSSTZ) < datetime.now(), '実行日時がアサーション時点の日時よりも小さいこと' + assert actual_process_result == {}, '処理結果出力用の空のdictが返却される' + + # ログの確認 + assert generate_log_message_tuple(log_message='I-PRE-01 データ取得準備処理を開始します') in caplog.record_tuples + assert generate_log_message_tuple(log_message=f'I-PRE-02 データ取得処理開始日時:{str(actual_execute_datetime)}') in caplog.record_tuples + assert generate_log_message_tuple(log_message='I-PRE-09 データ取得準備処理を終了します') in caplog.record_tuples From fe9f6ef42ae73b91b4f7a3e7dda45d602221411b Mon Sep 17 00:00:00 2001 From: "shimoda.m@nds-tyo.co.jp" Date: Fri, 5 Aug 2022 22:24:58 +0900 Subject: [PATCH 3/8] =?UTF-8?q?style:=20retrun=E3=81=AE=E9=9A=A3=E3=81=AB?= =?UTF-8?q?=E3=82=B9=E3=83=9A=E3=83=BC=E3=82=B9=E3=82=92=E6=8C=BF=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ecs/crm-datafetch/src/prepare_data_fetch_process.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ecs/crm-datafetch/src/prepare_data_fetch_process.py b/ecs/crm-datafetch/src/prepare_data_fetch_process.py index 3488c71f..03427265 100644 --- a/ecs/crm-datafetch/src/prepare_data_fetch_process.py +++ b/ecs/crm-datafetch/src/prepare_data_fetch_process.py @@ -79,4 +79,4 @@ def prepare_data_fetch_process(): logger.info('I-PRE-09 データ取得準備処理を終了します') # ⑧ 次の処理へ移行する - return(fetch_target_objects, execute_datetime, process_result) + return (fetch_target_objects, execute_datetime, process_result) From a4c500331a7e5047753d257f4c2c61bfa5900a6d Mon Sep 17 00:00:00 2001 From: "shimoda.m@nds-tyo.co.jp" Date: Fri, 5 Aug 2022 23:13:17 +0900 Subject: [PATCH 4/8] =?UTF-8?q?feat:=20=E4=BE=9D=E5=AD=98=E3=83=A2?= =?UTF-8?q?=E3=82=B8=E3=83=A5=E3=83=BC=E3=83=AB=E3=81=8C=E5=91=BC=E3=81=B0?= =?UTF-8?q?=E3=82=8C=E3=81=A6=E3=81=84=E3=82=8B=E3=81=8B=E3=81=A9=E3=81=86?= =?UTF-8?q?=E3=81=8B=E3=82=92=E7=A2=BA=E8=AA=8D=E3=81=99=E3=82=8B=E3=83=86?= =?UTF-8?q?=E3=82=B9=E3=83=88=E8=BF=BD=E5=8A=A0=E3=80=81json=5Fparse=20?= =?UTF-8?q?=E2=86=92=20json=5Fparser?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../parser/{json_parse.py => json_parser.py} | 0 .../src/prepare_data_fetch_process.py | 2 +- .../src/set_datetime_period_process.py | 2 +- .../tests/test_prepare_data_fetch_process.py | 36 +++++++++++++++++++ 4 files changed, 38 insertions(+), 2 deletions(-) rename ecs/crm-datafetch/src/parser/{json_parse.py => json_parser.py} (100%) diff --git a/ecs/crm-datafetch/src/parser/json_parse.py b/ecs/crm-datafetch/src/parser/json_parser.py similarity index 100% rename from ecs/crm-datafetch/src/parser/json_parse.py rename to ecs/crm-datafetch/src/parser/json_parser.py diff --git a/ecs/crm-datafetch/src/prepare_data_fetch_process.py b/ecs/crm-datafetch/src/prepare_data_fetch_process.py index 03427265..f0ea9ab6 100644 --- a/ecs/crm-datafetch/src/prepare_data_fetch_process.py +++ b/ecs/crm-datafetch/src/prepare_data_fetch_process.py @@ -1,7 +1,7 @@ from src.aws.s3 import ConfigBucket from src.config.objects import FetchTargetObjects from src.error.exceptions import FileNotFoundException, InvalidConfigException -from src.parser.json_parse import JsonParser +from src.parser.json_parser import JsonParser from src.system_var.constants import PRE_JP_NAME from src.system_var.environments import (CRM_CONFIG_BUCKET, OBJECT_INFO_FILENAME, diff --git a/ecs/crm-datafetch/src/set_datetime_period_process.py b/ecs/crm-datafetch/src/set_datetime_period_process.py index bfebd5c2..062fac97 100644 --- a/ecs/crm-datafetch/src/set_datetime_period_process.py +++ b/ecs/crm-datafetch/src/set_datetime_period_process.py @@ -1,7 +1,7 @@ from src.aws.s3 import ConfigBucket from src.config.objects import LastFetchDatetime, TargetObject from src.error.exceptions import FileNotFoundException, InvalidConfigException -from src.parser.json_parse import JsonParser +from src.parser.json_parser import JsonParser from src.system_var.constants import DATE_JP_NAME from src.system_var.environments import (CRM_CONFIG_BUCKET, LAST_FETCH_DATE_FOLDER) diff --git a/ecs/crm-datafetch/tests/test_prepare_data_fetch_process.py b/ecs/crm-datafetch/tests/test_prepare_data_fetch_process.py index 8eff4b2a..298eb192 100644 --- a/ecs/crm-datafetch/tests/test_prepare_data_fetch_process.py +++ b/ecs/crm-datafetch/tests/test_prepare_data_fetch_process.py @@ -1,6 +1,7 @@ import json import logging from datetime import datetime +from unittest.mock import MagicMock, patch import pytest from src.config.objects import FetchTargetObjects @@ -92,3 +93,38 @@ class TestPrepareDataFetchProcess: assert generate_log_message_tuple(log_message='I-PRE-01 データ取得準備処理を開始します') in caplog.record_tuples assert generate_log_message_tuple(log_message=f'I-PRE-02 データ取得処理開始日時:{str(actual_execute_datetime)}') in caplog.record_tuples assert generate_log_message_tuple(log_message='I-PRE-09 データ取得準備処理を終了します') in caplog.record_tuples + + def mock_get_object_info_file(): + return {} + + def mock_parse(): + return {} + + def mock_constructor(): + pass + + def test_call_depended_modules(self, s3_client, prepare_bucket, bucket_name, monkeypatch, caplog): + """ + Cases: + データ取得準備処理内で依存しているモジュールが正しく呼ばれていること + Arranges: + - データ取得準備処理の依存モジュールをモック化する + Expects: + - 依存しているモジュールが正しく呼ばれている + """ + + # Arrange + mock_config_bucket = MagicMock(return_value='') + mock_json_parser = MagicMock(return_value={}) + mock_fetch_target_objects = MagicMock(return_value=None) + # Act + with patch('src.aws.s3.ConfigBucket.get_object_info_file', mock_config_bucket), \ + patch('src.parser.json_parser.JsonParser.parse', mock_json_parser), \ + patch('src.config.objects.FetchTargetObjects.__init__', mock_fetch_target_objects): + prepare_data_fetch_process() + + # Assert + + assert mock_config_bucket.called is True + assert mock_json_parser.called is True + assert mock_fetch_target_objects.called is True From 37f0c4f1f14a470088e33b8847cda6ceb5936fb3 Mon Sep 17 00:00:00 2001 From: "shimoda.m@nds-tyo.co.jp" Date: Fri, 5 Aug 2022 23:14:08 +0900 Subject: [PATCH 5/8] =?UTF-8?q?feat:=20=E3=81=84=E3=82=89=E3=81=AA?= =?UTF-8?q?=E3=81=84=E3=83=95=E3=82=A3=E3=82=AF=E3=82=B9=E3=83=81=E3=83=A3?= =?UTF-8?q?=E5=BC=95=E6=95=B0=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tests/test_prepare_data_fetch_process.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/ecs/crm-datafetch/tests/test_prepare_data_fetch_process.py b/ecs/crm-datafetch/tests/test_prepare_data_fetch_process.py index 298eb192..e5896058 100644 --- a/ecs/crm-datafetch/tests/test_prepare_data_fetch_process.py +++ b/ecs/crm-datafetch/tests/test_prepare_data_fetch_process.py @@ -94,16 +94,7 @@ class TestPrepareDataFetchProcess: assert generate_log_message_tuple(log_message=f'I-PRE-02 データ取得処理開始日時:{str(actual_execute_datetime)}') in caplog.record_tuples assert generate_log_message_tuple(log_message='I-PRE-09 データ取得準備処理を終了します') in caplog.record_tuples - def mock_get_object_info_file(): - return {} - - def mock_parse(): - return {} - - def mock_constructor(): - pass - - def test_call_depended_modules(self, s3_client, prepare_bucket, bucket_name, monkeypatch, caplog): + def test_call_depended_modules(self): """ Cases: データ取得準備処理内で依存しているモジュールが正しく呼ばれていること From a298e322049aed6317e0470e14bb6311d566f737 Mon Sep 17 00:00:00 2001 From: "shimoda.m@nds-tyo.co.jp" Date: Fri, 5 Aug 2022 23:56:24 +0900 Subject: [PATCH 6/8] =?UTF-8?q?feat:=20=E4=BE=8B=E5=A4=96=E7=B3=BB?= =?UTF-8?q?=E3=83=86=E3=82=B9=E3=83=88=E3=82=B1=E3=83=BC=E3=82=B9=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tests/test_prepare_data_fetch_process.py | 115 +++++++++++++++--- 1 file changed, 99 insertions(+), 16 deletions(-) diff --git a/ecs/crm-datafetch/tests/test_prepare_data_fetch_process.py b/ecs/crm-datafetch/tests/test_prepare_data_fetch_process.py index e5896058..9471946f 100644 --- a/ecs/crm-datafetch/tests/test_prepare_data_fetch_process.py +++ b/ecs/crm-datafetch/tests/test_prepare_data_fetch_process.py @@ -1,28 +1,16 @@ import json -import logging from datetime import datetime from unittest.mock import MagicMock, patch import pytest from src.config.objects import FetchTargetObjects -from src.error.exceptions import MeDaCaCRMDataFetchException +from src.error.exceptions import FileNotFoundException, InvalidConfigException from src.prepare_data_fetch_process import prepare_data_fetch_process -from src.system_var.constants import YYYYMMDDTHHMMSSTZ +from src.system_var.constants import PRE_JP_NAME, YYYYMMDDTHHMMSSTZ from .test_utils.log_message import generate_log_message_tuple -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 TestPrepareDataFetchProcess: @pytest.fixture @@ -39,9 +27,9 @@ class TestPrepareDataFetchProcess: Cases: データ取得準備処理が正常終了し、期待通りの結果が返ること Arranges: - - prepare_bucketフィクスチャで、CRM取得オブジェクト情報ファイルを置くためのモックバケットを作る + - prepare_bucketフィクスチャで、CRM_取得オブジェクト情報ファイルを置くためのモックバケットを作る - 作成したモックバケットを指すように環境変数を設定する - - CRM取得オブジェクト情報ファイルを置く + - CRM_取得オブジェクト情報ファイルを置く Expects: - CRM取得オブジェクトクラスのインスタンスが返却される - CRM取得オブジェクトクラスのインスタンスが期待値と一致 @@ -119,3 +107,98 @@ class TestPrepareDataFetchProcess: assert mock_config_bucket.called is True assert mock_json_parser.called is True assert mock_fetch_target_objects.called is True + + def test_raise_get_object_info(self, bucket_name, monkeypatch, caplog): + """ + Cases: + CRM_取得オブジェクト情報ファイルを取得できない場合、エラーが発生すること + Arranges: + - オブジェクト情報ファイル取得処理で例外が発生するようにする + Expects: + - 例外が発生する + - ファイルが読み込めないエラーが返却される + """ + + # Arrange + monkeypatch.setattr('src.prepare_data_fetch_process.OBJECT_INFO_FILENAME', 'crm_object_list_diff.json') + mock_config_bucket = MagicMock(side_effect=Exception('ファイル取得エラー')) + mock_json_parser = MagicMock(return_value={}) + mock_fetch_target_objects = MagicMock(return_value=None) + # Act + with patch('src.aws.s3.ConfigBucket.get_object_info_file', mock_config_bucket), \ + patch('src.parser.json_parser.JsonParser.parse', mock_json_parser), \ + patch('src.config.objects.FetchTargetObjects.__init__', mock_fetch_target_objects): + with pytest.raises(FileNotFoundException) as e: + prepare_data_fetch_process() + + # Assert + + assert mock_config_bucket.called is True + assert mock_json_parser.called is False + assert mock_fetch_target_objects.called is False + assert e.value.error_id == 'E-PRE-01' + assert e.value.func_name == PRE_JP_NAME + assert e.value.args[0] == f'CRM_取得オブジェクト情報ファイルが存在しません ファイル名:[crm_object_list_diff.json] エラー内容:[ファイル取得エラー]' + + def test_raise_parse_json_str(self, bucket_name, monkeypatch, caplog): + """ + Cases: + CRM_取得オブジェクト情報ファイルをパースできない場合、エラーが発生すること + Arranges: + - オブジェクト情報ファイルパース処理で例外が発生するようにする + Expects: + - 例外が発生する + - パースが失敗した旨、エラーメッセージが表示される + """ + + # Arrange + mock_config_bucket = MagicMock(return_value='') + mock_json_parser = MagicMock(side_effect=Exception('JSONパースエラー')) + mock_fetch_target_objects = MagicMock(return_value=None) + # Act + with patch('src.aws.s3.ConfigBucket.get_object_info_file', mock_config_bucket), \ + patch('src.parser.json_parser.JsonParser.parse', mock_json_parser), \ + patch('src.config.objects.FetchTargetObjects.__init__', mock_fetch_target_objects): + with pytest.raises(InvalidConfigException) as e: + prepare_data_fetch_process() + + # Assert + + assert mock_config_bucket.called is True + assert mock_json_parser.called is True + assert mock_fetch_target_objects.called is False + assert e.value.error_id == 'E-PRE-02' + assert e.value.func_name == PRE_JP_NAME + assert e.value.args[0] == f'CRM_取得オブジェクト情報ファイルのパースに失敗しました エラー内容:[JSONパースエラー]' + + def test_raise_check_objects_format(self, bucket_name, monkeypatch, caplog): + """ + Cases: + CRM_取得オブジェクト情報のキーobjectsの形式チェックが不正の場合、エラーが発生すること + Arranges: + - CRM_取得オブジェクト情報のキーobjectsの形式チェックで例外が発生するようにする + Expects: + - 例外が発生する + - 形式チェックが失敗した旨、エラーメッセージが表示される + """ + + # Arrange + monkeypatch.setattr('src.prepare_data_fetch_process.OBJECT_INFO_FILENAME', 'crm_object_list_diff.json') + mock_config_bucket = MagicMock(return_value='') + mock_json_parser = MagicMock(return_value={}) + mock_fetch_target_objects = MagicMock(side_effect=Exception('形式チェックエラー')) + # Act + with patch('src.aws.s3.ConfigBucket.get_object_info_file', mock_config_bucket), \ + patch('src.parser.json_parser.JsonParser.parse', mock_json_parser), \ + patch('src.config.objects.FetchTargetObjects.__init__', mock_fetch_target_objects): + with pytest.raises(InvalidConfigException) as e: + prepare_data_fetch_process() + + # Assert + + assert mock_config_bucket.called is True + assert mock_json_parser.called is True + assert mock_fetch_target_objects.called is True + assert e.value.error_id == 'E-PRE-03' + assert e.value.func_name == PRE_JP_NAME + assert e.value.args[0] == 'CRM_取得オブジェクト情報ファイルの形式チェックに失敗しました ファイル名:[crm_object_list_diff.json] エラー内容:[形式チェックエラー]' From 4e215335f7fea1f19a4b7d92b2ad4d1538786d5a Mon Sep 17 00:00:00 2001 From: "shimoda.m@nds-tyo.co.jp" Date: Sat, 6 Aug 2022 00:13:54 +0900 Subject: [PATCH 7/8] =?UTF-8?q?feat:=20=E4=BB=96PR=E3=81=AE=E3=83=95?= =?UTF-8?q?=E3=82=A3=E3=83=BC=E3=83=89=E3=83=90=E3=83=83=E3=82=AF=20S3?= =?UTF-8?q?=E3=81=AE=E4=BE=8B=E5=A4=96=E3=83=86=E3=82=B9=E3=83=88=E3=82=92?= =?UTF-8?q?=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ecs/crm-datafetch/tests/aws/test_s3.py | 191 ++++++++++++++++++++++++- 1 file changed, 189 insertions(+), 2 deletions(-) diff --git a/ecs/crm-datafetch/tests/aws/test_s3.py b/ecs/crm-datafetch/tests/aws/test_s3.py index 1daab1e7..943b1e56 100644 --- a/ecs/crm-datafetch/tests/aws/test_s3.py +++ b/ecs/crm-datafetch/tests/aws/test_s3.py @@ -35,6 +35,22 @@ class TestS3Resource: # Assert assert actual == 'aaaaaaaaaaaaaaa' + def test_raise_get_object(self, s3_test, s3_client, bucket_name): + """ + Cases: + - オブジェクトのキーが存在しない場合エラーになること + Arranges: + - S3をモック化する + Expects: + - オブジェクト取得時にエラーになること + """ + # Arrange + # Act + sut = S3Resource(bucket_name) + with pytest.raises(Exception): + # Assert + sut.get_object('hogehoge/test.txt') + def test_put_object(self, s3_test, s3_client, bucket_name): """ Cases: @@ -52,6 +68,23 @@ class TestS3Resource: assert actual['Body'].read().decode('utf-8') == 'aaaaaaaaaaaaaaa' + def test_raise_put_object(self, s3_client, bucket_name): + """ + Cases: + - バケットが存在しない場合エラーになること + Arranges: + - S3をモック化する + - バケットを作成しない + Expects: + - オブジェクト登録時にエラーになること + """ + # Arrange + # Act + sut = S3Resource(bucket_name) + with pytest.raises(Exception): + # Assert + sut.put_object('hogehoge/test.txt', 'aaaaaaaaaaaaaaa') + def test_copy(self, s3_test, s3_client, bucket_name): """ Cases: @@ -74,7 +107,23 @@ class TestS3Resource: actual = s3_client.get_object(Bucket=for_copy_bucket, Key='test.txt') assert actual['Body'].read() == b'aaaaaaaaaaaaaaa' - def test_init_raise_no_provide_bucket_name(self): + def test_raise_copy(self, s3_client, s3_test, bucket_name): + """ + Cases: + - コピー対象のキーが存在しない場合エラーになること + Arranges: + - S3をモック化する + Expects: + - オブジェクト登録時にエラーになること + """ + # Arrange + # Act + sut = S3Resource(bucket_name) + with pytest.raises(Exception): + # Assert + sut.copy(bucket_name, 'hogehoge/test.txt', 'for_copy_bucket', 'test.txt') + + def test_raise_init_no_provide_bucket_name(self): """ Cases: - バケット名を指定しない場合、例外となること @@ -95,6 +144,7 @@ class TestConfigBucket: Cases: - オブジェクト情報ファイルが取得できること Arranges: + - 環境変数を置き換える - オブジェクト情報ファイルを配置する Expects: - オブジェクト情報ファイルが文字列として取得でき、期待値と一致する @@ -109,6 +159,24 @@ class TestConfigBucket: assert actual == 'aaaaaaaaaaaaaaa' + def test_raise_get_object_info_file(self, s3_test, s3_client, bucket_name, monkeypatch): + """ + Cases: + - オブジェクト情報ファイルが存在しない場合、エラーになること + Arranges: + - s3_testフィクスチャを引数に指定しない + - 環境変数を置き換える + Expects: + - オブジェクト情報ファイルが取得できず、例外が発生する + """ + monkeypatch.setattr('src.aws.s3.CRM_CONFIG_BUCKET', bucket_name) + monkeypatch.setattr('src.aws.s3.OBJECT_INFO_FOLDER', 'crm') + monkeypatch.setattr('src.aws.s3.OBJECT_INFO_FILENAME', 'objects.json') + + sut = ConfigBucket() + with pytest.raises(Exception): + sut.get_object_info_file() + def test_get_last_fetch_datetime_file(self, s3_test, s3_client, bucket_name, monkeypatch): """ Cases: @@ -128,6 +196,23 @@ class TestConfigBucket: assert actual == 'aaaaaaaaaaaaaaa' + def test_raise_get_last_fetch_datetime_file(self, s3_test, s3_client, bucket_name, monkeypatch): + """ + Cases: + - オブジェクト最終更新日時ファイルが存在しない場合、エラーになること + Arranges: + - s3_testフィクスチャを引数に指定しない + - 環境変数を置き換える + Expects: + - オブジェクト最終更新日時ファイルが取得できず、例外が発生する + """ + monkeypatch.setattr('src.aws.s3.CRM_CONFIG_BUCKET', bucket_name) + monkeypatch.setattr('src.aws.s3.LAST_FETCH_DATE_FOLDER', 'crm') + + sut = ConfigBucket() + with pytest.raises(Exception): + sut.get_last_fetch_datetime_file('Object.json') + def test_put_last_fetch_datetime_file(self, s3_test, s3_client, bucket_name, monkeypatch): """ Cases: @@ -147,6 +232,23 @@ class TestConfigBucket: actual = s3_client.get_object(Bucket=bucket_name, Key=f'crm/Object.json') assert actual['Body'].read().decode('utf-8') == 'aaaaaaaaaaaaaaa' + def test_raise_put_last_fetch_datetime_file(self, s3_client, bucket_name, monkeypatch): + """ + Cases: + - オブジェクト最終更新日時ファイルをPUTできない場合、エラーになること + Arranges: + - s3_testフィクスチャを引数に指定しない + - 環境変数を置き換える + Expects: + - オブジェクト最終更新日時ファイルをPUTできず、例外が発生する + """ + monkeypatch.setattr('src.aws.s3.CRM_CONFIG_BUCKET', bucket_name) + monkeypatch.setattr('src.aws.s3.LAST_FETCH_DATE_FOLDER', 'crm') + + sut = ConfigBucket() + with pytest.raises(Exception): + sut.put_last_fetch_datetime_file('Object.json', 'aaaaaaaaaaaaaaa') + def test_config_bucket_str(self, s3_test, s3_client, bucket_name, monkeypatch): """ Cases: @@ -184,6 +286,23 @@ class TestDataBucket: actual = s3_client.get_object(Bucket=bucket_name, Key=f'crm/target/test.csv') assert actual['Body'].read().decode('utf-8') == 'test,test,test' + def test_raise_put_csv(self, s3_client, bucket_name, monkeypatch): + """ + Cases: + - CSVファイルをPUTできず、エラーになること + Arranges: + - s3_testフィクスチャを引数に指定しない + - 環境変数を置き換える + Expects: + - CSVファイルをPUTできず、例外が発生する + """ + monkeypatch.setattr('src.aws.s3.IMPORT_DATA_BUCKET', bucket_name) + monkeypatch.setattr('src.aws.s3.CRM_IMPORT_DATA_FOLDER', 'crm/target') + + sut = DataBucket() + with pytest.raises(Exception): + sut.put_csv('test.csv', 'test,test,test') + def test_put_csv_from(self, s3_test, s3_client, bucket_name, monkeypatch): """ Cases: @@ -209,6 +328,23 @@ class TestDataBucket: assert actual['Body'].read().decode('utf-8') == 'test,test,test' + def test_raise_put_csv_from(self, s3_client, bucket_name, monkeypatch): + """ + Cases: + - 他のバケットからCSVファイルをコピーできず、エラーになること + Arranges: + - s3_testフィクスチャを引数に指定しない + - 環境変数を置き換える + Expects: + - コピーできず、例外が発生する + """ + monkeypatch.setattr('src.aws.s3.IMPORT_DATA_BUCKET', 'for_copy_bucket') + monkeypatch.setattr('src.aws.s3.CRM_IMPORT_DATA_FOLDER', 'crm/target') + + sut = DataBucket() + with pytest.raises(Exception): + sut.put_csv_from(bucket_name, 'hogehoge/test.csv') + def test_data_bucket_str(self, s3_test, s3_client, bucket_name, monkeypatch): """ Cases: @@ -246,6 +382,23 @@ class TestBackupBucket: actual = s3_client.get_object(Bucket=bucket_name, Key=f'data_import/test.csv') assert actual['Body'].read().decode('utf-8') == 'test,test,test' + def test_raise_put_csv_from(self, s3_client, bucket_name, monkeypatch): + """ + Cases: + - CSVファイルをPUTできず、エラーになること + Arranges: + - s3_testフィクスチャを引数に指定しない + - 環境変数を置き換える + Expects: + - CSVファイルがPUTできず、例外が発生する + """ + monkeypatch.setattr('src.aws.s3.IMPORT_DATA_BUCKET', bucket_name) + monkeypatch.setattr('src.aws.s3.CRM_IMPORT_DATA_FOLDER', 'crm/target') + + sut = BackupBucket() + with pytest.raises(Exception): + sut.put_csv('test.csv', 'test,test,test') + def test_put_response_json(self, s3_test, s3_client, bucket_name, monkeypatch): """ Cases: @@ -265,10 +418,27 @@ class TestBackupBucket: actual = s3_client.get_object(Bucket=bucket_name, Key=f'response_json/test.json') assert actual['Body'].read().decode('utf-8') == '{"test": "test"}' + def test_raise_response_json(self, s3_client, bucket_name, monkeypatch): + """ + Cases: + - JSONファイルをPUTできず、エラーになること + Arranges: + - s3_testフィクスチャを引数に指定しない + - 環境変数を置き換える + Expects: + - JSONファイルをPUTできず、例外が発生する + """ + monkeypatch.setattr('src.aws.s3.CRM_BACKUP_BUCKET', bucket_name) + monkeypatch.setattr('src.aws.s3.RESPONSE_JSON_BACKUP_FOLDER', 'response_json') + + sut = BackupBucket() + with pytest.raises(Exception): + sut.put_response_json('test.json', {"test": "test"}) + def test_put_result_json(self, s3_test, s3_client, bucket_name, monkeypatch): """ Cases: - - JSONファイルをPUTできること + - 結果のJSONファイルをPUTできること Arranges: - S3をモック化する - 環境変数をテスト用の値に置き換える @@ -284,6 +454,23 @@ class TestBackupBucket: actual = s3_client.get_object(Bucket=bucket_name, Key=f'data_import/result.json') assert actual['Body'].read().decode('utf-8') == '{"test": "test"}' + def test_raise_result_json(self, s3_client, bucket_name, monkeypatch): + """ + Cases: + - 結果のJSONファイルをPUTできず、エラーになること + Arranges: + - s3_testフィクスチャを引数に指定しない + - 環境変数を置き換える + Expects: + - 結果のJSONファイルをPUTできず、例外が発生する + """ + monkeypatch.setattr('src.aws.s3.CRM_BACKUP_BUCKET', bucket_name) + monkeypatch.setattr('src.aws.s3.PROCESS_RESULT_FOLDER', 'data_import') + + sut = BackupBucket() + with pytest.raises(Exception): + sut.put_result_json('result.json', {"test": "test"}) + def test_backup_bucket_str(self, s3_test, s3_client, bucket_name, monkeypatch): """ Cases: From 2153eb5a203d64abe769f7931b2ec83bae89b347 Mon Sep 17 00:00:00 2001 From: Y_SAKAI Date: Mon, 8 Aug 2022 15:23:30 +0900 Subject: [PATCH 8/8] =?UTF-8?q?feat:=20execute=5Fdatetime=E3=81=AE?= =?UTF-8?q?=E3=83=86=E3=82=B9=E3=83=88=E3=82=B3=E3=83=BC=E3=83=89=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tests/util/test_execute_datetime.py | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 ecs/crm-datafetch/tests/util/test_execute_datetime.py diff --git a/ecs/crm-datafetch/tests/util/test_execute_datetime.py b/ecs/crm-datafetch/tests/util/test_execute_datetime.py new file mode 100644 index 00000000..cace2ff8 --- /dev/null +++ b/ecs/crm-datafetch/tests/util/test_execute_datetime.py @@ -0,0 +1,81 @@ +import re +from datetime import datetime, timezone + +from src.util.execute_datetime import ExecuteDateTime + + +class TestExecuteDateTime: + + def test_constructor(self): + """ + Cases: + インスタンス生成テスト + UTC時刻が文字列で設定されるかのチェック + Arranges: + - 現在時刻の保持 + - 期待される値の正規表現作成 + Expects: + - 作成されたクラスが保持している時刻が、期待値と一致すること + - 作成されたクラスが保持している時刻が、正規表現と一致すること + """ + + # Arranges + datetime_now = datetime.now(timezone.utc).strftime('%Y-%m-%dT%H:%M:%S.000Z') + + pattern = r'[12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]\.000Z' + + # Expects + sut = ExecuteDateTime() + + assert str(sut) == datetime_now + assert re.fullmatch(pattern, str(sut)) + + def test_to_path(self) -> str: + """ + Cases: + 生成されたパスがYYYYMMDD/HHMMSSの形式で出力されること + Arranges: + - 現在時刻をパスに変換する + - 期待される値の正規表現作成 + Expects: + - 戻り値が、期待値と一致する + - 戻り値が、正規表現と一致すること + """ + + # Arranges + datetime_now_path = datetime.now(timezone.utc).strftime( + '%Y-%m-%dT%H:%M:%S.000Z').rstrip('000Z').translate(str.maketrans({'-': '/', 'T': '/', ':': None, '.': None})) + + pattern = r'[12]\d{3}\/(0[1-9]|1[0-2])\/(0[1-9]|[12][0-9]|3[01])\/([01][0-9]|2[0-3])[0-5][0-9][0-5][0-9]' + + # Expects + sut = ExecuteDateTime() + actual = sut.to_path() + + assert actual == datetime_now_path + assert re.fullmatch(pattern, actual) + + def test_format_date(self) -> str: + """ + Cases: + 生成されたパスがYYYYMMDDHHMMSSの形式で出力されること + Arranges: + - 現在時刻をパスに変換する + - 期待される値の正規表現作成 + Expects: + - 戻り値が、期待値と一致する + - 戻り値が、正規表現と一致すること + """ + + # Arranges + datetime_now_path = datetime.now(timezone.utc).strftime( + '%Y-%m-%dT%H:%M:%S.000Z').rstrip('000Z').translate(str.maketrans({'-': None, 'T': None, ':': None, '.': None})) + + pattern = r'[12]\d{3}(0[1-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])([01][0-9]|2[0-3])[0-5][0-9][0-5][0-9]' + + # Expects + sut = ExecuteDateTime() + actual = sut.format_date() + + assert actual == datetime_now_path + assert re.fullmatch(pattern, actual)