From 98771e060e8bd22b55d3fc890a7b3e3b751bc2ce Mon Sep 17 00:00:00 2001 From: Igor Radovanovic <74266147+IgorWounds@users.noreply.github.com> Date: Wed, 4 Oct 2023 15:20:46 +0200 Subject: [PATCH] Processing tests QA --- .../tests/test_integration_tests.py | 3 + .../utils/integration_tests_generator.py | 12 +-- .../tests/utils/integration_tests_testers.py | 90 ++++++++++++++----- 3 files changed, 79 insertions(+), 26 deletions(-) diff --git a/openbb_platform/extensions/tests/test_integration_tests.py b/openbb_platform/extensions/tests/test_integration_tests.py index e59987d111f..6878c705c1d 100644 --- a/openbb_platform/extensions/tests/test_integration_tests.py +++ b/openbb_platform/extensions/tests/test_integration_tests.py @@ -34,3 +34,6 @@ def test_api_interface_integration_tests() -> None: def test_api_interface_integration_test_params() -> None: """Test if there are any missing params for integration tests.""" run_test("integration", check_missing_integration_test_params) + + +test_python_interface_integration_test_params() diff --git a/openbb_platform/extensions/tests/utils/integration_tests_generator.py b/openbb_platform/extensions/tests/utils/integration_tests_generator.py index b3a53b4dd90..8605d0a539d 100644 --- a/openbb_platform/extensions/tests/utils/integration_tests_generator.py +++ b/openbb_platform/extensions/tests/utils/integration_tests_generator.py @@ -82,7 +82,7 @@ def get_model_params(param_fields: Dict[str, FieldInfo]) -> Dict[str, Any]: elif field.annotation == bool: test_params[field_name] = True elif get_origin(field.annotation) is Literal: - test_params[field_name] = field.annotation.__args__[0] + test_params[field_name] = field.annotation.__args__[0] # type: ignore return test_params @@ -116,12 +116,12 @@ def get_test_params( def get_test_params_data_processing(hints: Dict[str, Type]): + """Get the test params for the data processing commands.""" return list(hints.keys()) def get_full_command_name_and_test_name(route: str) -> Tuple[str, str]: """Get the full command name and test name.""" - cmd_parts = route.split("/") del cmd_parts[0] @@ -139,11 +139,13 @@ def get_full_command_name_and_test_name(route: str) -> Tuple[str, str]: def test_exists(command_name: str, path: str): + """Check if test exists.""" with open(path) as f: return command_name in f.read() def write_to_file_w_template(test_file, params_list, full_command, test_name): + """Write to file with template.""" params = "" for test_params in params_list: params += f"({test_params}),\n" @@ -166,7 +168,6 @@ def write_test( provider_interface_map: Dict[str, Any], ): """Write test.""" - for route, model in commands_model.items(): if extension_name in route and route.startswith(f"/{extension_name}/"): test_name, full_command = get_full_command_name_and_test_name(route=route) @@ -188,7 +189,6 @@ def write_test_data_processing( test_file: PosixPath, commands_map: Dict[str, str], extension_name: str ): """Write test for data processing commands.""" - for route, _ in commands_map.items(): if extension_name in route and route.startswith(f"/{extension_name}/"): test_name, full_command = get_full_command_name_and_test_name(route=route) @@ -208,7 +208,6 @@ def add_test_commands_to_file( # pylint: disable=W0102 extensions: List[PosixPath], ) -> None: """Add test commands to file.""" - provider_interface = ProviderInterface() provider_interface_map = provider_interface.map @@ -249,4 +248,5 @@ def write_integration_test() -> None: add_test_commands_to_file(extensions) -write_integration_test() +if __name__ == "__main__": + write_integration_test() diff --git a/openbb_platform/extensions/tests/utils/integration_tests_testers.py b/openbb_platform/extensions/tests/utils/integration_tests_testers.py index e8042546172..f0b820b53f5 100644 --- a/openbb_platform/extensions/tests/utils/integration_tests_testers.py +++ b/openbb_platform/extensions/tests/utils/integration_tests_testers.py @@ -2,9 +2,12 @@ import importlib.util import inspect import os -from typing import Any, Callable, Dict, List, Literal +from typing import Any, Callable, Dict, List, Literal, Union, get_type_hints -from extensions.tests.utils.integration_tests_generator import find_extensions +from extensions.tests.utils.integration_tests_generator import ( + find_extensions, + get_test_params_data_processing, +) from openbb_core.app.provider_interface import ProviderInterface from openbb_core.app.router import CommandMap @@ -46,11 +49,15 @@ def get_module_functions(module_list: List[Any]) -> Dict[str, Any]: def check_missing_providers( - command_params: Dict[str, Dict[str, dict]], + command_params: Union[Dict[str, Dict[str, dict]], List[Dict[str, str]]], function_params: List[dict], function, + processing: bool = False, ) -> List[str]: """Check if there are any missing providers for a command.""" + if processing or not isinstance(command_params, dict): + return [] + missing_providers: List[str] = [] providers = list(command_params.keys()) providers.remove("openbb") @@ -75,39 +82,62 @@ def check_missing_providers( def check_missing_params( - command_params: Dict[str, Dict[str, dict]], function_params: List[dict], function + command_params: Union[Dict[str, Dict[str, dict]], List[Dict[str, str]]], + function_params: List[dict], + function, + processing: bool = False, ) -> List[str]: """Check if there are any missing params for a command.""" missing_params = [] - for test_params in function_params: - if "provider" in test_params: - provider = test_params["provider"] - if provider in command_params: - for expected_param in command_params[provider]["QueryParams"]["fields"]: + if not processing: + for test_params in function_params: + if "provider" in test_params: + provider = test_params["provider"] + if provider in command_params: + for expected_param in command_params[provider]["QueryParams"][ + "fields" + ]: + if expected_param not in test_params.keys(): + missing_params.append( + f"Missing param {expected_param} for provider {provider} in function {function}" + ) + elif isinstance(command_params, dict): + for expected_param in command_params["openbb"]["QueryParams"]["fields"]: if expected_param not in test_params.keys(): missing_params.append( - f"Missing param {expected_param} for provider {provider} in function {function}" + f"Missing standard param {expected_param} in function {function}" + ) + else: + for test_params in function_params: + if isinstance(command_params, list): + for expected_param in command_params[0]: + if expected_param not in test_params.keys(): + missing_params.append( + f"Missing param {expected_param} in function {function}" ) - else: - for expected_param in command_params["openbb"]["QueryParams"]["fields"]: - if expected_param not in test_params.keys(): - missing_params.append( - f"Missing standard param {expected_param} in function {function}" - ) - return missing_params def check_integration_tests( functions: Dict[str, Any], - check_function: Callable[[Dict[str, Dict[str, dict]], List[dict], str], List[str]], + check_function: Callable[ + [ + Union[Dict[str, Dict[str, dict]], List[Dict[str, str]]], + List[dict], + str, + bool, + ], + List[str], + ], ) -> List[str]: """Check if there are any missing items for integration tests.""" pi = ProviderInterface() provider_interface_map = pi.map cm = CommandMap(coverage_sep=".") + function_params: List[dict] = [] all_missing_items: List[str] = [] + used_functions: List[str] = [] for command, model in cm.commands_model.items(): for function in functions: @@ -115,10 +145,30 @@ def check_integration_tests( command_params: Dict[str, Dict[str, dict]] = provider_interface_map[ model ] - function_params: List[dict] = functions[function].pytestmark[1].args[1] + function_params = functions[function].pytestmark[1].args[1] missing_items = check_function( - command_params, function_params, function + command_params, function_params, function, False + ) + all_missing_items.extend(missing_items) + used_functions.append(function) + + # the processing commands are the ones that are left + processing_functions = [ + function for function in functions if function not in used_functions + ] + + for route, _ in cm.map.items(): + for function in processing_functions: + if route.replace("/", "_")[1:] == function.replace("test_", ""): + hints = get_type_hints(cm.map[route]) + processing_command_params = [ + {k: "" for k in get_test_params_data_processing(hints)} + ] + function_params = functions[function].pytestmark[1].args[1] + + missing_items = check_function( + processing_command_params, function_params, function, True ) all_missing_items.extend(missing_items)