From 1fb15948bd57324e63abd7697e54e2911a20150a Mon Sep 17 00:00:00 2001 From: David Bonnes Date: Sat, 2 Nov 2024 17:55:38 +0000 Subject: [PATCH] clean up test handlers --- tests/tests/conftest.py | 6 ++-- tests/tests_rf/conftest.py | 50 ++++++++++++++++++++++++++++---- tests/tests_rf/test_token_mgr.py | 6 ++-- tests/tests_rf/test_v1_apis.py | 3 +- tests/tests_rf/test_v1_xxxx.py | 4 ++- tests/tests_rf/test_v2_apis.py | 6 +++- tests/tests_rf/test_v2_task.py | 3 +- tests/tests_rf/test_v2_urls.py | 8 ++++- 8 files changed, 70 insertions(+), 16 deletions(-) diff --git a/tests/tests/conftest.py b/tests/tests/conftest.py index 73433834..d4d19d4a 100644 --- a/tests/tests/conftest.py +++ b/tests/tests/conftest.py @@ -31,8 +31,8 @@ # used to construct the default token cache -DEFAULT_USERNAME: Final[str] = "username@email.com" -DEFAULT_PASSWORD: Final[str] = "P@ssw0rd!!" # noqa: S105 +TEST_USERNAME: Final[str] = "username@email.com" +TEST_PASSWORD: Final[str] = "P@ssw0rd!!" # noqa: S105 class ClientStub: @@ -136,7 +136,7 @@ async def client_session() -> AsyncGenerator[aiohttp.ClientSession, None]: def credentials() -> tuple[str, str]: """Return a username and a password.""" - return DEFAULT_USERNAME, DEFAULT_PASSWORD + return TEST_USERNAME, TEST_PASSWORD @pytest.fixture # @pytest_asyncio.fixture(scope="session", loop_scope="session") diff --git a/tests/tests_rf/conftest.py b/tests/tests_rf/conftest.py index 8f8f07d3..84944ee3 100644 --- a/tests/tests_rf/conftest.py +++ b/tests/tests_rf/conftest.py @@ -3,6 +3,7 @@ from __future__ import annotations +import functools import json import os from collections.abc import AsyncGenerator @@ -20,15 +21,46 @@ # # normally, we want debug flags to be False -_DBG_USE_REAL_AIOHTTP = True +_DBG_USE_REAL_AIOHTTP = False _DBG_DISABLE_STRICT_ASSERTS = False # of response content-type, schema if TYPE_CHECKING: import aiohttp # used to construct the default token cache -DEFAULT_USERNAME: Final[str] = "username@email.com" -DEFAULT_PASSWORD: Final[str] = "P@ssw0rd!!" # noqa: S105 +TEST_USERNAME: Final[str] = "username@email.com" +TEST_PASSWORD: Final[str] = "P@ssw0rd!!" # noqa: S105 + + +# Global flag to indicate if AuthenticationFailedError has been encountered +global_auth_failed = False + + +def skipif_auth_failed(fnc): + """Decorator to skip tests if AuthenticationFailedError is encountered.""" + + @functools.wraps(fnc) + async def wrapper(*args, **kwargs): + global global_auth_failed + + if global_auth_failed: + pytest.skip("Unable to authenticate") + + try: + result = await fnc(*args, **kwargs) + return result + + except ( + evo1.AuthenticationFailedError, + evo2.AuthenticationFailedError, + ) as err: + if not _DBG_USE_REAL_AIOHTTP: + raise + + global_auth_failed = True + pytest.fail(f"Unable to authenticate: {err}") + + return wrapper @pytest.fixture(autouse=True) @@ -69,8 +101,8 @@ async def client_session() -> AsyncGenerator[aiohttp.ClientSession, None]: def credentials() -> tuple[str, str]: """Return a username and a password.""" - username: str = os.getenv("TEST_USERNAME") or DEFAULT_USERNAME - password: str = os.getenv("TEST_PASSWORD") or DEFAULT_PASSWORD + username: str = os.getenv("TEST_USERNAME") or TEST_USERNAME + password: str = os.getenv("TEST_PASSWORD") or TEST_PASSWORD return username, password @@ -134,6 +166,8 @@ async def evohome_v1( ) -> AsyncGenerator[evo1.EvohomeClient, None]: """Yield an instance of a v1 EvohomeClient.""" + global skipif_auth_failed + evo = evo1.EvohomeClient(*credentials, websession=client_session) try: @@ -142,6 +176,8 @@ async def evohome_v1( except evo1.AuthenticationFailedError as err: if not _DBG_USE_REAL_AIOHTTP: raise + + skipif_auth_failed = True pytest.skip(f"Unable to authenticate: {err}") @@ -151,6 +187,8 @@ async def evohome_v2( ) -> AsyncGenerator[evo2.EvohomeClientNew, None]: """Yield an instance of a v2 EvohomeClient.""" + global skipif_auth_failed + evo = evo2.EvohomeClientNew(token_manager) try: @@ -159,4 +197,6 @@ async def evohome_v2( except evo2.AuthenticationFailedError as err: if not _DBG_USE_REAL_AIOHTTP: raise + + skipif_auth_failed = True pytest.skip(f"Unable to authenticate: {err}") diff --git a/tests/tests_rf/test_token_mgr.py b/tests/tests_rf/test_token_mgr.py index acfc197e..b907d62b 100644 --- a/tests/tests_rf/test_token_mgr.py +++ b/tests/tests_rf/test_token_mgr.py @@ -18,7 +18,7 @@ from evohomeasync2 import exceptions as exc from evohomeasync2.client import TokenManager -from .conftest import DEFAULT_PASSWORD, DEFAULT_USERNAME +from .conftest import TEST_PASSWORD, TEST_USERNAME if TYPE_CHECKING: from datetime import datetime as dt @@ -47,8 +47,8 @@ def post_side_effect(*args: Any, **kwargs: Any) -> Any: # else: data["grant_type"] == "password"... if ( - data.get("Username") != DEFAULT_USERNAME - or data.get("Password") != DEFAULT_PASSWORD + data.get("Username") != TEST_USERNAME + or data.get("Password") != TEST_PASSWORD ): raise aiohttp.ClientResponseError(None, (), status=HTTPStatus.BAD_REQUEST) diff --git a/tests/tests_rf/test_v1_apis.py b/tests/tests_rf/test_v1_apis.py index 36a0ef69..56eb0bb1 100644 --- a/tests/tests_rf/test_v1_apis.py +++ b/tests/tests_rf/test_v1_apis.py @@ -7,7 +7,7 @@ import evohomeasync as evo1 -from .conftest import _DBG_USE_REAL_AIOHTTP +from .conftest import _DBG_USE_REAL_AIOHTTP, skipif_auth_failed async def _test_client_apis(evo: evo1.EvohomeClient) -> None: @@ -29,6 +29,7 @@ async def _test_client_apis(evo: evo1.EvohomeClient) -> None: # _LOGGER.warning("get_temperatures() OK") +@skipif_auth_failed async def test_client_apis(evohome_v1: evo1.EvohomeClient) -> None: """Test _populate_user_data() & _populate_full_data()""" diff --git a/tests/tests_rf/test_v1_xxxx.py b/tests/tests_rf/test_v1_xxxx.py index 5f6b3be1..b8b358d9 100644 --- a/tests/tests_rf/test_v1_xxxx.py +++ b/tests/tests_rf/test_v1_xxxx.py @@ -9,7 +9,7 @@ import evohomeasync as evo1 -from .conftest import _DBG_USE_REAL_AIOHTTP +from .conftest import _DBG_USE_REAL_AIOHTTP, skipif_auth_failed from .helpers import should_fail_v1, should_work_v1 @@ -58,6 +58,7 @@ async def _test_client_apis(evo: evo1.EvohomeClient) -> None: assert temps +@skipif_auth_failed async def test_locations(evohome_v1: evo1.EvohomeClient) -> None: """Test /locations""" @@ -67,6 +68,7 @@ async def test_locations(evohome_v1: evo1.EvohomeClient) -> None: await _test_url_locations(evohome_v1) +@skipif_auth_failed async def test_client_apis(evohome_v1: evo1.EvohomeClient) -> None: """Test _populate_user_data() & _populate_full_data()""" diff --git a/tests/tests_rf/test_v2_apis.py b/tests/tests_rf/test_v2_apis.py index 7eb130fc..61bc6f45 100644 --- a/tests/tests_rf/test_v2_apis.py +++ b/tests/tests_rf/test_v2_apis.py @@ -20,7 +20,7 @@ from evohomeasync2.zone import Zone from . import faked_server as faked -from .conftest import _DBG_USE_REAL_AIOHTTP +from .conftest import _DBG_USE_REAL_AIOHTTP, skipif_auth_failed ####################################################################################### @@ -114,21 +114,25 @@ async def _test_system_apis(evo: evo2.EvohomeClientNew) -> None: ####################################################################################### +@skipif_auth_failed async def test_basics(evohome_v2: evo2.EvohomeClientNew) -> None: """Test authentication, `user_account()` and `installation()`.""" await _test_basics_apis(evohome_v2) +@skipif_auth_failed async def _test_sched_(evohome_v2: evo2.EvohomeClientNew) -> None: """Test `get_schedule()` and `get_schedule()`.""" await _test_sched__apis(evohome_v2) +@skipif_auth_failed async def test_status(evohome_v2: evo2.EvohomeClientNew) -> None: """Test `_update()` for DHW/zone.""" await _test_update_apis(evohome_v2) +@skipif_auth_failed async def test_system(evohome_v2: evo2.EvohomeClientNew) -> None: """Test `set_mode()` for TCS""" diff --git a/tests/tests_rf/test_v2_task.py b/tests/tests_rf/test_v2_task.py index 080d6ce1..23a4d83e 100644 --- a/tests/tests_rf/test_v2_task.py +++ b/tests/tests_rf/test_v2_task.py @@ -20,7 +20,7 @@ ) from evohomeasync2.schema.helpers import pascal_case -from .conftest import _DBG_USE_REAL_AIOHTTP +from .conftest import _DBG_USE_REAL_AIOHTTP, skipif_auth_failed from .helpers import should_fail, should_work ####################################################################################### @@ -186,6 +186,7 @@ async def _test_task_id(evo: evo2.EvohomeClientNew) -> None: ####################################################################################### +@skipif_auth_failed async def test_task_id(evohome_v2: evo2.EvohomeClientNew) -> None: """Test /location/{loc.id}/status""" diff --git a/tests/tests_rf/test_v2_urls.py b/tests/tests_rf/test_v2_urls.py index 86fc26ca..9ea0fb92 100644 --- a/tests/tests_rf/test_v2_urls.py +++ b/tests/tests_rf/test_v2_urls.py @@ -35,7 +35,7 @@ from evohomeasync2.schema.schedule import convert_to_put_schedule from . import faked_server as faked -from .conftest import _DBG_USE_REAL_AIOHTTP +from .conftest import _DBG_USE_REAL_AIOHTTP, skipif_auth_failed from .helpers import should_fail, should_work if TYPE_CHECKING: @@ -302,6 +302,7 @@ async def _test_schedule(evo: evo2.EvohomeClientNew) -> None: ####################################################################################### +@skipif_auth_failed async def test_usr_account(evohome_v2: evo2.EvohomeClientNew) -> None: """Test /userAccount""" @@ -314,18 +315,21 @@ async def test_usr_account(evohome_v2: evo2.EvohomeClientNew) -> None: pytest.skip("Unable to authenticate") +@skipif_auth_failed async def test_all_config(evohome_v2: evo2.EvohomeClientNew) -> None: """Test /location/installationInfo""" await _test_all_config(evohome_v2) +@skipif_auth_failed async def test_loc_status(evohome_v2: evo2.EvohomeClientNew) -> None: """Test /location/{loc.id}/status""" await _test_loc_status(evohome_v2) +@skipif_auth_failed async def test_tcs_mode(evohome_v2: evo2.EvohomeClientNew) -> None: """Test /temperatureControlSystem/{tcs.id}/mode""" @@ -338,6 +342,7 @@ async def test_tcs_mode(evohome_v2: evo2.EvohomeClientNew) -> None: pytest.skip("Mocked server API not implemented") +@skipif_auth_failed async def test_zone_mode(evohome_v2: evo2.EvohomeClientNew) -> None: """Test /temperatureZone/{zone.id}/heatSetpoint""" @@ -350,6 +355,7 @@ async def test_zone_mode(evohome_v2: evo2.EvohomeClientNew) -> None: pytest.skip("Mocked server API not implemented") +@skipif_auth_failed async def test_schedule(evohome_v2: evo2.EvohomeClientNew) -> None: """Test /{x.TYPE}/{x.id}/schedule"""