From e65a4d013854fb3ef4d4e3cd1927bc07e7a0a6c6 Mon Sep 17 00:00:00 2001 From: CuberHuber Date: Wed, 22 Jan 2025 17:04:36 +0300 Subject: [PATCH] fix(tests): added compliance tests (#38) - comparison config and payload class - stop after first failure Solved: #38 --- pytest.ini | 1 + readme.md | 15 ++++++++++ src/s3_platform_plugin_template/config.py | 6 ++-- tests/config/fixtures.py | 9 ++++-- tests/config/test_compliance_config.py | 36 +++++++++++++++++++++++ tests/fixtures/__init__.py | 0 tests/fixtures/payload_class.py | 11 +++++++ tests/payload/test_plugin_run.py | 22 +++++--------- 8 files changed, 80 insertions(+), 20 deletions(-) create mode 100644 tests/config/test_compliance_config.py create mode 100644 tests/fixtures/__init__.py create mode 100644 tests/fixtures/payload_class.py diff --git a/pytest.ini b/pytest.ini index 6c741c8..01e85f7 100644 --- a/pytest.ini +++ b/pytest.ini @@ -4,3 +4,4 @@ markers = payload_set: mark test a part of the main payload set (plugin run) timeout = 100 +addopts = -x \ No newline at end of file diff --git a/readme.md b/readme.md index 73a590f..caa333b 100644 --- a/readme.md +++ b/readme.md @@ -28,6 +28,8 @@ S3 Platform Plugin Template - это репозиторий предоставл - [Тесты](#тесты) - [Как запустить тесты](#запуск-тестов) - [Правила написания парсера](#правила-написания-парсеров) +- [Пример конфигурации](#примеры-конфигурации) + - [Конфигурация параметров запуска плагина](#пример-конфигурации-параметров-запуска-плагина) ## Быстрый старт @@ -274,3 +276,16 @@ class MyTemplateParser(S3PParserBase): ``` +## Примеры конфигурации + +### Пример конфигурации параметров запуска плагина +Ниже приведен пример конфигурации `payload.entry.params`. +```python +from s3p_sdk.plugin.config import payload +from s3p_sdk.module import WebDriver + +[ + payload.entry.ModuleParamConfig(key='web_driver', module_name=WebDriver, bus=True), # Передается модуль + payload.entry.ConstParamConfig(key='url', value='url to the source page'), # Передается константа +] +``` diff --git a/src/s3_platform_plugin_template/config.py b/src/s3_platform_plugin_template/config.py index 89a9b3b..e956904 100644 --- a/src/s3_platform_plugin_template/config.py +++ b/src/s3_platform_plugin_template/config.py @@ -49,10 +49,8 @@ entry=payload.entry.EntryConfig( method='content', params=[ - payload.entry.ModuleParamConfig(key='driver', module_name=WebDriver, bus=True), - payload.entry.ConstParamConfig(key='url', - value='url to the source page'), - ] + payload.entry.ModuleParamConfig(key='web_driver', module_name=WebDriver, bus=True), + ] # Подробнее можно почитать [тут](./readme.md#пример-конфигурации-параметров-запуска-плагина ) ) ) diff --git a/tests/config/fixtures.py b/tests/config/fixtures.py index 84d8a89..b7f1183 100644 --- a/tests/config/fixtures.py +++ b/tests/config/fixtures.py @@ -34,12 +34,12 @@ def __init__(self, dir: str): raise FileNotFoundError(f"File not found {Path(dir) / 'plugin.xml'}") -@pytest.fixture(scope="module") +@pytest.fixture(scope="session") def project_config() -> Project: return Project(str(Path(__file__).parent.parent.parent)) -@pytest.fixture(scope="module") +@pytest.fixture(scope="session") def fix_plugin_config(project_config) -> PluginConfig: """Загружает конфигурацию из config.py файла по динамическому пути на основании конфигурации""" config_path = Path(project_config.root) / 'src' / project_config.name / 'config.py' @@ -48,3 +48,8 @@ def fix_plugin_config(project_config) -> PluginConfig: module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) return module.config + + +@pytest.fixture(scope="session") +def fix_necessary_payload_entry_params() -> tuple[str, ...]: + return 'refer', 'plugin', 'restrictions', 'self' diff --git a/tests/config/test_compliance_config.py b/tests/config/test_compliance_config.py new file mode 100644 index 0000000..83b29f1 --- /dev/null +++ b/tests/config/test_compliance_config.py @@ -0,0 +1,36 @@ +import inspect + +import pytest + +from tests.fixtures.payload_class import fix_plugin_class +from tests.config.fixtures import fix_plugin_config, project_config, fix_necessary_payload_entry_params + + +@pytest.mark.pre_set +class TestPluginConfigCompliance: + + def test_payload_entry_params_equaled_payload_init_params(self, fix_plugin_config, fix_plugin_class, + fix_necessary_payload_entry_params): + """ + Тест проверяет соответствие начальных параметров в конфигурации и аргументов + """ + full_arg_spec = inspect.getfullargspec(fix_plugin_class.__init__) + entry_params = list(full_arg_spec.args) + + for necessary_param in fix_necessary_payload_entry_params: + assert necessary_param in entry_params + entry_params.remove(necessary_param) + + for param in fix_plugin_config.payload.entry.params: + assert param.key not in fix_necessary_payload_entry_params, f"Custom param should not overload necessary params" + assert param.key in full_arg_spec.args, f'Param `{param.key}` must be processed in the payload class constructor' + + assert set(full_arg_spec.args) == set([param.key for param in fix_plugin_config.payload.entry.params]).union(set(fix_necessary_payload_entry_params)) + + def test_payload_entry_param_key_unique(self, fix_plugin_config): + + param_keys = [] + for param in fix_plugin_config.payload.entry.params: + param_keys.append(param.key) + + assert len(param_keys) == len(set(param_keys)) \ No newline at end of file diff --git a/tests/fixtures/__init__.py b/tests/fixtures/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/fixtures/payload_class.py b/tests/fixtures/payload_class.py new file mode 100644 index 0000000..19331a5 --- /dev/null +++ b/tests/fixtures/payload_class.py @@ -0,0 +1,11 @@ +from typing import Type + +import pytest + +# TODO: Указать путь до класса плагина +from s3_platform_plugin_template.template_payload import MyTemplateParser as imported_payload_class + + +@pytest.fixture(scope="module") +def fix_plugin_class() -> Type[imported_payload_class]: + return imported_payload_class diff --git a/tests/payload/test_plugin_run.py b/tests/payload/test_plugin_run.py index 2c52cf9..05981b4 100644 --- a/tests/payload/test_plugin_run.py +++ b/tests/payload/test_plugin_run.py @@ -1,7 +1,7 @@ import datetime import importlib.util import os -from typing import Type +from typing import Callable, Union import pytest from pathlib import Path @@ -41,7 +41,7 @@ def fix_s3pPlugin(self) -> S3PPlugin: return S3PPlugin(1, 'unittests/repo/1', True, None, None, SOURCE, "3.0") @pytest.fixture(scope="module", autouse=True) - def fix_payload(self, project_config, fix_plugin_config) -> Type[S3PParserBase]: + def fix_payload(self, project_config, fix_plugin_config) -> S3PParserBase: MODULE_NAME: str = 's3p_test_plugin_payload' """Загружает конфигурацию из config.py файла по динамическому пути на основании конфигурации""" payload_path = Path(project_config.root) / 'src' / project_config.name / fix_plugin_config.payload.file @@ -58,19 +58,13 @@ def fix_payload(self, project_config, fix_plugin_config) -> Type[S3PParserBase]: assert issubclass(parser_class, S3PParserBase), f"{class_name} is not a subclass of S3PParserBase." return parser_class - def run_payload(self, payload: Type[S3PParserBase], _plugin: S3PPlugin, driver: WebDriver, refer: S3PRefer, max_document: int): + def run_payload(self, payload: Union[S3PParserBase, Callable], _plugin: S3PPlugin, driver: WebDriver, refer: S3PRefer, max_document: int): - # !WARNING Требуется изменить путь до актуального парсера плагина - from src.s3_platform_plugin_template.template_payload import MyTemplateParser - - if isinstance(payload, type(MyTemplateParser)): - _payload = payload( - refer=refer, - plugin=_plugin, - restrictions=S3PPluginRestrictions(max_document, None, None, None), web_driver=driver) - return _payload.content() - else: - assert False, "Тест проверяет payload плагина" + _payload = payload( + refer=refer, + plugin=_plugin, + restrictions=S3PPluginRestrictions(max_document, None, None, None), web_driver=driver) + return _payload.content() # !WARNING: Изменить максимальное время работы плагина из логических соображений @pytest.mark.timeout(20)