From 1fec5cda018061a1c32a5297f539587a372fd7bc Mon Sep 17 00:00:00 2001 From: Steven B <51370195+sdb9696@users.noreply.github.com> Date: Fri, 8 Nov 2024 15:07:29 +0000 Subject: [PATCH 1/8] Fix test framework against real devices --- kasa/tests/device_fixtures.py | 48 +++++++++++++++++++---- kasa/tests/fixtureinfo.py | 10 +++-- kasa/tests/smart/modules/test_firmware.py | 1 + kasa/tests/test_aestransport.py | 2 + kasa/tests/test_cli.py | 4 ++ kasa/tests/test_device_factory.py | 2 + kasa/tests/test_discovery.py | 3 ++ kasa/tests/test_klapprotocol.py | 2 + kasa/tests/test_protocol.py | 11 ++++-- kasa/tests/test_smartdevice.py | 2 + kasa/tests/test_smartprotocol.py | 10 ++--- kasa/tests/test_sslaestransport.py | 2 + 12 files changed, 76 insertions(+), 21 deletions(-) diff --git a/kasa/tests/device_fixtures.py b/kasa/tests/device_fixtures.py index e05be7b69..ad1b03cd9 100644 --- a/kasa/tests/device_fixtures.py +++ b/kasa/tests/device_fixtures.py @@ -142,7 +142,7 @@ ) ALL_DEVICES = ALL_DEVICES_IOT.union(ALL_DEVICES_SMART) -IP_MODEL_CACHE: dict[str, str] = {} +IP_FIXTURE_CACHE: dict[str, FixtureInfo] = {} def parametrize_combine(parametrized: list[pytest.MarkDecorator]): @@ -448,6 +448,34 @@ def get_fixture_info(fixture, protocol): return fixture_info +def get_nearest_fixture_to_ip(dev): + if isinstance(dev, SmartDevice): + protocol_fixtures = filter_fixtures("", protocol_filter={"SMART"}) + elif isinstance(dev, SmartCamera): + protocol_fixtures = filter_fixtures("", protocol_filter={"SMARTCAMERA"}) + else: + protocol_fixtures = filter_fixtures("", protocol_filter={"IOT"}) + assert protocol_fixtures, "Unknown device type" + + # Could try an exact match here but would be easier if region was available + # on the device + if "(" in dev.model: + model, _, _ = dev.model.partition("(") + else: + model = dev.model + if model_fixtures := filter_fixtures( + "", model_filter={model}, fixture_list=protocol_fixtures + ): + return next(iter(model_fixtures)) + + if device_type_fixtures := filter_fixtures( + "", device_type_filter={dev.device_type}, fixture_list=protocol_fixtures + ): + return next(iter(device_type_fixtures)) + + return next(iter(protocol_fixtures)) + + @pytest.fixture(params=filter_fixtures("main devices"), ids=idgenerator) async def dev(request) -> AsyncGenerator[Device, None]: """Device fixture. @@ -462,21 +490,25 @@ async def dev(request) -> AsyncGenerator[Device, None]: username = request.config.getoption("--username") password = request.config.getoption("--password") if ip: - model = IP_MODEL_CACHE.get(ip) + fixture = IP_FIXTURE_CACHE.get(ip) + d = None - if not model: + if not fixture: d = await _discover_update_and_close(ip, username, password) - IP_MODEL_CACHE[ip] = model = d.model - - if model not in fixture_data.name: + IP_FIXTURE_CACHE[ip] = fixture = get_nearest_fixture_to_ip(d) + assert fixture + if fixture.name != fixture_data.name: pytest.skip(f"skipping file {fixture_data.name}") - dev = d if d else await _discover_update_and_close(ip, username, password) + dev = None + else: + dev = d if d else await _discover_update_and_close(ip, username, password) else: dev = await get_device_for_fixture(fixture_data) yield dev - await dev.disconnect() + if dev: + await dev.disconnect() def get_parent_and_child_modules(device: Device, module_name): diff --git a/kasa/tests/fixtureinfo.py b/kasa/tests/fixtureinfo.py index 9f4d39529..be01ea553 100644 --- a/kasa/tests/fixtureinfo.py +++ b/kasa/tests/fixtureinfo.py @@ -106,6 +106,7 @@ def filter_fixtures( model_filter: set[str] | None = None, component_filter: str | ComponentFilter | None = None, device_type_filter: Iterable[DeviceType] | None = None, + fixture_list: list[FixtureInfo] = FIXTURE_DATA, ): """Filter the fixtures based on supplied parameters. @@ -175,7 +176,7 @@ def _device_type_match(fixture_data: FixtureInfo, device_type): filtered = [] if protocol_filter is None: protocol_filter = {"IOT", "SMART"} - for fixture_data in FIXTURE_DATA: + for fixture_data in fixture_list: if data_root_filter and data_root_filter not in fixture_data.data: continue if fixture_data.protocol not in protocol_filter: @@ -191,8 +192,9 @@ def _device_type_match(fixture_data: FixtureInfo, device_type): filtered.append(fixture_data) - print(f"# {desc}") - for value in filtered: - print(f"\t{value.name}") + if desc: + print(f"# {desc}") + for value in filtered: + print(f"\t{value.name}") filtered.sort() return filtered diff --git a/kasa/tests/smart/modules/test_firmware.py b/kasa/tests/smart/modules/test_firmware.py index c10d90861..d29d6816b 100644 --- a/kasa/tests/smart/modules/test_firmware.py +++ b/kasa/tests/smart/modules/test_firmware.py @@ -73,6 +73,7 @@ async def test_update_available_without_cloud(dev: SmartDevice): pytest.param(False, pytest.raises(KasaException), id="not-available"), ], ) +@pytest.mark.requires_dummy() async def test_firmware_update( dev: SmartDevice, mocker: MockerFixture, diff --git a/kasa/tests/test_aestransport.py b/kasa/tests/test_aestransport.py index f1dbfb320..221de0df6 100644 --- a/kasa/tests/test_aestransport.py +++ b/kasa/tests/test_aestransport.py @@ -29,6 +29,8 @@ ) from ..httpclient import HttpClient +pytestmark = [pytest.mark.requires_dummy] + DUMMY_QUERY = {"foobar": {"foo": "bar", "bar": "foo"}} key = b"8\x89\x02\xfa\xf5Xs\x1c\xa1 H\x9a\x82\xc7\xd9\t" diff --git a/kasa/tests/test_cli.py b/kasa/tests/test_cli.py index 7a0b0ddee..d22bb1129 100644 --- a/kasa/tests/test_cli.py +++ b/kasa/tests/test_cli.py @@ -51,6 +51,10 @@ turn_on, ) +# The cli tests should be testing the cli logic rather than a physical device +# so mark the whole file for skipping with real devices. +pytestmark = [pytest.mark.requires_dummy] + @pytest.fixture() def runner(): diff --git a/kasa/tests/test_device_factory.py b/kasa/tests/test_device_factory.py index 35031cd0e..723569d1e 100644 --- a/kasa/tests/test_device_factory.py +++ b/kasa/tests/test_device_factory.py @@ -35,6 +35,8 @@ from .conftest import DISCOVERY_MOCK_IP +pytestmark = [pytest.mark.requires_dummy] + def _get_connection_type_device_class(discovery_info): if "result" in discovery_info: diff --git a/kasa/tests/test_discovery.py b/kasa/tests/test_discovery.py index 0318de35c..7f69977ed 100644 --- a/kasa/tests/test_discovery.py +++ b/kasa/tests/test_discovery.py @@ -53,6 +53,9 @@ wallswitch_iot, ) +# A physical device has to respond to discovery for the tests to work. +pytestmark = [pytest.mark.requires_dummy] + UNSUPPORTED = { "result": { "device_id": "xx", diff --git a/kasa/tests/test_klapprotocol.py b/kasa/tests/test_klapprotocol.py index ce370b5b6..18a10ace2 100644 --- a/kasa/tests/test_klapprotocol.py +++ b/kasa/tests/test_klapprotocol.py @@ -32,6 +32,8 @@ DUMMY_QUERY = {"foobar": {"foo": "bar", "bar": "foo"}} +pytestmark = [pytest.mark.requires_dummy] + class _mock_response: def __init__(self, status, content: bytes): diff --git a/kasa/tests/test_protocol.py b/kasa/tests/test_protocol.py index 9c15795f1..4235957be 100644 --- a/kasa/tests/test_protocol.py +++ b/kasa/tests/test_protocol.py @@ -687,10 +687,13 @@ def test_deprecated_protocol(): @device_iot async def test_iot_queries_redaction(dev: IotDevice, caplog: pytest.LogCaptureFixture): """Test query sensitive info redaction.""" - device_id = "123456789ABCDEF" - cast(FakeIotTransport, dev.protocol._transport).proto["system"]["get_sysinfo"][ - "deviceId" - ] = device_id + if isinstance(dev.protocol._transport, FakeIotTransport): + device_id = "123456789ABCDEF" + cast(FakeIotTransport, dev.protocol._transport).proto["system"]["get_sysinfo"][ + "deviceId" + ] = device_id + else: # real device with --ip + device_id = dev.sys_info["deviceId"] # Info no message logging caplog.set_level(logging.INFO) diff --git a/kasa/tests/test_smartdevice.py b/kasa/tests/test_smartdevice.py index d96542e5e..616db77e7 100644 --- a/kasa/tests/test_smartdevice.py +++ b/kasa/tests/test_smartdevice.py @@ -26,6 +26,7 @@ @device_smart +@pytest.mark.requires_dummy() async def test_try_get_response(dev: SmartDevice, caplog): mock_response: dict = { "get_device_info": SmartErrorCode.PARAMS_ERROR, @@ -37,6 +38,7 @@ async def test_try_get_response(dev: SmartDevice, caplog): @device_smart +@pytest.mark.requires_dummy() async def test_update_no_device_info(dev: SmartDevice, mocker: MockerFixture): mock_response: dict = { "get_device_usage": {}, diff --git a/kasa/tests/test_smartprotocol.py b/kasa/tests/test_smartprotocol.py index 420c10fc3..33ced4a9e 100644 --- a/kasa/tests/test_smartprotocol.py +++ b/kasa/tests/test_smartprotocol.py @@ -1,5 +1,4 @@ import logging -from typing import cast import pytest import pytest_mock @@ -420,10 +419,11 @@ async def test_smart_queries_redaction( dev: SmartDevice, caplog: pytest.LogCaptureFixture ): """Test query sensitive info redaction.""" - device_id = "123456789ABCDEF" - cast(FakeSmartTransport, dev.protocol._transport).info["get_device_info"][ - "device_id" - ] = device_id + if isinstance(dev.protocol._transport, FakeSmartTransport): + device_id = "123456789ABCDEF" + dev.protocol._transport.info["get_device_info"]["device_id"] = device_id + else: # real device + device_id = dev.device_id # Info no message logging caplog.set_level(logging.INFO) diff --git a/kasa/tests/test_sslaestransport.py b/kasa/tests/test_sslaestransport.py index bea10528b..428a0e41c 100644 --- a/kasa/tests/test_sslaestransport.py +++ b/kasa/tests/test_sslaestransport.py @@ -24,6 +24,8 @@ from ..experimental.sslaestransport import SslAesTransport, TransportState, _sha256_hash from ..httpclient import HttpClient +pytestmark = [pytest.mark.requires_dummy] + MOCK_ADMIN_USER = get_default_credentials(DEFAULT_CREDENTIALS["TAPOCAMERA"]).username MOCK_PWD = "correct_pwd" # noqa: S105 MOCK_USER = "mock@example.com" From 42a89802f9ed9a2433a165638e53e8bd9e1b27e7 Mon Sep 17 00:00:00 2001 From: Steven B <51370195+sdb9696@users.noreply.github.com> Date: Mon, 11 Nov 2024 15:02:58 +0000 Subject: [PATCH 2/8] Fix bulb tests --- kasa/device.py | 5 +++++ kasa/iot/iotdevice.py | 6 ++++++ kasa/smart/smartdevice.py | 11 +++++++++++ tests/device_fixtures.py | 11 ++++++++--- tests/fixtureinfo.py | 10 +++++++++- tests/test_bulb.py | 2 +- 6 files changed, 40 insertions(+), 5 deletions(-) diff --git a/kasa/device.py b/kasa/device.py index 72c567175..b4e6c490b 100644 --- a/kasa/device.py +++ b/kasa/device.py @@ -320,6 +320,11 @@ def config(self) -> DeviceConfig: def model(self) -> str: """Returns the device model.""" + @property + @abstractmethod + def model_region(self) -> str: + """Return device full model name and region.""" + @property @abstractmethod def alias(self) -> str | None: diff --git a/kasa/iot/iotdevice.py b/kasa/iot/iotdevice.py index 4ee403dba..913b6c1d9 100755 --- a/kasa/iot/iotdevice.py +++ b/kasa/iot/iotdevice.py @@ -455,6 +455,12 @@ def model(self) -> str: sys_info = self._sys_info return str(sys_info["model"]) + @property + @requires_update + def model_region(self) -> str: + """Return device full model name and region.""" + return self.model + @property # type: ignore def alias(self) -> str | None: """Return device name (alias).""" diff --git a/kasa/smart/smartdevice.py b/kasa/smart/smartdevice.py index 35524ee8c..7aac74ad0 100644 --- a/kasa/smart/smartdevice.py +++ b/kasa/smart/smartdevice.py @@ -492,6 +492,17 @@ def model(self) -> str: """Returns the device model.""" return str(self._info.get("model")) + @property + def model_region(self) -> str: + """Return device full model name and region.""" + if (disco := self._discovery_info) and ( + disco_model := disco.get("device_model") + ): + return disco_model + # Some devices have the region in the specs element. + region = f"({specs})" if (specs := self._info.get("specs")) else "" + return f"{self.model}{region}" + @property def alias(self) -> str | None: """Returns the device alias or nickname.""" diff --git a/tests/device_fixtures.py b/tests/device_fixtures.py index b6f8c604b..06ddf724e 100644 --- a/tests/device_fixtures.py +++ b/tests/device_fixtures.py @@ -457,14 +457,19 @@ def get_nearest_fixture_to_ip(dev): protocol_fixtures = filter_fixtures("", protocol_filter={"IOT"}) assert protocol_fixtures, "Unknown device type" - # Could try an exact match here but would be easier if region was available - # on the device + # This will get the best fixture with a match on model region + if model_region_fixtures := filter_fixtures( + "", model_filter={dev.model_region}, fixture_list=protocol_fixtures + ): + return next(iter(model_region_fixtures)) + + # This will get the best fixture based on model starting with the name. if "(" in dev.model: model, _, _ = dev.model.partition("(") else: model = dev.model if model_fixtures := filter_fixtures( - "", model_filter={model}, fixture_list=protocol_fixtures + "", model_startswith_filter=model, fixture_list=protocol_fixtures ): return next(iter(model_fixtures)) diff --git a/tests/fixtureinfo.py b/tests/fixtureinfo.py index be01ea553..cb75b4232 100644 --- a/tests/fixtureinfo.py +++ b/tests/fixtureinfo.py @@ -104,6 +104,7 @@ def filter_fixtures( data_root_filter: str | None = None, protocol_filter: set[str] | None = None, model_filter: set[str] | None = None, + model_startswith_filter: str | None = None, component_filter: str | ComponentFilter | None = None, device_type_filter: Iterable[DeviceType] | None = None, fixture_list: list[FixtureInfo] = FIXTURE_DATA, @@ -128,12 +129,15 @@ def _model_match(fixture_data: FixtureInfo, model_filter: set[str]): and (model := model_filter_list[0]) and len(model.split("_")) == 3 ): - # return exact match + # filter string includes hw and fw, return exact match return fixture_data.name == f"{model}.json" file_model_region = fixture_data.name.split("_")[0] file_model = file_model_region.split("(")[0] return file_model in model_filter + def _model_startswith_match(fixture_data: FixtureInfo, starts_with: str): + return fixture_data.name.startswith(starts_with) + def _component_match( fixture_data: FixtureInfo, component_filter: str | ComponentFilter ): @@ -183,6 +187,10 @@ def _device_type_match(fixture_data: FixtureInfo, device_type): continue if model_filter is not None and not _model_match(fixture_data, model_filter): continue + if model_startswith_filter is not None and not _model_startswith_match( + fixture_data, model_startswith_filter + ): + continue if component_filter and not _component_match(fixture_data, component_filter): continue if device_type_filter and not _device_type_match( diff --git a/tests/test_bulb.py b/tests/test_bulb.py index 9e6dd7c2f..64c012fd7 100644 --- a/tests/test_bulb.py +++ b/tests/test_bulb.py @@ -32,7 +32,7 @@ from .test_iotdevice import SYSINFO_SCHEMA -@bulb +@bulb_iot async def test_bulb_sysinfo(dev: Device): assert dev.sys_info is not None SYSINFO_SCHEMA_BULB(dev.sys_info) From 81cd8aaa7d79f65f8bd1c133c90d00cfad425bf0 Mon Sep 17 00:00:00 2001 From: Steven B <51370195+sdb9696@users.noreply.github.com> Date: Mon, 11 Nov 2024 15:07:54 +0000 Subject: [PATCH 3/8] Enable getting username and password from environment vars --- tests/device_fixtures.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/device_fixtures.py b/tests/device_fixtures.py index 06ddf724e..1e00d3dc9 100644 --- a/tests/device_fixtures.py +++ b/tests/device_fixtures.py @@ -1,5 +1,6 @@ from __future__ import annotations +import os from collections.abc import AsyncGenerator import pytest @@ -492,8 +493,8 @@ async def dev(request) -> AsyncGenerator[Device, None]: dev: Device ip = request.config.getoption("--ip") - username = request.config.getoption("--username") - password = request.config.getoption("--password") + username = request.config.getoption("--username") or os.environ.get("KASA_USERNAME") + password = request.config.getoption("--password") or os.environ.get("KASA_PASSWORD") if ip: fixture = IP_FIXTURE_CACHE.get(ip) From 291121d59756e9caf5747407074c89bbaf2b9b22 Mon Sep 17 00:00:00 2001 From: Steven B <51370195+sdb9696@users.noreply.github.com> Date: Mon, 11 Nov 2024 15:23:16 +0000 Subject: [PATCH 4/8] Exclude test_child_time from physical device tests --- tests/test_childdevice.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/test_childdevice.py b/tests/test_childdevice.py index 797e8dff5..05743abb5 100644 --- a/tests/test_childdevice.py +++ b/tests/test_childdevice.py @@ -125,8 +125,13 @@ async def test_parent_property(dev: Device): @has_children_smart +@pytest.mark.requires_dummy() async def test_child_time(dev: Device, freezer: FrozenDateTimeFactory): - """Test a child device gets the time from it's parent module.""" + """Test a child device gets the time from it's parent module. + + This is excluded from real device testing as the test often fail if the + device time is not in the past. + """ if not dev.children: pytest.skip(f"Device {dev} fixture does not have any children") From 05bac8c3c7356abc1e9af564307a0778eb2d7a0a Mon Sep 17 00:00:00 2001 From: Steven B <51370195+sdb9696@users.noreply.github.com> Date: Mon, 11 Nov 2024 16:52:17 +0000 Subject: [PATCH 5/8] Revert time test back to original time --- tests/test_common_modules.py | 47 +++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/tests/test_common_modules.py b/tests/test_common_modules.py index 5e2622b9b..e2e2bf137 100644 --- a/tests/test_common_modules.py +++ b/tests/test_common_modules.py @@ -1,7 +1,6 @@ from datetime import datetime import pytest -from freezegun.api import FrozenDateTimeFactory from pytest_mock import MockerFixture from zoneinfo import ZoneInfo @@ -326,22 +325,36 @@ async def test_light_preset_save(dev: Device, mocker: MockerFixture): assert new_preset_state.color_temp == new_preset.color_temp -async def test_set_time(dev: Device, freezer: FrozenDateTimeFactory): +async def test_set_time(dev: Device): """Test setting the device time.""" - freezer.move_to("2021-01-09 12:00:00+00:00") time_mod = dev.modules[Module.Time] - tz_info = time_mod.timezone - now = datetime.now(tz=tz_info) - now = now.replace(microsecond=0) - assert time_mod.time != now - await time_mod.set_time(now) - await dev.update() - assert time_mod.time == now - - zone = ZoneInfo("Europe/Berlin") - now = datetime.now(tz=zone) - now = now.replace(microsecond=0) - await time_mod.set_time(now) - await dev.update() - assert time_mod.time == now + original_time = time_mod.time + original_timezone = time_mod.timezone + + test_time = datetime.fromisoformat("2021-01-09 12:00:00+00:00") + test_time = test_time.astimezone(original_timezone) + + try: + assert time_mod.time != test_time + + await time_mod.set_time(test_time) + await dev.update() + assert time_mod.time == test_time + + assert isinstance(original_timezone, ZoneInfo) + if original_timezone.key != "Europe/Berlin": + test_zonezone = ZoneInfo("Europe/Berlin") + else: + test_zonezone = ZoneInfo("Europe/London") + + # Just update the timezone + new_time = time_mod.time.astimezone(test_zonezone) + await time_mod.set_time(new_time) + await dev.update() + assert time_mod.time == new_time + finally: + # Reset back to the original + await time_mod.set_time(original_time) + await dev.update() + assert time_mod.time == original_time From 7c305a49be479b57cfae09c6e461f46303b6bb0c Mon Sep 17 00:00:00 2001 From: Steven B <51370195+sdb9696@users.noreply.github.com> Date: Mon, 11 Nov 2024 17:17:55 +0000 Subject: [PATCH 6/8] Fix tests --- tests/test_common_modules.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/test_common_modules.py b/tests/test_common_modules.py index e2e2bf137..168b4090f 100644 --- a/tests/test_common_modules.py +++ b/tests/test_common_modules.py @@ -342,8 +342,10 @@ async def test_set_time(dev: Device): await dev.update() assert time_mod.time == test_time - assert isinstance(original_timezone, ZoneInfo) - if original_timezone.key != "Europe/Berlin": + if ( + isinstance(original_timezone, ZoneInfo) + and original_timezone.key != "Europe/Berlin" + ): test_zonezone = ZoneInfo("Europe/Berlin") else: test_zonezone = ZoneInfo("Europe/London") From 3c168a9f012fb2df275e084ddf43e70a4a42e8fe Mon Sep 17 00:00:00 2001 From: Steven B <51370195+sdb9696@users.noreply.github.com> Date: Mon, 11 Nov 2024 17:18:53 +0000 Subject: [PATCH 7/8] Make model-region private --- kasa/device.py | 2 +- kasa/iot/iotdevice.py | 2 +- kasa/smart/smartdevice.py | 2 +- tests/device_fixtures.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/kasa/device.py b/kasa/device.py index b4e6c490b..ca16bb6bf 100644 --- a/kasa/device.py +++ b/kasa/device.py @@ -322,7 +322,7 @@ def model(self) -> str: @property @abstractmethod - def model_region(self) -> str: + def _model_region(self) -> str: """Return device full model name and region.""" @property diff --git a/kasa/iot/iotdevice.py b/kasa/iot/iotdevice.py index 913b6c1d9..20284c1d8 100755 --- a/kasa/iot/iotdevice.py +++ b/kasa/iot/iotdevice.py @@ -457,7 +457,7 @@ def model(self) -> str: @property @requires_update - def model_region(self) -> str: + def _model_region(self) -> str: """Return device full model name and region.""" return self.model diff --git a/kasa/smart/smartdevice.py b/kasa/smart/smartdevice.py index 7aac74ad0..e497b8e8c 100644 --- a/kasa/smart/smartdevice.py +++ b/kasa/smart/smartdevice.py @@ -493,7 +493,7 @@ def model(self) -> str: return str(self._info.get("model")) @property - def model_region(self) -> str: + def _model_region(self) -> str: """Return device full model name and region.""" if (disco := self._discovery_info) and ( disco_model := disco.get("device_model") diff --git a/tests/device_fixtures.py b/tests/device_fixtures.py index 1e00d3dc9..4d335d5c5 100644 --- a/tests/device_fixtures.py +++ b/tests/device_fixtures.py @@ -460,7 +460,7 @@ def get_nearest_fixture_to_ip(dev): # This will get the best fixture with a match on model region if model_region_fixtures := filter_fixtures( - "", model_filter={dev.model_region}, fixture_list=protocol_fixtures + "", model_filter={dev._model_region}, fixture_list=protocol_fixtures ): return next(iter(model_region_fixtures)) From 420f428445ed71b699e113152bad363af1bb154f Mon Sep 17 00:00:00 2001 From: Steven B <51370195+sdb9696@users.noreply.github.com> Date: Mon, 11 Nov 2024 17:33:42 +0000 Subject: [PATCH 8/8] Add reasons to requires_dummy marks --- tests/test_device_factory.py | 2 ++ tests/test_klapprotocol.py | 1 + tests/test_sslaestransport.py | 1 + 3 files changed, 4 insertions(+) diff --git a/tests/test_device_factory.py b/tests/test_device_factory.py index 723569d1e..8690e5802 100644 --- a/tests/test_device_factory.py +++ b/tests/test_device_factory.py @@ -35,6 +35,8 @@ from .conftest import DISCOVERY_MOCK_IP +# Device Factory tests are not relevant for real devices which run against +# a single device that has already been created via the factory. pytestmark = [pytest.mark.requires_dummy] diff --git a/tests/test_klapprotocol.py b/tests/test_klapprotocol.py index 57990c2af..524a6be3e 100644 --- a/tests/test_klapprotocol.py +++ b/tests/test_klapprotocol.py @@ -32,6 +32,7 @@ DUMMY_QUERY = {"foobar": {"foo": "bar", "bar": "foo"}} +# Transport tests are not designed for real devices pytestmark = [pytest.mark.requires_dummy] diff --git a/tests/test_sslaestransport.py b/tests/test_sslaestransport.py index 20d83bc07..49605d372 100644 --- a/tests/test_sslaestransport.py +++ b/tests/test_sslaestransport.py @@ -27,6 +27,7 @@ from kasa.httpclient import HttpClient from kasa.protocol import DEFAULT_CREDENTIALS, get_default_credentials +# Transport tests are not designed for real devices pytestmark = [pytest.mark.requires_dummy] MOCK_ADMIN_USER = get_default_credentials(DEFAULT_CREDENTIALS["TAPOCAMERA"]).username