mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-11-08 02:11:44 +00:00
Merge branch 'feature/unit-tests' of github.com:OpenBB-finance/OpenBBTerminal into feature/unit-tests
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
"""App factory."""
|
||||
# pylint: disable=W0231:super-init-not-called
|
||||
|
||||
from openbb_core.app.command_runner import CommandRunnerSession
|
||||
@@ -8,6 +9,7 @@ from openbb_core.app.static.coverage import Coverage
|
||||
|
||||
|
||||
def create_app():
|
||||
"""Create the app."""
|
||||
try:
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from openbb_core.app.static.package.__commands__ import Commands
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
"""Container class."""
|
||||
from openbb_core.app.command_runner import CommandRunnerSession
|
||||
|
||||
|
||||
class Container:
|
||||
"""Container class for the command runner session."""
|
||||
|
||||
def __init__(self, command_runner_session: CommandRunnerSession) -> None:
|
||||
self._command_runner_session = command_runner_session
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
"""Coverage module."""
|
||||
from openbb_core.app.router import CommandMap
|
||||
|
||||
|
||||
class Coverage:
|
||||
"""Coverage class."""
|
||||
|
||||
def __init__(self):
|
||||
self.__command_map = CommandMap()
|
||||
|
||||
@property
|
||||
def providers(self):
|
||||
"""Return providers coverage."""
|
||||
return self.__command_map.provider_coverage
|
||||
|
||||
@property
|
||||
def commands(self):
|
||||
"""Return commands coverage."""
|
||||
return self.__command_map.command_coverage
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
"""OpenBB filters."""
|
||||
|
||||
import builtins
|
||||
from functools import wraps
|
||||
|
||||
@@ -10,10 +12,12 @@ from openbb_core.app.utils import df_to_basemodel
|
||||
|
||||
|
||||
class OpenBBError(Exception):
|
||||
pass
|
||||
"""A custom exception for OpenBB errors."""
|
||||
|
||||
|
||||
def filter_call(func):
|
||||
"""Filter command call."""
|
||||
|
||||
@wraps(wrapped=func)
|
||||
def inner(*args, **kwargs):
|
||||
self = args[0]
|
||||
@@ -36,7 +40,7 @@ def filter_call(func):
|
||||
|
||||
|
||||
def filter_inputs(**kwargs) -> dict:
|
||||
"""Filter command inputs"""
|
||||
"""Filter command inputs."""
|
||||
for key, value in kwargs.items():
|
||||
if isinstance(value, pd.DataFrame):
|
||||
kwargs[key] = df_to_basemodel(value, index=True)
|
||||
@@ -45,7 +49,7 @@ def filter_inputs(**kwargs) -> dict:
|
||||
|
||||
|
||||
def filter_output(command_output: CommandOutput) -> CommandOutput:
|
||||
"""Filter command output"""
|
||||
"""Filter command output."""
|
||||
if command_output.warnings:
|
||||
for w in command_output.warnings:
|
||||
category = getattr(builtins, w.category, OpenBBWarning)
|
||||
|
||||
0
openbb_sdk/sdk/core/tests/.gitkeep
vendored
0
openbb_sdk/sdk/core/tests/.gitkeep
vendored
@@ -2,6 +2,7 @@
|
||||
# pylint: disable=redefined-outer-name
|
||||
|
||||
from dataclasses import dataclass
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
from openbb_core.app.model.command_context import CommandContext
|
||||
@@ -11,6 +12,32 @@ from openbb_core.app.provider_interface import (
|
||||
StandardParams,
|
||||
)
|
||||
from openbb_core.app.query import Query
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
def create_mock_query():
|
||||
"""Mock query."""
|
||||
|
||||
class StockEOD:
|
||||
"""Mock StockEOD class."""
|
||||
|
||||
start_date = "2020-01-01"
|
||||
end_date = "2020-01-05"
|
||||
symbol = "AAPL"
|
||||
|
||||
return StockEOD()
|
||||
|
||||
|
||||
def create_mock_extra_params():
|
||||
"""Mock ExtraParams dataclass."""
|
||||
|
||||
@dataclass
|
||||
class StockEOD:
|
||||
"""Mock ExtraParams dataclass."""
|
||||
|
||||
sort: str = "desc"
|
||||
|
||||
return StockEOD()
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
@@ -31,29 +58,16 @@ def test_init(query):
|
||||
|
||||
def test_to_query_params(query):
|
||||
"""Test to_query_params."""
|
||||
standard_params = create_mock_query()
|
||||
|
||||
class StockEOD:
|
||||
"""Mock StockEOD class."""
|
||||
|
||||
open: float = 0.0
|
||||
high: float = 0.0
|
||||
|
||||
standard_params = StockEOD()
|
||||
assert query.to_query_params(standard_params)
|
||||
|
||||
|
||||
def test_filter_extra_params(query):
|
||||
"""Test filter_extra_params."""
|
||||
|
||||
@dataclass
|
||||
class StockEOD:
|
||||
"""Mock ExtraParams dataclass."""
|
||||
|
||||
sort: str = "desc"
|
||||
|
||||
extra_params = StockEOD()
|
||||
extra_params = create_mock_extra_params()
|
||||
extra_params = query.filter_extra_params(extra_params, "fmp")
|
||||
print(extra_params)
|
||||
|
||||
assert isinstance(extra_params, dict)
|
||||
assert len(extra_params) == 0
|
||||
|
||||
@@ -73,7 +87,40 @@ def test_filter_extra_params_wrong_param(query):
|
||||
assert not query.filter_extra_params(extra_params, "fmp")
|
||||
|
||||
|
||||
@pytest.mark.skip(reason="TODO: see how to properly mock the execute method")
|
||||
def test_execute(query):
|
||||
"""Test execute."""
|
||||
assert query.execute()
|
||||
@pytest.fixture
|
||||
def mock_registry():
|
||||
"""Mock registry."""
|
||||
with patch(
|
||||
"openbb_core.app.provider_interface.get_provider_interface"
|
||||
) as mock_get_provider_interface:
|
||||
mock_registry = MagicMock()
|
||||
mock_get_provider_interface.return_value.build_registry.return_value = (
|
||||
mock_registry
|
||||
)
|
||||
yield mock_registry
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def query_instance():
|
||||
"""Set up query."""
|
||||
standard_params = create_mock_query()
|
||||
extra_params = create_mock_extra_params()
|
||||
|
||||
cc = CommandContext()
|
||||
setattr(cc.user_settings.credentials, "fmp_api_key", "1234")
|
||||
|
||||
return Query(
|
||||
cc=cc,
|
||||
provider_choices=ProviderChoices(provider="fmp"),
|
||||
standard_params=standard_params,
|
||||
extra_params=extra_params,
|
||||
)
|
||||
|
||||
|
||||
def test_execute_method_fake_credentials(query_instance, mock_registry):
|
||||
"""Test execute method without setting credentials."""
|
||||
mock_fetch_result = BaseModel() # Replace with an actual instance of BaseModel
|
||||
mock_registry.fetch.return_value = mock_fetch_result
|
||||
|
||||
with pytest.raises(Exception):
|
||||
query_instance.execute()
|
||||
|
||||
307
openbb_sdk/sdk/core/tests/test_router.py
Normal file
307
openbb_sdk/sdk/core/tests/test_router.py
Normal file
@@ -0,0 +1,307 @@
|
||||
"""Test router.py file."""
|
||||
# pylint: disable=redefined-outer-name
|
||||
# pylint: disable=unused-argument
|
||||
|
||||
|
||||
import pytest
|
||||
from openbb_core.app.model.command_context import CommandContext
|
||||
from openbb_core.app.model.command_output import CommandOutput
|
||||
from openbb_core.app.provider_interface import (
|
||||
ExtraParams,
|
||||
ProviderChoices,
|
||||
StandardParams,
|
||||
)
|
||||
from openbb_core.app.router import (
|
||||
CommandMap,
|
||||
CommandValidator,
|
||||
Router,
|
||||
RouterLoader,
|
||||
SignatureInspector,
|
||||
)
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def command_validator():
|
||||
"""Set up command_validator."""
|
||||
return CommandValidator()
|
||||
|
||||
|
||||
def test_command_validator_init(command_validator):
|
||||
"""Test init."""
|
||||
assert command_validator
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"type_, expected",
|
||||
[
|
||||
(str, True),
|
||||
(int, True),
|
||||
(float, True),
|
||||
(bool, True),
|
||||
(list, True),
|
||||
(BaseModel, False),
|
||||
],
|
||||
)
|
||||
def test_is_standard_pydantic_type(command_validator, type_, expected):
|
||||
"""Test is_standard_pydantic_type."""
|
||||
# assert command_validator.is_standard_pydantic_type(str)
|
||||
assert command_validator.is_standard_pydantic_type(type_) == expected
|
||||
|
||||
|
||||
def test_is_valid_pydantic_model_type(command_validator):
|
||||
"""Test is_valid_pydantic_model_type."""
|
||||
assert command_validator.is_valid_pydantic_model_type(BaseModel)
|
||||
assert not command_validator.is_valid_pydantic_model_type(str)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"type_, expected",
|
||||
[
|
||||
(str, True),
|
||||
(int, True),
|
||||
(float, True),
|
||||
(bool, True),
|
||||
(list, True),
|
||||
(BaseModel, True),
|
||||
],
|
||||
)
|
||||
def test_is_serializable_value_type(command_validator, type_, expected):
|
||||
"""Test is_serializable_value_type."""
|
||||
assert command_validator.is_serializable_value_type(type_) == expected
|
||||
|
||||
|
||||
def test_is_annotated_dc(command_validator):
|
||||
"""Test is_annotated_dc."""
|
||||
assert not command_validator.is_annotated_dc(str)
|
||||
|
||||
|
||||
def test_check_reserved_param(command_validator):
|
||||
"""Test check_reserved_param."""
|
||||
assert command_validator.check_reserved_param("name", str, {}, str, str) is None
|
||||
assert not command_validator.check_reserved_param("name", str, {}, str, int)
|
||||
|
||||
|
||||
def test_check_parameters(command_validator):
|
||||
"""Test check_parameters."""
|
||||
|
||||
def func():
|
||||
pass
|
||||
|
||||
assert command_validator.check_parameters(func) is None
|
||||
assert not command_validator.check_parameters(BaseModel)
|
||||
|
||||
|
||||
def test_check_return_error(command_validator):
|
||||
"""Test check_return fail."""
|
||||
with pytest.raises(TypeError):
|
||||
|
||||
def func():
|
||||
pass
|
||||
|
||||
command_validator.check_return(func)
|
||||
|
||||
|
||||
def test_check_return(command_validator):
|
||||
"""Test check_return."""
|
||||
|
||||
def valid_function() -> CommandOutput[int]:
|
||||
return CommandOutput(results=[1, 2, 3])
|
||||
|
||||
assert command_validator.check_return(valid_function) is None
|
||||
|
||||
|
||||
def test_check(command_validator):
|
||||
"""Test check."""
|
||||
|
||||
def valid_function() -> CommandOutput[int]:
|
||||
return CommandOutput(results=[1, 2, 3])
|
||||
|
||||
assert command_validator.check(valid_function) is None
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def router():
|
||||
"""Set up router."""
|
||||
return Router()
|
||||
|
||||
|
||||
def test_router_init(router):
|
||||
"""Test init."""
|
||||
assert router
|
||||
|
||||
|
||||
def test_command(router):
|
||||
"""Test command."""
|
||||
|
||||
@router.command
|
||||
def valid_function() -> CommandOutput[int]:
|
||||
return CommandOutput(results=[1, 2, 3])
|
||||
|
||||
assert valid_function
|
||||
|
||||
|
||||
def test_include_router(router):
|
||||
"""Test include_router."""
|
||||
some_router = Router()
|
||||
assert router.include_router(some_router) is None
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def router_loader():
|
||||
"""Set up router_loader."""
|
||||
return RouterLoader()
|
||||
|
||||
|
||||
def test_router_loader_init(router_loader):
|
||||
"""Test init."""
|
||||
assert router_loader
|
||||
|
||||
|
||||
def test_from_extensions(router_loader):
|
||||
"""Test from_extensions."""
|
||||
assert router_loader.from_extensions()
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def signature_inspector():
|
||||
"""Set up signature_inspector."""
|
||||
return SignatureInspector()
|
||||
|
||||
|
||||
def test_signature_inspector_init(signature_inspector):
|
||||
"""Test init."""
|
||||
assert signature_inspector
|
||||
|
||||
|
||||
def test_complete_signature(signature_inspector):
|
||||
"""Test complete_signature."""
|
||||
|
||||
def sample_function(
|
||||
cc: CommandContext,
|
||||
provider_choices: ProviderChoices,
|
||||
standard_params: StandardParams,
|
||||
extra_params: ExtraParams,
|
||||
) -> CommandOutput:
|
||||
pass
|
||||
|
||||
model = "StockEOD"
|
||||
|
||||
assert signature_inspector.complete_signature(sample_function, model)
|
||||
|
||||
|
||||
def test_complete_signature_error(signature_inspector):
|
||||
"""Test complete_signature."""
|
||||
|
||||
def valid_function() -> CommandOutput[int]:
|
||||
return CommandOutput(results=[1, 2, 3])
|
||||
|
||||
with pytest.raises(AttributeError):
|
||||
signature_inspector.complete_signature(valid_function, "invalid_model")
|
||||
|
||||
|
||||
def test_validate_signature(signature_inspector):
|
||||
"""Test validate_signature."""
|
||||
|
||||
def sample_function(
|
||||
cc: CommandContext,
|
||||
provider_choices: ProviderChoices,
|
||||
standard_params: StandardParams,
|
||||
extra_params: ExtraParams,
|
||||
) -> CommandOutput:
|
||||
pass
|
||||
|
||||
expected_signature = {
|
||||
"cc": CommandContext,
|
||||
"provider_choices": ProviderChoices,
|
||||
"standard_params": StandardParams,
|
||||
"extra_params": ExtraParams,
|
||||
}
|
||||
|
||||
assert (
|
||||
signature_inspector.validate_signature(sample_function, expected_signature)
|
||||
is None
|
||||
)
|
||||
|
||||
|
||||
def test_inject_dependency(signature_inspector):
|
||||
"""Test inject_dependency."""
|
||||
|
||||
def sample_function(
|
||||
cc: CommandContext,
|
||||
provider_choices: ProviderChoices,
|
||||
standard_params: StandardParams,
|
||||
extra_params: ExtraParams,
|
||||
) -> CommandOutput:
|
||||
pass
|
||||
|
||||
assert signature_inspector.inject_dependency(sample_function, "cc", CommandContext)
|
||||
|
||||
|
||||
def test_get_description(signature_inspector):
|
||||
"""Test get_description."""
|
||||
|
||||
def some_function():
|
||||
"""Mock function."""
|
||||
|
||||
assert signature_inspector.get_description(some_function) == some_function.__doc__
|
||||
|
||||
|
||||
def test_get_description_no_doc(signature_inspector):
|
||||
"""Test get_description."""
|
||||
|
||||
def some_function():
|
||||
pass
|
||||
|
||||
assert signature_inspector.get_description(some_function) == ""
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def command_map():
|
||||
"""Set up command_map."""
|
||||
return CommandMap()
|
||||
|
||||
|
||||
def test_command_map_init(command_map):
|
||||
"""Test init."""
|
||||
assert command_map
|
||||
|
||||
|
||||
def test_map(command_map):
|
||||
"""Test map."""
|
||||
assert isinstance(command_map.map, dict)
|
||||
|
||||
|
||||
def test_provider_coverage(command_map):
|
||||
"""Test provider_coverage."""
|
||||
assert isinstance(command_map.provider_coverage, dict)
|
||||
|
||||
|
||||
def test_command_coverage(command_map):
|
||||
"""Test command_coverage."""
|
||||
assert isinstance(command_map.command_coverage, dict)
|
||||
|
||||
|
||||
def test_get_command_map(command_map, router):
|
||||
"""Test get_command_map."""
|
||||
command_map = command_map.get_command_map(router)
|
||||
assert isinstance(command_map, dict)
|
||||
assert len(command_map) > 0
|
||||
|
||||
|
||||
def test_get_provider_coverage(command_map, router):
|
||||
"""Test get_provider_coverage."""
|
||||
provider_coverage = command_map.get_provider_coverage(router)
|
||||
assert isinstance(provider_coverage, dict)
|
||||
|
||||
|
||||
def test_get_command_coverage(command_map, router):
|
||||
"""Test get_command_coverage."""
|
||||
command_coverage = command_map.get_command_coverage(router)
|
||||
assert isinstance(command_coverage, dict)
|
||||
|
||||
|
||||
def test_get_command(command_map):
|
||||
"""Test get_command."""
|
||||
command = command_map.get_command("stocks/load")
|
||||
assert command is None
|
||||
48
openbb_sdk/sdk/core/tests/test_static_app_factory.py
Normal file
48
openbb_sdk/sdk/core/tests/test_static_app_factory.py
Normal file
@@ -0,0 +1,48 @@
|
||||
"""Test static app factory."""
|
||||
# pylint: disable=redefined-outer-name
|
||||
|
||||
import pytest
|
||||
from openbb_core.app.model.system_settings import SystemSettings
|
||||
from openbb_core.app.model.user_settings import UserSettings
|
||||
from openbb_core.app.static.account import Account
|
||||
from openbb_core.app.static.app_factory import create_app
|
||||
from openbb_core.app.static.coverage import Coverage
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def app_factory():
|
||||
"""Return app factory."""
|
||||
return create_app()
|
||||
|
||||
|
||||
def test_app_factory_init(app_factory):
|
||||
"""Test app factory init."""
|
||||
assert app_factory
|
||||
|
||||
|
||||
def test_app_system_settings(app_factory):
|
||||
"""Test app system settings."""
|
||||
system_settings = app_factory.system
|
||||
assert system_settings
|
||||
assert isinstance(system_settings, SystemSettings)
|
||||
|
||||
|
||||
def test_app_user_settings(app_factory):
|
||||
"""Test app user settings."""
|
||||
user_settings = app_factory.settings
|
||||
assert user_settings
|
||||
assert isinstance(user_settings, UserSettings)
|
||||
|
||||
|
||||
def test_app_account(app_factory):
|
||||
"""Test app account."""
|
||||
account = app_factory.account
|
||||
assert account
|
||||
assert isinstance(account, Account)
|
||||
|
||||
|
||||
def test_app_coverage(app_factory):
|
||||
"""Test app coverage."""
|
||||
coverage = app_factory.coverage
|
||||
assert coverage
|
||||
assert isinstance(coverage, Coverage)
|
||||
9
openbb_sdk/sdk/core/tests/test_static_container.py
Normal file
9
openbb_sdk/sdk/core/tests/test_static_container.py
Normal file
@@ -0,0 +1,9 @@
|
||||
"""Test the app/static/container.py file."""
|
||||
|
||||
from openbb_core.app.static.container import Container
|
||||
|
||||
|
||||
def test_container_init():
|
||||
"""Test container init."""
|
||||
container = Container(None)
|
||||
assert container
|
||||
30
openbb_sdk/sdk/core/tests/test_static_coverage.py
Normal file
30
openbb_sdk/sdk/core/tests/test_static_coverage.py
Normal file
@@ -0,0 +1,30 @@
|
||||
"""Test the app/static/coverage.py file."""
|
||||
# pylint: disable=redefined-outer-name
|
||||
|
||||
import pytest
|
||||
from openbb_core.app.static.coverage import Coverage
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def coverage():
|
||||
"""Return coverage."""
|
||||
return Coverage()
|
||||
|
||||
|
||||
def test_coverage_init(coverage):
|
||||
"""Test coverage init."""
|
||||
assert coverage
|
||||
|
||||
|
||||
def test_coverage_providers(coverage):
|
||||
"""Test coverage providers."""
|
||||
provider_coverage = coverage.providers
|
||||
assert provider_coverage
|
||||
assert isinstance(provider_coverage, dict)
|
||||
|
||||
|
||||
def test_coverage_commands(coverage):
|
||||
"""Test coverage commands."""
|
||||
command_coverage = coverage.commands
|
||||
assert command_coverage
|
||||
assert isinstance(command_coverage, dict)
|
||||
44
openbb_sdk/sdk/core/tests/test_static_filters.py
Normal file
44
openbb_sdk/sdk/core/tests/test_static_filters.py
Normal file
@@ -0,0 +1,44 @@
|
||||
"""Test the app/static/filters.py file."""
|
||||
|
||||
import pytest
|
||||
from openbb_core.app.model.command_output import CommandOutput
|
||||
from openbb_core.app.static.filters import filter_call, filter_inputs, filter_output
|
||||
from pandas import DataFrame
|
||||
|
||||
|
||||
def test_filter_call_error():
|
||||
"""Test filter_call."""
|
||||
|
||||
class Test:
|
||||
@filter_call
|
||||
def test(self):
|
||||
return 1 / 0
|
||||
|
||||
test = Test()
|
||||
|
||||
with pytest.raises(Exception):
|
||||
test.test()
|
||||
|
||||
|
||||
def test_filter_inputs_not_df():
|
||||
"""Test filter_inputs."""
|
||||
kwargs = {"num": 1}
|
||||
kwargs = filter_inputs(**kwargs)
|
||||
|
||||
assert kwargs["num"] == 1
|
||||
|
||||
|
||||
def test_filter_inputs_df():
|
||||
"""Test filter_inputs."""
|
||||
df = DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]})
|
||||
kwargs = {"df": df}
|
||||
kwargs = filter_inputs(**kwargs)
|
||||
|
||||
assert isinstance(kwargs["df"], list)
|
||||
|
||||
|
||||
def test_filter_output():
|
||||
"""Test filter_output."""
|
||||
command_output = filter_output(CommandOutput())
|
||||
|
||||
assert command_output is not None
|
||||
2
pyproject.toml
vendored
2
pyproject.toml
vendored
@@ -183,7 +183,7 @@ select = ["E", "W", "F", "Q", "S", "UP", "I", "PLC", "PLE", "PLR", "PLW", "SIM"]
|
||||
ignore = ["S105", "S106", "S107", "S110", "PLR2004", "PLR0911", "PLR0913", "PLR0912", "PLR0915", "SIM114", "SIM105", "SIM117", "PLC1901", "PLR5501","PLW2901","PLW0603"]
|
||||
|
||||
[tool.ruff.per-file-ignores]
|
||||
"tests/*" = ["S101"]
|
||||
"*tests/*" = ["S101"]
|
||||
|
||||
[tool.ruff.flake8-import-conventions.aliases]
|
||||
"matplotlib.pyplot" = "plt"
|
||||
|
||||
Reference in New Issue
Block a user