Skip to content

Commit

Permalink
test_parser typing (#584)
Browse files Browse the repository at this point in the history
typing for tests/framework/components/test_parser.py
  • Loading branch information
hussain-jafari authored Feb 12, 2025
1 parent a816095 commit 14dae78
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 20 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
**3.3.2 - 02/12/25**

- Type-hinting: Fix mypy errors in tests/framework/components/test_parser.py

**3.3.1 - 02/07/25**

- Type-hinting: Fix mypy errors in tests/framework/lookup/test_interpolation.py
Expand Down
1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ exclude = [
'src/vivarium/testing_utilities.py',
'tests/examples/test_disease_model.py',
'tests/framework/components/test_manager.py',
'tests/framework/components/test_parser.py',
'tests/framework/lookup/test_lookup.py',
'tests/framework/population/test_manager.py',
'tests/framework/population/test_population_view.py',
Expand Down
39 changes: 20 additions & 19 deletions tests/framework/components/test_parser.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
from unittest.mock import call
from abc import ABCMeta
from typing import Any
from unittest.mock import Mock, call

import pytest
import yaml
from _pytest.monkeypatch import MonkeyPatch
from layered_config_tree.main import LayeredConfigTree
from pytest_mock import MockerFixture

from tests.helpers import MockComponentA, MockComponentB
from vivarium.framework.components.parser import ComponentConfigurationParser, ParsingError
Expand Down Expand Up @@ -75,40 +79,34 @@
]


def mock_importer(path):
def mock_importer(path: str) -> ABCMeta:
return {
"test_components.MockComponentA": MockComponentA,
"test_components.MockComponentB": MockComponentB,
}[path]


@pytest.fixture()
def parser(mocker) -> ComponentConfigurationParser:
def parser(mocker: MockerFixture) -> ComponentConfigurationParser:
parser = ComponentConfigurationParser()
parser.import_and_instantiate_component = mocker.Mock()
parser.import_and_instantiate_component = mocker.Mock() # type: ignore [method-assign]
return parser


@pytest.fixture(params=[TEST_COMPONENTS_NESTED, TEST_COMPONENTS_FLAT])
def components(request):
def components(request: pytest.FixtureRequest) -> str:
assert isinstance(request.param, str)
return request.param


@pytest.fixture
def import_and_instantiate_mock(mocker):
return mocker.patch(
"vivarium.framework.components.parser.import_and_instantiate_component"
)


def test_prep_component(parser):
def test_prep_component(parser: ComponentConfigurationParser) -> None:
desc = 'cave_system.monsters.Rabbit("timid", "squeak")'
component, args = parser.prep_component(desc)
assert component == "cave_system.monsters.Rabbit"
assert set(args) == {"timid", "squeak"}


def test_prep_component_syntax_error(parser):
def test_prep_component_syntax_error(parser: ComponentConfigurationParser) -> None:
desc = 'cave_system.monsters.Rabbit("timid", 0.01)'
with pytest.raises(ParsingError):
parser.prep_component(desc)
Expand All @@ -122,15 +120,15 @@ def test_prep_component_syntax_error(parser):
parser.prep_component(desc)


def test_parse_and_prep_components(parser):
def test_parse_and_prep_components(parser: ComponentConfigurationParser) -> None:
prepped_components = [
parser.prep_component(component) for component in TEST_COMPONENTS_PARSED
]

assert set(TEST_COMPONENTS_PREPPED) == set(prepped_components)


def test_import_and_instantiate_components(monkeypatch):
def test_import_and_instantiate_components(monkeypatch: MonkeyPatch) -> None:
monkeypatch.setattr("vivarium.framework.components.parser.import_by_path", mock_importer)

component_descriptions = [
Expand All @@ -151,14 +149,15 @@ def test_import_and_instantiate_components(monkeypatch):
assert component_list[1].args == ("Ethel the Aardvark goes Quantity Surveying",)


def test_get_components(parser, components):
def test_get_components(parser: ComponentConfigurationParser, components: str) -> None:
config = build_simulation_configuration()
config.update(components)

parser.get_components(config.components)

calls = [call(path, args) for path, args in TEST_COMPONENTS_PREPPED]
parser.import_and_instantiate_component.assert_has_calls(calls)
# mypy is interpreting assert_has_calls as an attribute
parser.import_and_instantiate_component.assert_has_calls(calls) # type: ignore[attr-defined]


@pytest.mark.parametrize(
Expand All @@ -168,7 +167,9 @@ def test_get_components(parser, components):
(TEST_COMPONENTS_NON_STRING, "should be a string, list, or dictionary"),
],
)
def test_components_invalid_config(parser, config, error_message):
def test_components_invalid_config(
parser: ComponentConfigurationParser, config: str, error_message: str
) -> None:
bad_config = LayeredConfigTree(yaml.full_load(config))["components"]
with pytest.raises(ParsingError, match=error_message):
parser.parse_component_config(bad_config)

0 comments on commit 14dae78

Please sign in to comment.