Skip to content

Commit

Permalink
test(coverage): fix non-tested code
Browse files Browse the repository at this point in the history
  • Loading branch information
xaviml committed Apr 25, 2020
1 parent 1459826 commit 5379fb9
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 30 deletions.
7 changes: 7 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[report]
exclude_lines =
# Have to re-enable the standard pragma
pragma: no cover

# Don't complain if tests don't hit defensive assertion code:
raise NotImplementedError
21 changes: 19 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,16 @@ repos:
rev: 19.10b0
hooks:
- id: black
language_version: python3.8
- repo: https://gitlab.com/pycqa/flake8
rev: 3.7.9
hooks:
- id: flake8
files: apps/controllerx
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v0.770
hooks:
- id: mypy
files: apps/controllerx
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.4.0
hooks:
Expand All @@ -12,4 +21,12 @@ repos:
args:
- --autofix
- --indent
- "4"
- "4"
- repo: local
hooks:
- id: pytest
name: pytest
entry: pytest
language: system
pass_filenames: false
always_run: true
5 changes: 3 additions & 2 deletions apps/controllerx/core/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ def get_type_actions_mapping(self) -> TypeActionsMapping:
class TypeController(Controller, abc.ABC):
@abc.abstractmethod
def get_domain(self) -> str:
...
raise NotImplementedError

async def check_domain(self, entity: str) -> None:
domain = self.get_domain()
Expand Down Expand Up @@ -277,13 +277,14 @@ async def before_action(self, action: str, *args, **kwargs) -> bool:
to_return = not (action == "hold" and self.on_hold)
return await super().before_action(action, *args, **kwargs) and to_return

@abc.abstractmethod
async def hold_loop(self, *args) -> bool:
"""
This function is called by the ReleaseHoldController depending on the settings.
It stops calling the function once release action is called or when this function
returns True.
"""
return True
raise NotImplementedError

def default_delay(self) -> int:
"""
Expand Down
2 changes: 1 addition & 1 deletion apps/controllerx/core/custom_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def parse_action(self, action: str) -> TypeAction:
It should eiter return a value parsed by 'get_type_actions_mapping' or
a tuple with (function, arg1, arg2, ...).
"""
...
raise NotImplementedError

def get_z2m_actions_mapping(self) -> TypeActionsMapping:
return self.get_custom_mapping()
Expand Down
6 changes: 3 additions & 3 deletions apps/controllerx/core/integration/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ def __init__(self, controller, kwargs: Dict[str, Any]):

@abc.abstractmethod
def get_name(self) -> str:
...
raise NotImplementedError

@abc.abstractmethod
def get_actions_mapping(self) -> Optional[TypeActionsMapping]:
...
raise NotImplementedError

@abc.abstractmethod
def listen_changes(self, controller_id: str) -> None:
...
raise NotImplementedError


