Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor split smartdevice tests to test_{iot,smart}device #822

Merged
merged 1 commit into from
Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion kasa/tests/device_fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ async def get_device_for_fixture(fixture_data: FixtureInfo):
"system": {"get_sysinfo": fixture_data.data["system"]["get_sysinfo"]}
}

if discovery_data: # Child devices do not have discovery info
if discovery_data: # Child devices do not have discovery info
d.update_from_discover_info(discovery_data)

await _update_and_close(d)
Expand Down
4 changes: 3 additions & 1 deletion kasa/tests/smart/modules/test_humidity.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
from kasa.smart.modules import HumiditySensor
from kasa.tests.device_fixtures import parametrize

humidity = parametrize("has humidity", component_filter="humidity", protocol_filter={"SMART.CHILD"})
humidity = parametrize(
"has humidity", component_filter="humidity", protocol_filter={"SMART.CHILD"}
)


@humidity
Expand Down
4 changes: 3 additions & 1 deletion kasa/tests/smart/modules/test_temperature.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
from kasa.smart.modules import TemperatureSensor
from kasa.tests.device_fixtures import parametrize

temperature = parametrize("has temperature", component_filter="temperature", protocol_filter={"SMART.CHILD"})
temperature = parametrize(
"has temperature", component_filter="temperature", protocol_filter={"SMART.CHILD"}
)


@temperature
Expand Down
9 changes: 8 additions & 1 deletion kasa/tests/test_bulb.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
variable_temp,
variable_temp_iot,
)
from .test_smartdevice import SYSINFO_SCHEMA
from .test_iotdevice import SYSINFO_SCHEMA


@bulb
Expand Down Expand Up @@ -370,3 +370,10 @@ async def test_modify_preset_payloads(dev: IotBulb, preset, payload, mocker):
],
}
)


@bulb
def test_device_type_bulb(dev):
if dev.is_light_strip:
pytest.skip("bulb has also lightstrips to test the api")
assert dev.device_type == DeviceType.Bulb
121 changes: 121 additions & 0 deletions kasa/tests/test_device.py
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not completely happy about the naming of this file, as it doesn't really test the Device API at the moment, but rather some other common functionalities.

Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
"""Tests for all devices."""
import importlib
import inspect
import pkgutil
import sys
from unittest.mock import Mock, patch

import pytest

import kasa
from kasa import Credentials, Device, DeviceConfig
from kasa.iot import IotDevice
from kasa.smart import SmartChildDevice, SmartDevice


def _get_subclasses(of_class):
package = sys.modules["kasa"]
subclasses = set()
for _, modname, _ in pkgutil.iter_modules(package.__path__):
importlib.import_module("." + modname, package="kasa")
module = sys.modules["kasa." + modname]
for name, obj in inspect.getmembers(module):
if (
inspect.isclass(obj)
and issubclass(obj, of_class)
and module.__package__ != "kasa"
):
subclasses.add((module.__package__ + "." + name, obj))
return subclasses


device_classes = pytest.mark.parametrize(
"device_class_name_obj", _get_subclasses(Device), ids=lambda t: t[0]
)


async def test_alias(dev):
test_alias = "TEST1234"
original = dev.alias

assert isinstance(original, str)
await dev.set_alias(test_alias)
await dev.update()
assert dev.alias == test_alias

await dev.set_alias(original)
await dev.update()
assert dev.alias == original


@device_classes
async def test_device_class_ctors(device_class_name_obj):
"""Make sure constructor api not broken for new and existing SmartDevices."""
host = "127.0.0.2"
port = 1234
credentials = Credentials("foo", "bar")
config = DeviceConfig(host, port_override=port, credentials=credentials)
klass = device_class_name_obj[1]
if issubclass(klass, SmartChildDevice):
parent = SmartDevice(host, config=config)
dev = klass(
parent, {"dummy": "info", "device_id": "dummy"}, {"dummy": "components"}
)
else:
dev = klass(host, config=config)
assert dev.host == host
assert dev.port == port
assert dev.credentials == credentials


async def test_create_device_with_timeout():
"""Make sure timeout is passed to the protocol."""
host = "127.0.0.1"
dev = IotDevice(host, config=DeviceConfig(host, timeout=100))
assert dev.protocol._transport._timeout == 100
dev = SmartDevice(host, config=DeviceConfig(host, timeout=100))
assert dev.protocol._transport._timeout == 100


async def test_create_thin_wrapper():
"""Make sure thin wrapper is created with the correct device type."""
mock = Mock()
config = DeviceConfig(
host="test_host",
port_override=1234,
timeout=100,
credentials=Credentials("username", "password"),
)
with patch("kasa.device_factory.connect", return_value=mock) as connect:
dev = await Device.connect(config=config)
assert dev is mock

connect.assert_called_once_with(
host=None,
config=config,
)


@pytest.mark.parametrize(
"device_class, use_class", kasa.deprecated_smart_devices.items()
)
def test_deprecated_devices(device_class, use_class):
package_name = ".".join(use_class.__module__.split(".")[:-1])
msg = f"{device_class} is deprecated, use {use_class.__name__} from package {package_name} instead"
with pytest.deprecated_call(match=msg):
getattr(kasa, device_class)
packages = package_name.split(".")
module = __import__(packages[0])
for _ in packages[1:]:
module = importlib.import_module(package_name, package=module.__name__)
getattr(module, use_class.__name__)


@pytest.mark.parametrize(
"exceptions_class, use_class", kasa.deprecated_exceptions.items()
)
def test_deprecated_exceptions(exceptions_class, use_class):
msg = f"{exceptions_class} is deprecated, use {use_class.__name__} instead"
with pytest.deprecated_call(match=msg):
getattr(kasa, exceptions_class)
getattr(kasa, use_class.__name__)
6 changes: 6 additions & 0 deletions kasa/tests/test_dimmer.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import pytest

from kasa import DeviceType
from kasa.iot import IotDimmer

from .conftest import dimmer, handle_turn_on, turn_on
Expand Down Expand Up @@ -132,3 +133,8 @@ async def test_set_dimmer_transition_invalid(dev):
for invalid_transition in [-1, 0, 0.5]:
with pytest.raises(ValueError):
await dev.set_dimmer_transition(1, invalid_transition)


@dimmer
def test_device_type_dimmer(dev):
assert dev.device_type == DeviceType.Dimmer