Merge branch 'develop-6crm' into feature-NEWDWH2021-643-converter
This commit is contained in:
commit
cade77d14b
@ -74,7 +74,7 @@
|
||||
|
||||
```text
|
||||
.
|
||||
├── Dockerfile -- Dokcerイメージを作成するためのファイル
|
||||
├── Dockerfile -- Dockerイメージを作成するためのファイル
|
||||
├── Pipfile -- Pipenv(Pythonの仮想環境管理モジュール)で、依存関係を管理するためのファイル
|
||||
├── Pipfile.lock -- Pipenvでインストールされた依存関係のバージョン固定ファイル
|
||||
├── README.md -- README
|
||||
@ -105,7 +105,8 @@
|
||||
│ └── logger.py -- ログ管理クラス
|
||||
│
|
||||
└── tests/ -- テストコード置き場
|
||||
├── aws -- AWS操作モジュールのテスト
|
||||
├── test_utils/ -- テストコードで共通的に使用できる関数群
|
||||
├── aws/ -- AWS操作モジュールのテスト
|
||||
├── ... -- src配下のモジュール構成と同じ階層にテストコードを追加していく
|
||||
├── conftest.py -- pytestのフィクスチャやフックを管理するファイル
|
||||
└── docstring_parser.py -- pytest-htmlのレポート出力用のヘルパー
|
||||
|
||||
@ -2,4 +2,7 @@ from src.controller import controller
|
||||
|
||||
"""CRMデータ取得処理のエントリーポイント"""
|
||||
if __name__ == '__main__':
|
||||
controller()
|
||||
try:
|
||||
exit(controller())
|
||||
except Exception:
|
||||
exit(0)
|
||||
|
||||
@ -1,19 +1,13 @@
|
||||
from src.system_var.constants import (COLUMNS_KEY, COLUMNS_TYPE,
|
||||
DATE_PATTERN_YYYYMMDDTHHMMSSTZ,
|
||||
DATETIME_COLUMN_DEFAULT_VALUE,
|
||||
DATETIME_COLUMN_KEY,
|
||||
DATETIME_COLUMN_TYPE, IS_SKIP_KEY,
|
||||
IS_SKIP_TYPE,
|
||||
IS_UPDATE_LAST_FETCH_DATETIME_KEY,
|
||||
IS_UPDATE_LAST_FETCH_DATETIME_TYPE,
|
||||
LAST_FETCH_DATETIME_FILE_NAME_KEY,
|
||||
LAST_FETCH_DATETIME_FILE_NAME_TYPE,
|
||||
LAST_FETCH_DATETIME_FROM_KEY,
|
||||
LAST_FETCH_DATETIME_TO_KEY,
|
||||
OBJECT_NAME_KEY, OBJECT_NAME_TYPE,
|
||||
OBJECTS_KEY, OBJECTS_TYPE,
|
||||
UPLOAD_FILE_NAME_KEY,
|
||||
UPLOAD_FILE_NAME_TYPE)
|
||||
from src.system_var.constants import (
|
||||
COLUMNS_KEY, COLUMNS_TYPE, DATE_PATTERN_YYYYMMDDTHHMMSSTZ,
|
||||
DATETIME_COLUMN_DEFAULT_VALUE, DATETIME_COLUMN_KEY, DATETIME_COLUMN_TYPE,
|
||||
DATE_PATTERN_EXPECTED_YYYYMMDDTHHMMSSTZ, IS_SKIP_KEY, IS_SKIP_TYPE,
|
||||
IS_UPDATE_LAST_FETCH_DATETIME_KEY, IS_UPDATE_LAST_FETCH_DATETIME_TYPE,
|
||||
LAST_FETCH_DATETIME_FILE_NAME_KEY, LAST_FETCH_DATETIME_FILE_NAME_TYPE,
|
||||
LAST_FETCH_DATETIME_FROM_KEY, LAST_FETCH_DATETIME_FROM_TYPE,
|
||||
LAST_FETCH_DATETIME_TO_KEY, LAST_FETCH_DATETIME_TO_TYPE, OBJECT_NAME_KEY,
|
||||
OBJECT_NAME_TYPE, OBJECTS_KEY, OBJECTS_TYPE, UPLOAD_FILE_NAME_KEY,
|
||||
UPLOAD_FILE_NAME_TYPE)
|
||||
from src.util.dict_checker import DictChecker
|
||||
from src.util.execute_datetime import ExecuteDateTime
|
||||
|
||||
@ -22,7 +16,7 @@ class FetchTargetObjects():
|
||||
def __init__(self, object_info_file_dict) -> None:
|
||||
self.__objects = object_info_file_dict
|
||||
self.__dict_checker = DictChecker(self.__objects)
|
||||
self.validate()
|
||||
self.__validate()
|
||||
self.__i = 0
|
||||
|
||||
def __iter__(self):
|
||||
@ -35,7 +29,7 @@ class FetchTargetObjects():
|
||||
self.__i += 1
|
||||
return value
|
||||
|
||||
def validate(self) -> None:
|
||||
def __validate(self) -> None:
|
||||
self.__dict_checker.assert_key_exist(OBJECTS_KEY)
|
||||
self.__dict_checker.assert_data_type(OBJECTS_KEY, OBJECTS_TYPE)
|
||||
|
||||
@ -58,6 +52,7 @@ class TargetObject():
|
||||
self.__dict_checker.assert_data_type(OBJECT_NAME_KEY, OBJECT_NAME_TYPE)
|
||||
self.__dict_checker.assert_key_exist(COLUMNS_KEY)
|
||||
self.__dict_checker.assert_data_type(COLUMNS_KEY, COLUMNS_TYPE)
|
||||
self.__dict_checker.assert_list_empty(COLUMNS_KEY)
|
||||
|
||||
return
|
||||
|
||||
@ -95,7 +90,7 @@ class TargetObject():
|
||||
def is_update_last_fetch_datetime(self) -> bool:
|
||||
if self.__dict_checker.check_key_exist(IS_UPDATE_LAST_FETCH_DATETIME_KEY):
|
||||
return self.__object_info[IS_UPDATE_LAST_FETCH_DATETIME_KEY]
|
||||
return False
|
||||
return True
|
||||
|
||||
@property
|
||||
def last_fetch_datetime_file_name(self) -> str:
|
||||
@ -107,7 +102,7 @@ class TargetObject():
|
||||
def upload_file_name(self) -> str:
|
||||
if self.__dict_checker.check_key_exist(UPLOAD_FILE_NAME_KEY):
|
||||
return self.__object_info[UPLOAD_FILE_NAME_KEY].format(execute_datetime=self.__execute_datetime.format_date())
|
||||
return f'{self.__object_info[OBJECT_NAME_KEY]}_{self.__execute_datetime.format_date()}'
|
||||
return f'CRM_{self.__object_info[OBJECT_NAME_KEY]}_{self.__execute_datetime.format_date()}'
|
||||
|
||||
@property
|
||||
def datetime_column(self) -> str:
|
||||
@ -122,10 +117,12 @@ class LastFetchDatetime():
|
||||
self.__validate()
|
||||
|
||||
def __validate(self) -> None:
|
||||
if self.__dict_checker.check_key_exist(LAST_FETCH_DATETIME_FROM_KEY):
|
||||
self.__dict_checker.assert_match_pattern(LAST_FETCH_DATETIME_FROM_KEY, DATE_PATTERN_YYYYMMDDTHHMMSSTZ)
|
||||
self.__dict_checker.assert_key_exist(LAST_FETCH_DATETIME_FROM_KEY)
|
||||
self.__dict_checker.assert_data_type(LAST_FETCH_DATETIME_FROM_KEY, LAST_FETCH_DATETIME_FROM_TYPE)
|
||||
self.__dict_checker.assert_match_pattern(LAST_FETCH_DATETIME_FROM_KEY, DATE_PATTERN_YYYYMMDDTHHMMSSTZ,DATE_PATTERN_EXPECTED_YYYYMMDDTHHMMSSTZ)
|
||||
if self.__dict_checker.check_key_exist(LAST_FETCH_DATETIME_TO_KEY):
|
||||
self.__dict_checker.assert_match_pattern(LAST_FETCH_DATETIME_TO_KEY, DATE_PATTERN_YYYYMMDDTHHMMSSTZ)
|
||||
self.__dict_checker.assert_data_type(LAST_FETCH_DATETIME_TO_KEY, LAST_FETCH_DATETIME_TO_TYPE)
|
||||
self.__dict_checker.assert_match_pattern(LAST_FETCH_DATETIME_TO_KEY, DATE_PATTERN_YYYYMMDDTHHMMSSTZ,DATE_PATTERN_EXPECTED_YYYYMMDDTHHMMSSTZ)
|
||||
return
|
||||
|
||||
@property
|
||||
@ -136,4 +133,4 @@ class LastFetchDatetime():
|
||||
def last_fetch_datetime_to(self) -> str:
|
||||
if self.__dict_checker.check_key_exist(LAST_FETCH_DATETIME_TO_KEY):
|
||||
return self.__last_fetch_datetime_file_dict[LAST_FETCH_DATETIME_TO_KEY]
|
||||
return self.__execute_datetime
|
||||
return str(self.__execute_datetime)
|
||||
|
||||
@ -33,37 +33,40 @@ def controller() -> None:
|
||||
# ③ object_infoのobjectsキーの値の件数分ループする
|
||||
logger.info('I-CTRL-03 取得対象オブジェクトのループ処理開始')
|
||||
|
||||
process_result = fetch_crm_data(fetch_target_objects, execute_datetime, process_result)
|
||||
process_result = _fetch_crm_data(fetch_target_objects, execute_datetime, process_result)
|
||||
|
||||
# ④ すべてのオブジェクトの処理が完了したことと、オブジェクト毎の処理結果をログに出力する
|
||||
logger.info(f'I-CTRL-17 すべてのオブジェクトの処理が終了しました 実行結果:[{process_result}]')
|
||||
|
||||
# 最終結果が0件(1件も処理されていない)の場合、ログ出力して処理を終了する
|
||||
if len(process_result.keys()) == 0:
|
||||
logger.info('I-CTRL-21 処理対象のデータが存在しませんでした')
|
||||
return 0
|
||||
|
||||
# ⑤ 取得処理実施結果アップロード処理を呼び出す
|
||||
logger.info('I-CTRL-18 CRM_取得処理実施結果ファイルアップロード処理開始')
|
||||
upload_result_data_process(process_result, execute_datetime)
|
||||
|
||||
# ⑥ 最終結果をチェックし、チェック結果をログに出力
|
||||
if not all([v == 'success' for v in process_result.values()]):
|
||||
logger.error('E-CTRL-01 一部のデータ取得に失敗しています 詳細はログをご確認ください')
|
||||
else:
|
||||
logger.info('I-CTRL-19 すべてのデータの取得に成功しました')
|
||||
_check_process_result(process_result)
|
||||
|
||||
# ⑦ CRMデータ取得処理終了ログを出力する
|
||||
logger.info('I-CTRL-20 CRMデータ取得処理を終了します')
|
||||
|
||||
return exit(0)
|
||||
return 0
|
||||
|
||||
except MeDaCaCRMDataFetchException as e:
|
||||
logger.error(f'E-ERR-01 [{e.func_name}]でエラーが発生したため、処理を終了します')
|
||||
logger.exception(f'{e.error_id} {e}')
|
||||
return exit(0)
|
||||
raise e
|
||||
|
||||
except Exception as e:
|
||||
logger.exception('E-ERR-02 予期せぬエラーが発生したため、処理を終了します', e)
|
||||
return exit(0)
|
||||
logger.exception(f'E-ERR-02 予期せぬエラーが発生したため、処理を終了します エラー内容: [{e}]')
|
||||
raise e
|
||||
|
||||
finally:
|
||||
# ⑦ CRMデータ取得処理終了ログを出力する
|
||||
logger.info('I-CTRL-20 CRMデータ取得処理を終了します')
|
||||
|
||||
|
||||
def fetch_crm_data(fetch_target_objects: FetchTargetObjects, execute_datetime: ExecuteDateTime, process_result: dict):
|
||||
def _fetch_crm_data(fetch_target_objects: FetchTargetObjects, execute_datetime: ExecuteDateTime, process_result: dict):
|
||||
"""取得対象オブジェクト情報をループし、1オブジェクトごとのデータを取得する
|
||||
|
||||
Args:
|
||||
@ -79,7 +82,7 @@ def fetch_crm_data(fetch_target_objects: FetchTargetObjects, execute_datetime: E
|
||||
try:
|
||||
process_result[object_info.get(OBJECT_NAME_KEY)] = 'fail'
|
||||
|
||||
fetch_crm_data_per_object(object_info, execute_datetime)
|
||||
_fetch_crm_data_per_object(object_info, execute_datetime)
|
||||
|
||||
process_result[object_info.get(OBJECT_NAME_KEY)] = 'success'
|
||||
|
||||
@ -91,13 +94,13 @@ def fetch_crm_data(fetch_target_objects: FetchTargetObjects, execute_datetime: E
|
||||
|
||||
except Exception as e:
|
||||
logger.info(
|
||||
f'I-ERR-04 [{object_info.get(OBJECT_NAME_KEY)}] の処理中に予期せぬエラーが発生しました 次のオブジェクトの処理に移行します', e, exc_info=True)
|
||||
f'I-ERR-04 [{object_info.get(OBJECT_NAME_KEY)}] の処理中に予期せぬエラーが発生しました 次のオブジェクトの処理に移行します エラー内容: [{e}]', exc_info=True)
|
||||
continue
|
||||
|
||||
return process_result
|
||||
|
||||
|
||||
def fetch_crm_data_per_object(object_info: dict, execute_datetime: ExecuteDateTime) -> None:
|
||||
def _fetch_crm_data_per_object(object_info: dict, execute_datetime: ExecuteDateTime) -> None:
|
||||
"""オブジェクトごとにCRMのデータを取得し、取込フォルダにアップロードする
|
||||
|
||||
Args:
|
||||
@ -136,6 +139,12 @@ def fetch_crm_data_per_object(object_info: dict, execute_datetime: ExecuteDateTi
|
||||
|
||||
crm_data_response = fetch_crm_data_process(target_object, last_fetch_datetime)
|
||||
|
||||
# 取得件数が0件の場合、次のオブジェクトの処理に移行する
|
||||
if len(crm_data_response) == 0:
|
||||
logger.info(
|
||||
f'I-CTRL-22 [{target_object_name}]のレコード件数が0件のため、ファイルアップロードをスキップします')
|
||||
return
|
||||
|
||||
# 7. 出力ファイル名をログ出力する
|
||||
logger.info(
|
||||
f'I-CTRL-10 [{target_object_name}] の出力ファイル名は [{target_object.upload_file_name}] となります')
|
||||
@ -174,3 +183,18 @@ def fetch_crm_data_per_object(object_info: dict, execute_datetime: ExecuteDateTi
|
||||
logger.info(f'I-CTRL-16 [{target_object_name}] 処理正常終了')
|
||||
|
||||
return
|
||||
|
||||
|
||||
def _check_process_result(process_result: dict) -> None:
|
||||
"""取得処理結果がすべて成功か、一部失敗しているかを判定し、ログ出力する
|
||||
|
||||
Args:
|
||||
process_result (dict): 取得処理結果辞書オブジェクト
|
||||
"""
|
||||
if not all([v == 'success' for v in process_result.values()]):
|
||||
logger.error('E-CTRL-01 一部のデータ取得に失敗しています 詳細はログをご確認ください')
|
||||
return
|
||||
|
||||
logger.info('I-CTRL-19 すべてのデータの取得に成功しました')
|
||||
|
||||
return
|
||||
|
||||
@ -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,
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -50,8 +50,10 @@ S3_CHAR_CODE = 'utf-8'
|
||||
# 正規表現チェック
|
||||
EXCLUDE_SYMBOL = ['#', '/']
|
||||
DATE_PATTERN_YYYYMMDDTHHMMSSTZ = 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'
|
||||
DATE_PATTERN_EXPECTED_YYYYMMDDTHHMMSSTZ = 'YYYY-MM-DDTHH:MM:SS.000Z'
|
||||
DATE_PATTERN_YYYYMMDDHHMMSSFFF_UTC = r'\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.000\+0000'
|
||||
|
||||
|
||||
# logger
|
||||
LOG_FORMAT = '[%(levelname)s]\t%(asctime)s\t%(message)s\n'
|
||||
LOG_DATE_FORMAT = '%Y-%m-%d %H:%M:%S'
|
||||
@ -93,4 +95,6 @@ DATETIME_COLUMN_KEY = 'datetime_column'
|
||||
DATETIME_COLUMN_TYPE = str
|
||||
DATETIME_COLUMN_DEFAULT_VALUE = 'SystemModstamp'
|
||||
LAST_FETCH_DATETIME_TO_KEY = 'last_fetch_datetime_to'
|
||||
LAST_FETCH_DATETIME_TO_TYPE = str
|
||||
LAST_FETCH_DATETIME_FROM_KEY = 'last_fetch_datetime_from'
|
||||
LAST_FETCH_DATETIME_FROM_TYPE = str
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
class CounterObject:
|
||||
def __init__(self, base_num=1) -> None:
|
||||
self.__counter = base_num
|
||||
self.__counter = int(base_num)
|
||||
|
||||
def describe(self) -> int:
|
||||
return self.__counter
|
||||
|
||||
@ -7,11 +7,15 @@ class DictChecker:
|
||||
|
||||
def is_empty(self, check_key):
|
||||
"""辞書型バリュー空文字チェック"""
|
||||
return self.__object_dict[check_key] != '' and self.__object_dict[check_key] is not None
|
||||
return self.__object_dict[check_key] == '' or self.__object_dict[check_key] is None
|
||||
|
||||
def is_list_empty(self, check_key):
|
||||
"""list型データ存在チェック"""
|
||||
return len(self.__object_dict[check_key]) == 0
|
||||
|
||||
def check_key_exist(self, check_key: str) -> bool:
|
||||
"""辞書型キー存在チェック"""
|
||||
return check_key in self.__object_dict and self.is_empty(check_key)
|
||||
return check_key in self.__object_dict and not self.is_empty(check_key)
|
||||
|
||||
def check_data_type(self, check_key: str, check_type: type) -> bool:
|
||||
"""辞書型バリュー型チェック"""
|
||||
@ -35,9 +39,13 @@ class DictChecker:
|
||||
|
||||
return
|
||||
|
||||
def assert_match_pattern(self, check_key: str, regex_str: str):
|
||||
def assert_match_pattern(self, check_key: str, regex_str: str, expected_str: str):
|
||||
"""正規表現検査"""
|
||||
if not self.check_match_pattern(regex_str, check_key):
|
||||
raise Exception(f'「{check_key}」キーの値の正規表現「{regex_str}」チェックに失敗しました')
|
||||
raise Exception(f'「{check_key}」キーの値の正規表現チェックに失敗しました 「{expected_str}」形式である必要があります')
|
||||
|
||||
return
|
||||
|
||||
def assert_list_empty(self, check_key: str):
|
||||
if self.is_list_empty(check_key):
|
||||
raise Exception(f'「{check_key}」キーのリストの値は必須です')
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -0,0 +1,467 @@
|
||||
import pytest
|
||||
from src.config.objects import FetchTargetObjects
|
||||
from src.parser.json_parser import JsonParser
|
||||
|
||||
|
||||
class TestFetchTargetObjects():
|
||||
|
||||
def test_constructor(self) -> None:
|
||||
"""
|
||||
Cases:
|
||||
インスタンス生成テスト
|
||||
辞書型のデータに対して、キーがあるかまた、キーの型が正しいかをチェック
|
||||
Arranges:
|
||||
- オブジェクト情報文字列を準備する
|
||||
- オブジェクト情報を辞書型にパースする
|
||||
Expects:
|
||||
- 例外が発生しないこと
|
||||
"""
|
||||
|
||||
# Arranges
|
||||
fetch_objects = '''{
|
||||
"objects": [
|
||||
{
|
||||
"object_name": "AccountShare",
|
||||
"columns": [
|
||||
"Id",
|
||||
"AccountId",
|
||||
"UserOrGroupId",
|
||||
"AccountAccessLevel",
|
||||
"OpportunityAccessLevel",
|
||||
"CaseAccessLevel",
|
||||
"ContactAccessLevel",
|
||||
"RowCause",
|
||||
"LastModifiedDate",
|
||||
"LastModifiedById",
|
||||
"IsDeleted"
|
||||
],
|
||||
"is_skip": false,
|
||||
"is_update_last_fetch_datetime": true,
|
||||
"datetime_column": "LastModifiedDate"
|
||||
},
|
||||
{
|
||||
"object_name": "Contact",
|
||||
"columns": [
|
||||
"Id",
|
||||
"IsDeleted",
|
||||
"MasterRecordId",
|
||||
"AccountId",
|
||||
"IsPersonAccount",
|
||||
"LastName",
|
||||
"FirstName",
|
||||
"Salutation",
|
||||
"Name",
|
||||
"OtherStreet",
|
||||
"OtherCity",
|
||||
"OtherState",
|
||||
"OtherPostalCode",
|
||||
"OtherCountry",
|
||||
"OtherLatitude",
|
||||
"OtherLongitude",
|
||||
"OtherGeocodeAccuracy",
|
||||
"OtherAddress",
|
||||
"MailingStreet",
|
||||
"MailingCity",
|
||||
"MailingState",
|
||||
"MailingPostalCode",
|
||||
"MailingCountry",
|
||||
"MailingLatitude",
|
||||
"MailingLongitude",
|
||||
"MailingGeocodeAccuracy",
|
||||
"MailingAddress",
|
||||
"Phone",
|
||||
"Fax",
|
||||
"MobilePhone",
|
||||
"HomePhone",
|
||||
"OtherPhone",
|
||||
"AssistantPhone",
|
||||
"ReportsToId",
|
||||
"Email",
|
||||
"Title",
|
||||
"Department",
|
||||
"AssistantName",
|
||||
"Birthdate",
|
||||
"Description",
|
||||
"OwnerId",
|
||||
"HasOptedOutOfEmail",
|
||||
"HasOptedOutOfFax",
|
||||
"DoNotCall",
|
||||
"CreatedDate",
|
||||
"CreatedById",
|
||||
"LastModifiedDate",
|
||||
"LastModifiedById",
|
||||
"SystemModstamp",
|
||||
"LastActivityDate",
|
||||
"LastCURequestDate",
|
||||
"LastCUUpdateDate",
|
||||
"MayEdit",
|
||||
"IsLocked",
|
||||
"LastViewedDate",
|
||||
"LastReferencedDate",
|
||||
"EmailBouncedReason",
|
||||
"EmailBouncedDate",
|
||||
"IsEmailBounced",
|
||||
"PhotoUrl",
|
||||
"Jigsaw",
|
||||
"JigsawContactId",
|
||||
"IndividualId",
|
||||
"Mobile_ID_vod__c",
|
||||
"H1Insights__H1_NPI_Value_for_Testing__c",
|
||||
"H1Insights__H1_Person_ID__c",
|
||||
"H1Insights__H1_Request_Status__c",
|
||||
"H1Insights__H1_URL__c",
|
||||
"H1Insights__NPI_Number__c",
|
||||
"H1Insights__NPI_Number_for_H1_Insights__c",
|
||||
"MSJ_Marketing_Cloud_Integration__c"
|
||||
],
|
||||
"is_skip": false,
|
||||
"is_update_last_fetch_datetime": true
|
||||
},
|
||||
{
|
||||
"object_name": "Territory2",
|
||||
"columns": [
|
||||
"Id",
|
||||
"Name",
|
||||
"Territory2TypeId",
|
||||
"Territory2ModelId",
|
||||
"ParentTerritory2Id",
|
||||
"Description",
|
||||
"ForecastUserId",
|
||||
"AccountAccessLevel",
|
||||
"OpportunityAccessLevel",
|
||||
"CaseAccessLevel",
|
||||
"ContactAccessLevel",
|
||||
"LastModifiedDate",
|
||||
"LastModifiedById",
|
||||
"SystemModstamp",
|
||||
"DeveloperName",
|
||||
"MSJ_Territory_Type__c",
|
||||
"MSJ_Level__c"
|
||||
],
|
||||
"is_skip": false,
|
||||
"is_update_last_fetch_datetime": true
|
||||
}
|
||||
]
|
||||
}'''
|
||||
|
||||
json_parser = JsonParser(fetch_objects)
|
||||
fetch_objects_dict = json_parser.parse()
|
||||
|
||||
# Act
|
||||
FetchTargetObjects(fetch_objects_dict)
|
||||
|
||||
# Expects
|
||||
pass
|
||||
|
||||
def test_raise_constructor_no_key(self) -> None:
|
||||
"""
|
||||
Cases:
|
||||
インスタンス生成テスト
|
||||
辞書型のデータに対して、必要なキーがない場合、例外が発生すること
|
||||
Arranges:
|
||||
- オブジェクト情報文字列を準備する
|
||||
Expects:
|
||||
- 例外が発生し期待値と一致する
|
||||
"""
|
||||
|
||||
# Arranges
|
||||
fetch_objects_dict = {
|
||||
"test_objects": [
|
||||
{
|
||||
"object_name": "AccountShare",
|
||||
"columns": [
|
||||
"Id",
|
||||
"AccountId",
|
||||
"UserOrGroupId",
|
||||
"AccountAccessLevel",
|
||||
"OpportunityAccessLevel",
|
||||
"CaseAccessLevel",
|
||||
"ContactAccessLevel",
|
||||
"RowCause",
|
||||
"LastModifiedDate",
|
||||
"LastModifiedById",
|
||||
"IsDeleted"
|
||||
],
|
||||
"is_skip": False,
|
||||
"is_update_last_fetch_datetime": False,
|
||||
"datetime_column": "LastModifiedDate"
|
||||
},
|
||||
{
|
||||
"object_name": "Contact",
|
||||
"columns": [
|
||||
"Id",
|
||||
"IsDeleted",
|
||||
"MasterRecordId",
|
||||
"AccountId",
|
||||
"IsPersonAccount",
|
||||
"LastName",
|
||||
"FirstName",
|
||||
"Salutation",
|
||||
"Name",
|
||||
"OtherStreet",
|
||||
"OtherCity",
|
||||
"OtherState",
|
||||
"OtherPostalCode",
|
||||
"OtherCountry",
|
||||
"OtherLatitude",
|
||||
"OtherLongitude",
|
||||
"OtherGeocodeAccuracy",
|
||||
"OtherAddress",
|
||||
"MailingStreet",
|
||||
"MailingCity",
|
||||
"MailingState",
|
||||
"MailingPostalCode",
|
||||
"MailingCountry",
|
||||
"MailingLatitude",
|
||||
"MailingLongitude",
|
||||
"MailingGeocodeAccuracy",
|
||||
"MailingAddress",
|
||||
"Phone",
|
||||
"Fax",
|
||||
"MobilePhone",
|
||||
"HomePhone",
|
||||
"OtherPhone",
|
||||
"AssistantPhone",
|
||||
"ReportsToId",
|
||||
"Email",
|
||||
"Title",
|
||||
"Department",
|
||||
"AssistantName",
|
||||
"Birthdate",
|
||||
"Description",
|
||||
"OwnerId",
|
||||
"HasOptedOutOfEmail",
|
||||
"HasOptedOutOfFax",
|
||||
"DoNotCall",
|
||||
"CreatedDate",
|
||||
"CreatedById",
|
||||
"LastModifiedDate",
|
||||
"LastModifiedById",
|
||||
"SystemModstamp",
|
||||
"LastActivityDate",
|
||||
"LastCURequestDate",
|
||||
"LastCUUpdateDate",
|
||||
"MayEdit",
|
||||
"IsLocked",
|
||||
"LastViewedDate",
|
||||
"LastReferencedDate",
|
||||
"EmailBouncedReason",
|
||||
"EmailBouncedDate",
|
||||
"IsEmailBounced",
|
||||
"PhotoUrl",
|
||||
"Jigsaw",
|
||||
"JigsawContactId",
|
||||
"IndividualId",
|
||||
"Mobile_ID_vod__c",
|
||||
"H1Insights__H1_NPI_Value_for_Testing__c",
|
||||
"H1Insights__H1_Person_ID__c",
|
||||
"H1Insights__H1_Request_Status__c",
|
||||
"H1Insights__H1_URL__c",
|
||||
"H1Insights__NPI_Number__c",
|
||||
"H1Insights__NPI_Number_for_H1_Insights__c",
|
||||
"MSJ_Marketing_Cloud_Integration__c"
|
||||
],
|
||||
"is_skip": False,
|
||||
"is_update_last_fetch_datetime": True
|
||||
},
|
||||
{
|
||||
"object_name": "Territory2",
|
||||
"columns": [
|
||||
"Id",
|
||||
"Name",
|
||||
"Territory2TypeId",
|
||||
"Territory2ModelId",
|
||||
"ParentTerritory2Id",
|
||||
"Description",
|
||||
"ForecastUserId",
|
||||
"AccountAccessLevel",
|
||||
"OpportunityAccessLevel",
|
||||
"CaseAccessLevel",
|
||||
"ContactAccessLevel",
|
||||
"LastModifiedDate",
|
||||
"LastModifiedById",
|
||||
"SystemModstamp",
|
||||
"DeveloperName",
|
||||
"MSJ_Territory_Type__c",
|
||||
"MSJ_Level__c"
|
||||
],
|
||||
"is_skip": False,
|
||||
"is_update_last_fetch_datetime": True
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
# Act
|
||||
with pytest.raises(Exception) as e:
|
||||
FetchTargetObjects(fetch_objects_dict)
|
||||
|
||||
# Expects
|
||||
assert str(e.value) == '「objects」キーは必須です'
|
||||
|
||||
def test_raise_constructor_no_type(self) -> None:
|
||||
"""
|
||||
Cases:
|
||||
インスタンス生成テスト
|
||||
辞書型のデータの対象のキーの値の型が想定と違う場合、例外が発生すること
|
||||
Arranges:
|
||||
- オブジェクト情報文字列を準備する
|
||||
Expects:
|
||||
- 例外が発生し期待値と一致する
|
||||
"""
|
||||
|
||||
# Arranges
|
||||
fetch_objects_dict = {
|
||||
"objects": "test_value"
|
||||
}
|
||||
|
||||
# Act
|
||||
with pytest.raises(Exception) as e:
|
||||
FetchTargetObjects(fetch_objects_dict)
|
||||
|
||||
# Expects
|
||||
assert str(e.value) == '「objects」キーの値は「<class \'list\'>」でなければなりません'
|
||||
|
||||
def test_constructor_iterator(self) -> None:
|
||||
"""
|
||||
Cases:
|
||||
インスタンス生成テスト
|
||||
登録されたオブジェクトリストをすべて取り出せること
|
||||
Arranges:
|
||||
- オブジェクト情報文字列を準備する
|
||||
Expects:
|
||||
- ループが最後まで回ること
|
||||
"""
|
||||
|
||||
fetch_objects_dict = {
|
||||
"objects": [
|
||||
{
|
||||
"object_name": "AccountShare",
|
||||
"columns": [
|
||||
"Id",
|
||||
"AccountId",
|
||||
"UserOrGroupId",
|
||||
"AccountAccessLevel",
|
||||
"OpportunityAccessLevel",
|
||||
"CaseAccessLevel",
|
||||
"ContactAccessLevel",
|
||||
"RowCause",
|
||||
"LastModifiedDate",
|
||||
"LastModifiedById",
|
||||
"IsDeleted"
|
||||
],
|
||||
"is_skip": False,
|
||||
"is_update_last_fetch_datetime": False,
|
||||
"datetime_column": "LastModifiedDate"
|
||||
},
|
||||
{
|
||||
"object_name": "Contact",
|
||||
"columns": [
|
||||
"Id",
|
||||
"IsDeleted",
|
||||
"MasterRecordId",
|
||||
"AccountId",
|
||||
"IsPersonAccount",
|
||||
"LastName",
|
||||
"FirstName",
|
||||
"Salutation",
|
||||
"Name",
|
||||
"OtherStreet",
|
||||
"OtherCity",
|
||||
"OtherState",
|
||||
"OtherPostalCode",
|
||||
"OtherCountry",
|
||||
"OtherLatitude",
|
||||
"OtherLongitude",
|
||||
"OtherGeocodeAccuracy",
|
||||
"OtherAddress",
|
||||
"MailingStreet",
|
||||
"MailingCity",
|
||||
"MailingState",
|
||||
"MailingPostalCode",
|
||||
"MailingCountry",
|
||||
"MailingLatitude",
|
||||
"MailingLongitude",
|
||||
"MailingGeocodeAccuracy",
|
||||
"MailingAddress",
|
||||
"Phone",
|
||||
"Fax",
|
||||
"MobilePhone",
|
||||
"HomePhone",
|
||||
"OtherPhone",
|
||||
"AssistantPhone",
|
||||
"ReportsToId",
|
||||
"Email",
|
||||
"Title",
|
||||
"Department",
|
||||
"AssistantName",
|
||||
"Birthdate",
|
||||
"Description",
|
||||
"OwnerId",
|
||||
"HasOptedOutOfEmail",
|
||||
"HasOptedOutOfFax",
|
||||
"DoNotCall",
|
||||
"CreatedDate",
|
||||
"CreatedById",
|
||||
"LastModifiedDate",
|
||||
"LastModifiedById",
|
||||
"SystemModstamp",
|
||||
"LastActivityDate",
|
||||
"LastCURequestDate",
|
||||
"LastCUUpdateDate",
|
||||
"MayEdit",
|
||||
"IsLocked",
|
||||
"LastViewedDate",
|
||||
"LastReferencedDate",
|
||||
"EmailBouncedReason",
|
||||
"EmailBouncedDate",
|
||||
"IsEmailBounced",
|
||||
"PhotoUrl",
|
||||
"Jigsaw",
|
||||
"JigsawContactId",
|
||||
"IndividualId",
|
||||
"Mobile_ID_vod__c",
|
||||
"H1Insights__H1_NPI_Value_for_Testing__c",
|
||||
"H1Insights__H1_Person_ID__c",
|
||||
"H1Insights__H1_Request_Status__c",
|
||||
"H1Insights__H1_URL__c",
|
||||
"H1Insights__NPI_Number__c",
|
||||
"H1Insights__NPI_Number_for_H1_Insights__c",
|
||||
"MSJ_Marketing_Cloud_Integration__c"
|
||||
],
|
||||
"is_skip": False,
|
||||
"is_update_last_fetch_datetime": True
|
||||
},
|
||||
{
|
||||
"object_name": "Territory2",
|
||||
"columns": [
|
||||
"Id",
|
||||
"Name",
|
||||
"Territory2TypeId",
|
||||
"Territory2ModelId",
|
||||
"ParentTerritory2Id",
|
||||
"Description",
|
||||
"ForecastUserId",
|
||||
"AccountAccessLevel",
|
||||
"OpportunityAccessLevel",
|
||||
"CaseAccessLevel",
|
||||
"ContactAccessLevel",
|
||||
"LastModifiedDate",
|
||||
"LastModifiedById",
|
||||
"SystemModstamp",
|
||||
"DeveloperName",
|
||||
"MSJ_Territory_Type__c",
|
||||
"MSJ_Level__c"
|
||||
],
|
||||
"is_skip": False,
|
||||
"is_update_last_fetch_datetime": True
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
# Act
|
||||
sut = FetchTargetObjects(fetch_objects_dict)
|
||||
for i, item in enumerate(sut, 1):
|
||||
assert item is not None
|
||||
|
||||
# Expects
|
||||
assert i == 3
|
||||
@ -0,0 +1,380 @@
|
||||
import pytest
|
||||
from src.config.objects import LastFetchDatetime
|
||||
from src.util.execute_datetime import ExecuteDateTime
|
||||
|
||||
|
||||
class TestLastFetchDatetime():
|
||||
def test_constructor(self) -> None:
|
||||
"""
|
||||
Cases:
|
||||
インスタンス生成テスト
|
||||
辞書型のデータに対して、バリデーションチェックを行いチェックが通ることを確認する
|
||||
Arranges:
|
||||
- 辞書型の前回取得日時データを準備する
|
||||
- 実行日時インスタンスを生成する
|
||||
Expects:
|
||||
- 例外が発生しないこと
|
||||
"""
|
||||
|
||||
# Arranges
|
||||
last_fetch_datetime_dict = {
|
||||
"last_fetch_datetime_from": "1900-01-01T00:00:00.000Z",
|
||||
"last_fetch_datetime_to": "2022-01-01T00:00:00.000Z"
|
||||
}
|
||||
|
||||
execute_datetime = ExecuteDateTime()
|
||||
|
||||
# Act
|
||||
LastFetchDatetime(last_fetch_datetime_dict, execute_datetime)
|
||||
|
||||
# Expects
|
||||
pass
|
||||
|
||||
def test_raise_constructor_last_fetch_datetime_from_no_key(self) -> None:
|
||||
"""
|
||||
Cases:
|
||||
インスタンス生成テスト
|
||||
辞書型のデータに対して、必要なキー(last_fetch_datetime_from)がない場合、例外が発生すること
|
||||
Arranges:
|
||||
- 辞書型の前回取得日時データを準備する
|
||||
- 実行日時インスタンスを生成する
|
||||
Expects:
|
||||
- 例外が発生し期待値と一致する
|
||||
"""
|
||||
|
||||
# Arranges
|
||||
last_fetch_datetime_dict = {
|
||||
"last_fetch_datetime_to": "2022-01-01T00:00:00.000Z"
|
||||
}
|
||||
|
||||
execute_datetime = ExecuteDateTime()
|
||||
|
||||
# Act
|
||||
with pytest.raises(Exception) as e:
|
||||
LastFetchDatetime(last_fetch_datetime_dict, execute_datetime)
|
||||
|
||||
# Expects
|
||||
assert str(e.value) == '「last_fetch_datetime_from」キーは必須です'
|
||||
|
||||
def test_raise_constructor_last_fetch_datetime_from_no_value(self) -> None:
|
||||
"""
|
||||
Cases:
|
||||
インスタンス生成テスト
|
||||
辞書型のデータの対象のキー(last_fetch_datetime_from)の値が空文字の場合、例外が発生すること
|
||||
Arranges:
|
||||
- 辞書型の前回取得日時データを準備する
|
||||
- 実行日時インスタンスを生成する
|
||||
Expects:
|
||||
- 例外が発生し期待値と一致する
|
||||
"""
|
||||
|
||||
# Arranges
|
||||
last_fetch_datetime_dict = {
|
||||
"last_fetch_datetime_from": "",
|
||||
"last_fetch_datetime_to": "2022-01-01T00:00:00.000Z"
|
||||
}
|
||||
|
||||
execute_datetime = ExecuteDateTime()
|
||||
|
||||
# Act
|
||||
with pytest.raises(Exception) as e:
|
||||
LastFetchDatetime(last_fetch_datetime_dict, execute_datetime)
|
||||
|
||||
# Expects
|
||||
assert str(e.value) == '「last_fetch_datetime_from」キーは必須です'
|
||||
|
||||
def test_raise_constructor_last_fetch_datetime_from_none_value(self) -> None:
|
||||
"""
|
||||
Cases:
|
||||
インスタンス生成テスト
|
||||
辞書型のデータの対象のキー(last_fetch_datetime_from)の値がNoneの場合、例外が発生すること
|
||||
Arranges:
|
||||
- 辞書型の前回取得日時データを準備する
|
||||
- 実行日時インスタンスを生成する
|
||||
Expects:
|
||||
- 例外が発生し期待値と一致する
|
||||
"""
|
||||
|
||||
# Arranges
|
||||
last_fetch_datetime_dict = {
|
||||
"last_fetch_datetime_from": None,
|
||||
"last_fetch_datetime_to": "2022-01-01T00:00:00.000Z"
|
||||
}
|
||||
|
||||
execute_datetime = ExecuteDateTime()
|
||||
|
||||
# Act
|
||||
with pytest.raises(Exception) as e:
|
||||
LastFetchDatetime(last_fetch_datetime_dict, execute_datetime)
|
||||
|
||||
# Expects
|
||||
assert str(e.value) == '「last_fetch_datetime_from」キーは必須です'
|
||||
|
||||
def test_raise_constructor_last_fetch_datetime_from_other_type(self) -> None:
|
||||
"""
|
||||
Cases:
|
||||
インスタンス生成テスト
|
||||
辞書型のデータの対象のキー(last_fetch_datetime_from)の値の型が想定と違う場合、例外が発生すること
|
||||
Arranges:
|
||||
- 辞書型の前回取得日時データを準備する
|
||||
- 実行日時インスタンスを生成する
|
||||
Expects:
|
||||
- 例外が発生し期待値と一致する
|
||||
"""
|
||||
|
||||
# Arranges
|
||||
last_fetch_datetime_dict = {
|
||||
"last_fetch_datetime_from": 1,
|
||||
"last_fetch_datetime_to": "2022-01-01T00:00:00.000Z"
|
||||
}
|
||||
|
||||
execute_datetime = ExecuteDateTime()
|
||||
|
||||
# Act
|
||||
with pytest.raises(Exception) as e:
|
||||
LastFetchDatetime(last_fetch_datetime_dict, execute_datetime)
|
||||
|
||||
# Expects
|
||||
assert str(e.value) == '「last_fetch_datetime_from」キーの値は「<class \'str\'>」でなければなりません'
|
||||
|
||||
def test_raise_constructor_last_fetch_datetime_from_other_string(self) -> None:
|
||||
"""
|
||||
Cases:
|
||||
インスタンス生成テスト
|
||||
辞書型のデータの対象のキー(last_fetch_datetime_from)の値が正規表現と違う場合、例外が発生すること
|
||||
Arranges:
|
||||
- 辞書型のオブジェクト情報を準備する
|
||||
- 実行日時インスタンスを生成する
|
||||
Expects:
|
||||
- 例外が発生し期待値と一致する
|
||||
"""
|
||||
|
||||
# Arranges
|
||||
last_fetch_datetime_dict = {
|
||||
"last_fetch_datetime_from": "aaa",
|
||||
"last_fetch_datetime_to": "2022-01-01T00:00:00.000Z"
|
||||
}
|
||||
|
||||
execute_datetime = ExecuteDateTime()
|
||||
|
||||
# Act
|
||||
with pytest.raises(Exception) as e:
|
||||
LastFetchDatetime(last_fetch_datetime_dict, execute_datetime)
|
||||
|
||||
# Expects
|
||||
assert str(
|
||||
e.value) == '「last_fetch_datetime_from」キーの値の正規表現チェックに失敗しました 「YYYY-MM-DDTHH:MM:SS.000Z」形式である必要があります'
|
||||
|
||||
def test_raise_constructor_last_fetch_datetime_to_no_key(self) -> None:
|
||||
"""
|
||||
Cases:
|
||||
インスタンス生成テスト
|
||||
辞書型のデータに対して、キー(last_fetch_datetime_to)がない場合、例外が発生しないこと
|
||||
Arranges:
|
||||
- 辞書型の前回取得日時データを準備する
|
||||
- 実行日時インスタンスを生成する
|
||||
Expects:
|
||||
- 例外が発生しないこと
|
||||
"""
|
||||
|
||||
# Arranges
|
||||
last_fetch_datetime_dict = {
|
||||
"last_fetch_datetime_from": "1900-01-01T00:00:00.000Z"
|
||||
}
|
||||
|
||||
execute_datetime = ExecuteDateTime()
|
||||
|
||||
# Act
|
||||
LastFetchDatetime(last_fetch_datetime_dict, execute_datetime)
|
||||
|
||||
# Expects
|
||||
pass
|
||||
|
||||
def test_constructor_last_fetch_datetime_to_no_value(self) -> None:
|
||||
"""
|
||||
Cases:
|
||||
辞書型のデータの対象のキー(last_fetch_datetime_to)の値の型が空文字の場合、例外が発生しないこと
|
||||
Arranges:
|
||||
- 辞書型の前回取得日時データを準備する
|
||||
- 実行日時インスタンスを生成する
|
||||
Expects:
|
||||
- 例外が発生しないこと
|
||||
"""
|
||||
|
||||
# Arranges
|
||||
last_fetch_datetime_dict = {
|
||||
"last_fetch_datetime_from": "1900-01-01T00:00:00.000Z",
|
||||
"last_fetch_datetime_to": ""
|
||||
}
|
||||
|
||||
execute_datetime = ExecuteDateTime()
|
||||
|
||||
# Act
|
||||
LastFetchDatetime(last_fetch_datetime_dict, execute_datetime)
|
||||
|
||||
# Expects
|
||||
None
|
||||
|
||||
def test_constructor_last_fetch_datetime_to_none__value(self) -> None:
|
||||
"""
|
||||
Cases:
|
||||
辞書型のデータの対象のキー(last_fetch_datetime_to)の値の型がNoneの場合、例外が発生しないこと
|
||||
Arranges:
|
||||
- 辞書型の前回取得日時データを準備する
|
||||
- 実行日時インスタンスを生成する
|
||||
Expects:
|
||||
- 例外が発生しないこと
|
||||
"""
|
||||
|
||||
# Arranges
|
||||
last_fetch_datetime_dict = {
|
||||
"last_fetch_datetime_from": "1900-01-01T00:00:00.000Z",
|
||||
"last_fetch_datetime_to": None
|
||||
}
|
||||
|
||||
execute_datetime = ExecuteDateTime()
|
||||
|
||||
# Act
|
||||
LastFetchDatetime(last_fetch_datetime_dict, execute_datetime)
|
||||
|
||||
# Expects
|
||||
pass
|
||||
|
||||
def test_raise_constructor_last_fetch_datetime_to_other_type(self) -> None:
|
||||
"""
|
||||
Cases:
|
||||
インスタンス生成テスト
|
||||
辞書型のデータの対象のキー(last_fetch_datetime_to)の値の型が想定と違う場合、例外が発生すること
|
||||
Arranges:
|
||||
- 辞書型の前回取得日時データを準備する
|
||||
- 実行日時インスタンスを生成する
|
||||
Expects:
|
||||
- 例外が発生し期待値と一致する
|
||||
"""
|
||||
|
||||
# Arranges
|
||||
last_fetch_datetime_dict = {
|
||||
"last_fetch_datetime_from": "1900-01-01T00:00:00.000Z",
|
||||
"last_fetch_datetime_to": 1
|
||||
}
|
||||
|
||||
execute_datetime = ExecuteDateTime()
|
||||
|
||||
# Act
|
||||
with pytest.raises(Exception) as e:
|
||||
LastFetchDatetime(last_fetch_datetime_dict, execute_datetime)
|
||||
|
||||
# Expects
|
||||
assert str(e.value) == '「last_fetch_datetime_to」キーの値は「<class \'str\'>」でなければなりません'
|
||||
|
||||
def test_raise_constructor_last_fetch_datetime_to_other_string(self) -> None:
|
||||
"""
|
||||
Cases:
|
||||
インスタンス生成テスト
|
||||
辞書型のデータの対象のキー(last_fetch_datetime_to)の値が正規表現と違う場合、例外が発生すること
|
||||
Arranges:
|
||||
- 辞書型の前回取得日時データを準備する
|
||||
- 実行日時インスタンスを生成する
|
||||
Expects:
|
||||
- 例外が発生し期待値と一致する
|
||||
"""
|
||||
|
||||
# Arranges
|
||||
last_fetch_datetime_dict = {
|
||||
"last_fetch_datetime_from": "1900-01-01T00:00:00.000Z",
|
||||
"last_fetch_datetime_to": "aaa"
|
||||
}
|
||||
|
||||
execute_datetime = ExecuteDateTime()
|
||||
|
||||
# Act
|
||||
with pytest.raises(Exception) as e:
|
||||
LastFetchDatetime(last_fetch_datetime_dict, execute_datetime)
|
||||
|
||||
# Expects
|
||||
assert str(
|
||||
e.value) == '「last_fetch_datetime_to」キーの値の正規表現チェックに失敗しました 「YYYY-MM-DDTHH:MM:SS.000Z」形式である必要があります'
|
||||
|
||||
def test_last_fetch_datetime_from(self) -> str:
|
||||
"""
|
||||
Cases:
|
||||
オブジェクト情報から対象の値を返すこと
|
||||
Arranges:
|
||||
- 辞書型の前回取得日時データを準備する
|
||||
- 実行日時インスタンスを生成する
|
||||
- 前回取得日時インスタンスを生成する
|
||||
Expects:
|
||||
- 戻り値が期待値と一致する
|
||||
"""
|
||||
|
||||
# Arranges
|
||||
last_fetch_datetime_dict = {
|
||||
"last_fetch_datetime_from": "1900-01-01T00:00:00.000Z",
|
||||
"last_fetch_datetime_to": "2022-01-01T00:00:00.000Z"
|
||||
}
|
||||
|
||||
execute_datetime = ExecuteDateTime()
|
||||
|
||||
sut = LastFetchDatetime(last_fetch_datetime_dict, execute_datetime)
|
||||
|
||||
# Act
|
||||
actual = sut.last_fetch_datetime_from
|
||||
|
||||
# Expects
|
||||
assert actual == '1900-01-01T00:00:00.000Z'
|
||||
|
||||
def test_last_fetch_datetime_to(self) -> str:
|
||||
"""
|
||||
Cases:
|
||||
オブジェクト情報から対象の値を返すこと
|
||||
Arranges:
|
||||
- 辞書型の前回取得日時データを準備する
|
||||
- 実行日時インスタンスを生成する
|
||||
- 前回取得日時インスタンスを生成する
|
||||
Expects:
|
||||
- 戻り値が期待値と一致する
|
||||
"""
|
||||
|
||||
# Arranges
|
||||
last_fetch_datetime_dict = {
|
||||
"last_fetch_datetime_from": "1900-01-01T00:00:00.000Z",
|
||||
"last_fetch_datetime_to": "2022-01-01T00:00:00.000Z"
|
||||
}
|
||||
|
||||
execute_datetime = ExecuteDateTime()
|
||||
|
||||
sut = LastFetchDatetime(last_fetch_datetime_dict, execute_datetime)
|
||||
|
||||
# Act
|
||||
actual = sut.last_fetch_datetime_to
|
||||
|
||||
# Expects
|
||||
assert actual == '2022-01-01T00:00:00.000Z'
|
||||
|
||||
def test_last_fetch_datetime_to_default(self) -> str:
|
||||
"""
|
||||
Cases:
|
||||
オブジェクト情報から対象の値を返すこと
|
||||
Arranges:
|
||||
- 辞書型の前回取得日時データを準備する
|
||||
- 実行日時インスタンスを生成する
|
||||
- 前回取得日時インスタンスを生成する
|
||||
Expects:
|
||||
- 戻り値が期待値と一致する
|
||||
"""
|
||||
|
||||
# Arranges
|
||||
last_fetch_datetime_dict = {
|
||||
"last_fetch_datetime_from": "1900-01-01T00:00:00.000Z",
|
||||
"last_fetch_datetime_to": ""
|
||||
}
|
||||
|
||||
execute_datetime = ExecuteDateTime()
|
||||
|
||||
sut = LastFetchDatetime(last_fetch_datetime_dict, execute_datetime)
|
||||
|
||||
# Act
|
||||
actual = sut.last_fetch_datetime_to
|
||||
|
||||
# Expects
|
||||
assert actual == str(execute_datetime)
|
||||
1802
ecs/crm-datafetch/tests/config/test_objects_target_object.py
Normal file
1802
ecs/crm-datafetch/tests/config/test_objects_target_object.py
Normal file
File diff suppressed because it is too large
Load Diff
77
ecs/crm-datafetch/tests/parser/test_json_parser.py
Normal file
77
ecs/crm-datafetch/tests/parser/test_json_parser.py
Normal file
@ -0,0 +1,77 @@
|
||||
import pytest
|
||||
from src.parser.json_parser import JsonParser
|
||||
|
||||
|
||||
class TestJsonParser():
|
||||
|
||||
def test_parse(self) -> dict:
|
||||
"""
|
||||
Cases:
|
||||
- コメントアウトが記載されているJSONからコメントを取り除き、辞書型を返すこと
|
||||
Arranges:
|
||||
- JSON文字列を準備する
|
||||
Expects:
|
||||
- json.loadsされたファイルの内容が期待値と一致する
|
||||
"""
|
||||
|
||||
# Arranges
|
||||
json_string = """{
|
||||
"aaaa": "aaaa",
|
||||
# これはコメントです
|
||||
"#これはコメントではありません": "#これはコメントではありません",
|
||||
"bbb": false,
|
||||
"hogehoge": [
|
||||
"ccc",
|
||||
/これはコメントです
|
||||
"/これはコメントではありません"
|
||||
]
|
||||
}"""
|
||||
|
||||
# Act
|
||||
sut = JsonParser(json_string)
|
||||
actual = sut.parse()
|
||||
|
||||
# Expects
|
||||
expected_value = {
|
||||
"aaaa": "aaaa",
|
||||
"#これはコメントではありません": "#これはコメントではありません",
|
||||
"bbb": False,
|
||||
"hogehoge": [
|
||||
"ccc",
|
||||
"/これはコメントではありません"
|
||||
]
|
||||
}
|
||||
|
||||
assert actual == expected_value
|
||||
|
||||
def test_raise_parse(self) -> dict:
|
||||
"""
|
||||
Cases:
|
||||
- コメントアウト記号ではない文字をコメントアウトとしたときに、例外が発生すること
|
||||
Arranges:
|
||||
- JSON文字列を準備する
|
||||
Expects:
|
||||
- 例外が発生し期待値と一致する
|
||||
"""
|
||||
|
||||
# Arranges
|
||||
json_string = """{
|
||||
"aaaa": "aaaa",
|
||||
$ これはコメントです
|
||||
"#これはコメントではありません": "#これはコメントではありません",
|
||||
"bbb": false,
|
||||
"hogehoge": [
|
||||
"ccc",
|
||||
/これはコメントです
|
||||
"/これはコメントではありません"
|
||||
]
|
||||
}"""
|
||||
|
||||
# Act
|
||||
with pytest.raises(Exception) as e:
|
||||
|
||||
sut = JsonParser(json_string)
|
||||
sut.parse()
|
||||
|
||||
# Expects
|
||||
assert "Expecting property name enclosed in double quotes:" in str(e.value)
|
||||
905
ecs/crm-datafetch/tests/test_controller.py
Normal file
905
ecs/crm-datafetch/tests/test_controller.py
Normal file
@ -0,0 +1,905 @@
|
||||
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:
|
||||
- データ取得準備処理で返される取得対象オブジェクト情報のうち、2つ目を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データ取得処理で返されるオブジェクトのうち、2つ目を空のリストにする
|
||||
- 各種プロセスメソッドと内部で使用している値オブジェクトをモック化する
|
||||
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:
|
||||
- パラメータ1:データ取得準備処理でシステム例外が発生するようにする
|
||||
- パラメータ2:データ取得準備処理で想定外の例外が発生するようにする
|
||||
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:
|
||||
- パラメータ1:オブジェクト情報形式チェック処理でシステム例外が発生するようにする
|
||||
- パラメータ2:オブジェクト情報形式チェック処理で想定外の例外が発生するようにする
|
||||
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:
|
||||
- パラメータ1:データ取得期間設定処理でシステム例外が発生するようにする
|
||||
- パラメータ2:データ取得期間設定処理で想定外の例外が発生するようにする
|
||||
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:
|
||||
- パラメータ1:CRMデータ取得処理でシステム例外が発生するようにする
|
||||
- パラメータ2: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:
|
||||
- パラメータ1:CRM電文データバックアップ処理でシステム例外が発生するようにする
|
||||
- パラメータ2: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:
|
||||
- パラメータ1:CSV変換処理でシステム例外が発生するようにする
|
||||
- パラメータ2: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:
|
||||
- パラメータ1:CSVバックアップ処理でシステム例外が発生するようにする
|
||||
- パラメータ2: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:
|
||||
- パラメータ1:CSVアップロード処理でシステム例外が発生するようにする
|
||||
- パラメータ2: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:
|
||||
- パラメータ1:前回取得日時ファイル更新処理でシステム例外が発生するようにする
|
||||
- パラメータ2:前回取得日時ファイル更新処理で想定外の例外が発生するようにする
|
||||
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:
|
||||
- パラメータ1:取得処理実施結果アップロード処理でシステム例外が発生するようにする
|
||||
- パラメータ2:取得処理実施結果アップロード処理で想定外の例外が発生するようにする
|
||||
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, '取得処理実施結果アップロード処理で発生した例外のログメッセージが出力されていること'
|
||||
204
ecs/crm-datafetch/tests/test_prepare_data_fetch_process.py
Normal file
204
ecs/crm-datafetch/tests/test_prepare_data_fetch_process.py
Normal file
@ -0,0 +1,204 @@
|
||||
import json
|
||||
from datetime import datetime
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
from src.config.objects import FetchTargetObjects
|
||||
from src.error.exceptions import FileNotFoundException, InvalidConfigException
|
||||
from src.prepare_data_fetch_process import prepare_data_fetch_process
|
||||
from src.system_var.constants import PRE_JP_NAME, YYYYMMDDTHHMMSSTZ
|
||||
|
||||
from .test_utils.log_message import generate_log_message_tuple
|
||||
|
||||
|
||||
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
|
||||
|
||||
def test_call_depended_modules(self):
|
||||
"""
|
||||
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
|
||||
|
||||
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] エラー内容:[形式チェックエラー]'
|
||||
7
ecs/crm-datafetch/tests/test_utils/log_message.py
Normal file
7
ecs/crm-datafetch/tests/test_utils/log_message.py
Normal file
@ -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)
|
||||
213
ecs/crm-datafetch/tests/util/test_counter_object.py
Normal file
213
ecs/crm-datafetch/tests/util/test_counter_object.py
Normal file
@ -0,0 +1,213 @@
|
||||
import pytest
|
||||
from src.util.counter_object import CounterObject
|
||||
|
||||
|
||||
class TestCounterObject:
|
||||
|
||||
def test_constructor(self) -> int:
|
||||
"""
|
||||
Cases:
|
||||
カウンターオブジェクト生成時に、数値を渡すと例外が発生しないこと
|
||||
Arranges:
|
||||
なし
|
||||
Expects:
|
||||
例外が発生しないこと
|
||||
"""
|
||||
# Act
|
||||
CounterObject(1)
|
||||
|
||||
# Expects
|
||||
pass
|
||||
|
||||
def test_constructor_string_number(self) -> int:
|
||||
"""
|
||||
Cases:
|
||||
カウンターオブジェクト生成時に、文字列型の数値を渡すと例外が発生しないこと
|
||||
Arranges:
|
||||
なし
|
||||
Expects:
|
||||
例外が発生しないこと
|
||||
"""
|
||||
# Act
|
||||
CounterObject("1")
|
||||
|
||||
# Expects
|
||||
pass
|
||||
|
||||
def test_raise_constructor_string(self) -> int:
|
||||
"""
|
||||
Cases:
|
||||
カウンターオブジェクト生成時に、文字列を渡すと例外が発生すること
|
||||
Arranges:
|
||||
なし
|
||||
Expects:
|
||||
発生した例外が期待値と一致すること
|
||||
"""
|
||||
# Act
|
||||
with pytest.raises(Exception) as e:
|
||||
CounterObject("test1")
|
||||
|
||||
# Expects
|
||||
assert "invalid literal for int() with base 10:" in str(e.value)
|
||||
|
||||
def test_describe(self) -> int:
|
||||
"""
|
||||
Cases:
|
||||
カウンターオブジェクトにて保持した値を返すこと(インスタンス生成時引数なし)
|
||||
Arranges:
|
||||
なし
|
||||
Expects:
|
||||
問い合わせた値が期待値と一致する
|
||||
"""
|
||||
|
||||
# Act
|
||||
sut = CounterObject()
|
||||
actual = sut.describe()
|
||||
|
||||
# Expects
|
||||
assert actual == 1
|
||||
|
||||
def test_describe_argument(self) -> int:
|
||||
"""
|
||||
Cases:
|
||||
カウンターオブジェクトにて保持した値を返すこと(インスタンス生成時引数あり)
|
||||
Arranges:
|
||||
なし
|
||||
Expects:
|
||||
問い合わせた値が期待値と一致する
|
||||
"""
|
||||
|
||||
# Act
|
||||
sut = CounterObject(3)
|
||||
actual = sut.describe()
|
||||
|
||||
# Expects
|
||||
assert actual == 3
|
||||
|
||||
def test_raise_describe(self) -> int:
|
||||
"""
|
||||
Cases:
|
||||
カウンターオブジェクトの保持した値を問い合わせる際、引数を渡すと例外が発生すること
|
||||
Arranges:
|
||||
なし
|
||||
Expects:
|
||||
問い合わせた値が期待値と一致する
|
||||
"""
|
||||
|
||||
# Act
|
||||
with pytest.raises(Exception) as e:
|
||||
sut = CounterObject()
|
||||
sut.describe(1)
|
||||
|
||||
# Expects
|
||||
assert str(e.value) == 'describe() takes 1 positional argument but 2 were given'
|
||||
|
||||
def test_increment(self) -> int:
|
||||
"""
|
||||
Cases:
|
||||
カウンターオブジェクトにて保持した値がインクリメントされていること(引数なし)
|
||||
Arranges:
|
||||
なし
|
||||
Expects:
|
||||
戻り値が期待値と一致する
|
||||
"""
|
||||
|
||||
# Act
|
||||
sut = CounterObject()
|
||||
sut.increment()
|
||||
actual = sut.increment()
|
||||
|
||||
# Expects
|
||||
assert actual == 3
|
||||
|
||||
def test_increment_argument(self) -> int:
|
||||
"""
|
||||
Cases:
|
||||
カウンターオブジェクトにて保持した値がインクリメントされていること(引数あり)
|
||||
Arranges:
|
||||
なし
|
||||
Expects:
|
||||
戻り値が期待値と一致する
|
||||
"""
|
||||
|
||||
# Act
|
||||
sut = CounterObject(5)
|
||||
sut.increment(2)
|
||||
actual = sut.increment(2)
|
||||
|
||||
# Expects
|
||||
assert actual == 9
|
||||
|
||||
def test_raise_increment(self) -> int:
|
||||
"""
|
||||
Cases:
|
||||
文字列を引数で渡すことで、例外が発生すること
|
||||
Arranges:
|
||||
なし
|
||||
Expects:
|
||||
発生した例外が期待値と一致する
|
||||
"""
|
||||
|
||||
# Act
|
||||
with pytest.raises(Exception) as e:
|
||||
sut = CounterObject(5)
|
||||
sut.increment('aaa')
|
||||
sut.increment('aaa')
|
||||
|
||||
# Expects
|
||||
assert str(e.value) == "unsupported operand type(s) for +=: 'int' and 'str'"
|
||||
|
||||
def test_decrement(self) -> int:
|
||||
"""
|
||||
Cases:
|
||||
カウンターオブジェクトにて保持した値がデクリメントされていること(引数なし)
|
||||
Arranges:
|
||||
なし
|
||||
Expects:
|
||||
戻り値が期待値と一致する
|
||||
"""
|
||||
|
||||
# Act
|
||||
sut = CounterObject()
|
||||
sut.decrement()
|
||||
actual = sut.decrement()
|
||||
|
||||
# Expects
|
||||
assert actual == -1
|
||||
|
||||
def test_decrement_argument(self) -> int:
|
||||
"""
|
||||
Cases:
|
||||
カウンターオブジェクトにて保持した値がデクリメントされていること(引数あり)
|
||||
Arranges:
|
||||
なし
|
||||
Expects:
|
||||
戻り値が期待値と一致する
|
||||
"""
|
||||
|
||||
# Act
|
||||
sut = CounterObject(5)
|
||||
sut.decrement(2)
|
||||
actual = sut.decrement(2)
|
||||
|
||||
# Expects
|
||||
assert actual == 1
|
||||
|
||||
def test_raise_decrement(self) -> int:
|
||||
"""
|
||||
Cases:
|
||||
文字列を引数で渡すことで、例外が発生すること
|
||||
Arranges:
|
||||
なし
|
||||
Expects:
|
||||
発生した例外が期待値と一致する
|
||||
"""
|
||||
|
||||
# Act
|
||||
with pytest.raises(Exception) as e:
|
||||
sut = CounterObject(5)
|
||||
sut.decrement('aaa')
|
||||
sut.decrement('aaa')
|
||||
|
||||
# Expects
|
||||
assert str(e.value) == "unsupported operand type(s) for -=: 'int' and 'str'"
|
||||
81
ecs/crm-datafetch/tests/util/test_execute_datetime.py
Normal file
81
ecs/crm-datafetch/tests/util/test_execute_datetime.py
Normal file
@ -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)
|
||||
Loading…
x
Reference in New Issue
Block a user