def _import_modules(file_dir: str, package: str) -> None:
Expand Down
2 changes: 1 addition & 1 deletion apps/controllerx/core/stepper/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ def step(self, value: float, direction: str) -> Tuple[Union[int, float], bool]:
that needs to take and returns the new value and True
if the step exceeds the boundaries.
"""
...
raise NotImplementedError
22 changes: 20 additions & 2 deletions tests/core/controller_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
from core import integration as integration_module
from core.controller import action
from tests.test_utils import (
hass_mock,
fake_controller,
IntegrationMock,
fake_async_function,
fake_controller,
hass_mock,
)


Expand Down Expand Up @@ -160,6 +160,7 @@ async def test_initialize(
("sensor1, sensor2", ["sensor1", "sensor2"]),
("sensor1,sensor2", ["sensor1", "sensor2"]),
(["sensor1", "sensor2"], ["sensor1", "sensor2"]),
(0.0, []),
],
)
def test_get_list(sut, monkeypatch, test_input, expected):
Expand Down Expand Up @@ -194,6 +195,7 @@ def test_get_option(sut, option, options, expect_an_error):
False,
),
({"test": "no name"}, "z2m", {}, True),
(0.0, None, {}, True),
],
)
def test_get_integration(
Expand Down Expand Up @@ -347,3 +349,19 @@ def test_get_action(sut, test_input, expected, error_expected):
else:
output = sut.get_action(test_input)
assert output == expected


@pytest.mark.parametrize(
"service, attributes",
[("test_service", {"attr1": 0.0, "attr2": "test"}), ("test_service", {}),],
)
@pytest.mark.asyncio
async def test_call_service(sut, mocker, service, attributes):

call_service_stub = mocker.patch.object(hass.Hass, "call_service")

# SUT
await sut.call_service(service, **attributes)

# Checker
call_service_stub.assert_called_once_with(service, **attributes)
73 changes: 55 additions & 18 deletions tests/core/type/light_controller_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,30 @@ def sut(hass_mock, monkeypatch):


@pytest.mark.parametrize(
"light_input, light_output",
"light_input, light_output, error_expected",
[
("light.kitchen", {"name": "light.kitchen", "color_mode": "auto"}),
("light.kitchen", {"name": "light.kitchen", "color_mode": "auto"}, False),
(
{"name": "light.kitchen", "color_mode": "auto"},
{"name": "light.kitchen", "color_mode": "auto"},
False,
),
(
{"name": "light.kitchen"},
{"name": "light.kitchen", "color_mode": "auto"},
False,
),
({"name": "light.kitchen"}, {"name": "light.kitchen", "color_mode": "auto"}),
(
{"name": "light.kitchen", "color_mode": "color_temp"},
{"name": "light.kitchen", "color_mode": "color_temp"},
False,
),
(0.0, None, True),
],
)
@pytest.mark.asyncio
async def test_initialize_and_get_light(
sut, monkeypatch, mocker, light_input, light_output
sut, monkeypatch, mocker, light_input, light_output, error_expected
):
super_initialize_stub = mocker.stub()

Expand All @@ -48,10 +55,17 @@ async def fake_super_initialize(self):
monkeypatch.setattr(ReleaseHoldController, "initialize", fake_super_initialize)

sut.args["light"] = light_input
await sut.initialize()

super_initialize_stub.assert_called_once()
assert sut.light == light_output
# SUT
if error_expected:
with pytest.raises(ValueError) as e:
await sut.initialize()
else:
await sut.initialize()

# Checks
super_initialize_stub.assert_called_once()
assert sut.light == light_output


@pytest.mark.parametrize(
Expand Down Expand Up @@ -97,20 +111,34 @@ def test_get_attribute(


@pytest.mark.parametrize(
"attribute_input, expected_output",
[("xy_color", 0), ("brightness", 3.0), ("color_temp", 1),],
"attribute_input, expected_output, error_expected",
[
("xy_color", 0, False),
("brightness", 3.0, False),
("color_temp", 1, False),
("xy_color", 0, False),
("brightness", None, True),
("color_temp", None, True),
],
)
@pytest.mark.asyncio
async def test_get_value_attribute(sut, monkeypatch, attribute_input, expected_output):
async def test_get_value_attribute(
sut, monkeypatch, attribute_input, expected_output, error_expected
):
async def fake_get_entity_state(entity, attribute):
return expected_output

monkeypatch.setattr(sut, "get_entity_state", fake_get_entity_state)

# SUT
output = await sut.get_value_attribute(attribute_input)
if error_expected:
with pytest.raises(ValueError) as e:
await sut.get_value_attribute(attribute_input)
else:
output = await sut.get_value_attribute(attribute_input)

assert output == expected_output
# Checks
assert output == expected_output


@pytest.mark.parametrize(
Expand Down Expand Up @@ -459,15 +487,24 @@ def fake_get_attribute(*args, **kwargs):
super_hold_patch.assert_called_with(attribute_input, expected_direction)


@pytest.mark.parametrize(
"value_attribute", [10, None],
)
@pytest.mark.asyncio
async def test_hold_loop(sut, mocker):
async def test_hold_loop(sut, mocker, value_attribute):
attribute = "test_attribute"
direction = Stepper.UP
sut.value_attribute = 10
sut.value_attribute = value_attribute
change_light_state_patch = mocker.patch.object(sut, "change_light_state")
stepper = MinMaxStepper(1, 10, 10)
sut.automatic_steppers = {attribute: stepper}
await sut.hold_loop(attribute, direction)
change_light_state_patch.assert_called_once_with(
sut.value_attribute, attribute, direction, stepper, "hold"
)

# SUT
exceeded = await sut.hold_loop(attribute, direction)

if value_attribute is None:
assert exceeded == True
else:
change_light_state_patch.assert_called_once_with(
sut.value_attribute, attribute, direction, stepper, "hold"
)
2 changes: 1 addition & 1 deletion tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def fake_fn(*args, **kwargs):
monkeypatch.setattr(hass.Hass, "listen_event", fake_fn)
monkeypatch.setattr(hass.Hass, "listen_state", fake_fn)
monkeypatch.setattr(hass.Hass, "log", fake_fn)
monkeypatch.setattr(hass.Hass, "call_service", fake_fn)
monkeypatch.setattr(hass.Hass, "call_service", fake_async_function())


@pytest.fixture
Expand Down

0 comments on commit 5379fb9

Please sign in to comment.