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

tidy tests #264

Merged
merged 6 commits into from
Apr 21, 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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import pytest

from wakepy import Method
from tests.unit.test_core.testmethods import TestMethod
from wakepy.core.strenum import StrEnum

if sys.version_info < (3, 8): # pragma: no-cover-if-py-gte-38
Expand All @@ -12,11 +12,6 @@
import typing


class TestMethod(Method):
__test__ = False # for pytest
mode = "_test"


@pytest.fixture
def method1():
return TestMethod()
Expand Down
15 changes: 5 additions & 10 deletions tests/unit/test_core/conftest.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,9 @@
import pytest

from tests.unit.test_core.testmethods import TestMethod
from wakepy.core import DBusAddress, DBusMethod, Method, PlatformName
from wakepy.core.heartbeat import Heartbeat

# B, D, E
FIRST_MODE = "first_mode"
# A, F
SECOND_MODE = "second_mode"


class TestMethod(Method):
__test__ = False # for pytest
mode = "_test"


@pytest.fixture
def heartbeat1(method1: Method):
Expand Down Expand Up @@ -71,6 +62,10 @@ class MultiPlatformA(TestMethod):
@pytest.fixture(scope="function")
def provide_methods_a_f(monkeypatch, testutils):
testutils.empty_method_registry(monkeypatch)
# B, D, E
FIRST_MODE = "first_mode"
# A, F
SECOND_MODE = "second_mode"

class MethodA(TestMethod):
name = "A"
Expand Down
26 changes: 12 additions & 14 deletions tests/unit/test_core/test_method/test_activation.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
METHOD_MISSING,
METHOD_OPTIONS,
WakepyMethodTestError,
combinations_of_test_methods,
get_test_method_class,
iterate_test_methods,
)
from wakepy.core import Method, MethodActivationResult, PlatformName, get_methods
from wakepy.core.constants import StageName, StageNameValue
Expand Down Expand Up @@ -67,7 +67,7 @@ def test_activate_method_method_without_platform_support(self):

def test_activate_method_method_caniuse_fails(self):
# Case 1: Fail by returning False from caniuse
method = get_test_method_class(caniuse=False, enter_mode=True, exit_mode=True)()
method = get_test_method_class(caniuse=False)()
res, heartbeat = activate_method(method)
assert res.success is False
assert res.failure_stage == StageName.REQUIREMENTS
Expand All @@ -77,8 +77,6 @@ def test_activate_method_method_caniuse_fails(self):
# Case 2: Fail by returning some error reason from caniuse
method = get_test_method_class(
caniuse="SomeSW version <2.1.5 not supported",
enter_mode=True,
exit_mode=True,
)()
res, heartbeat = activate_method(method)
assert res.success is False
Expand Down Expand Up @@ -145,7 +143,7 @@ def test_enter_mode_failing(self):
"""Tests 1) F* from TABLE 1; enter_mode failing"""

# Case: enter_mode raises exception
for method in iterate_test_methods(
for method in combinations_of_test_methods(
enter_mode=[RuntimeError(FAILURE_REASON)],
heartbeat=METHOD_OPTIONS,
exit_mode=METHOD_OPTIONS,
Expand All @@ -161,7 +159,7 @@ def test_enter_mode_failing(self):

def test_enter_mode_missing_and_heartbeat(self):
"""Tests 2) MM from TABLE 1; missing both enter_mode and heartbeat"""
for method in iterate_test_methods(
for method in combinations_of_test_methods(
enter_mode=[METHOD_MISSING],
heartbeat=[METHOD_MISSING],
exit_mode=METHOD_OPTIONS,
Expand All @@ -182,7 +180,7 @@ def test_enter_mode_missing_and_heartbeat(self):
def test_enter_mode_missing_heartbeat_failing(self):
"""Tests 3) MF from TABLE 1; enter_mode missing and heartbeat
failing"""
for method in iterate_test_methods(
for method in combinations_of_test_methods(
enter_mode=[METHOD_MISSING],
heartbeat=[False],
exit_mode=METHOD_OPTIONS,
Expand All @@ -197,7 +195,7 @@ def test_enter_mode_missing_heartbeat_failing(self):
assert "The only accepted return value is None" in err_message
assert heartbeat_call_time is None

for method in iterate_test_methods(
for method in combinations_of_test_methods(
enter_mode=[METHOD_MISSING],
heartbeat=[FAILURE_REASON],
exit_mode=METHOD_OPTIONS,
Expand All @@ -218,7 +216,7 @@ def test_enter_mode_missing_heartbeat_success(self):
expected_time = dt.datetime.strptime(
"2023-12-21 16:17:00", "%Y-%m-%d %H:%M:%S"
).replace(tzinfo=dt.timezone.utc)
for method in iterate_test_methods(
for method in combinations_of_test_methods(
enter_mode=[METHOD_MISSING],
heartbeat=[None],
exit_mode=METHOD_OPTIONS,
Expand All @@ -230,7 +228,7 @@ def test_enter_mode_missing_heartbeat_success(self):
def test_enter_mode_success_hearbeat_missing(self):
"""Tests 5) SM from TABLE 1; enter_mode success, heartbeat missing"""

for method in iterate_test_methods(
for method in combinations_of_test_methods(
enter_mode=[None],
heartbeat=[METHOD_MISSING],
exit_mode=METHOD_OPTIONS,
Expand All @@ -248,7 +246,7 @@ def test_enter_mode_success_heartbeat_failing(self):
"""

# Case: Heartbeate fails by raising RuntimeError
for method in iterate_test_methods(
for method in combinations_of_test_methods(
enter_mode=[None],
heartbeat=[RuntimeError(FAILURE_REASON)],
exit_mode=[None, METHOD_MISSING],
Expand All @@ -261,7 +259,7 @@ def test_enter_mode_success_heartbeat_failing(self):
# Case: The heartbeat fails, and because enter_mode() has succeed,
# wakepy tries to call exit_mode(). If that fails, the program must
# crash, as we are in an unknown state and this is clearly an error.
for method in iterate_test_methods(
for method in combinations_of_test_methods(
enter_mode=[None],
heartbeat=[False, FAILURE_REASON],
exit_mode=[False, FAILURE_REASON],
Expand All @@ -278,7 +276,7 @@ def test_enter_mode_success_heartbeat_failing(self):
# Case: Same as the one above, but this time exit_mode() raises a
# WakepyMethodTestError. That is re-raised as RuntimeError, instead.
# If this happens, the Method.exit_mode() has a bug.
for method in iterate_test_methods(
for method in combinations_of_test_methods(
enter_mode=[None],
heartbeat=[False, FAILURE_REASON],
exit_mode=[WakepyMethodTestError("foo")],
Expand All @@ -298,7 +296,7 @@ def test_enter_mode_success_heartbeat_success(self):
"2023-12-21 16:17:00", "%Y-%m-%d %H:%M:%S"
).replace(tzinfo=dt.timezone.utc)

for method in iterate_test_methods(
for method in combinations_of_test_methods(
enter_mode=[None],
heartbeat=[None],
exit_mode=METHOD_OPTIONS,
Expand Down
6 changes: 1 addition & 5 deletions tests/unit/test_core/test_method/test_method.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import pytest

from tests.unit.test_core.testmethods import TestMethod
from wakepy.core import DBusMethodCall
from wakepy.core.method import (
Method,
Expand All @@ -25,11 +26,6 @@
from wakepy.core import DBusMethod


class TestMethod(Method):
__test__ = False # for pytest
mode = "_test"


def test_overridden_methods_autodiscovery():
"""The enter_mode, heartbeat and exit_mode methods by default do nothing
(on the Method base class). In subclasses, these are usually overriden.
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/test_core/test_mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ def test_truthy_values(self, val):
assert should_fake_success(val) is True


class TestActivateMode:
class TestActivateOneOfMethods:
"""tests for Mode._activate_one_of_methods"""

def test_activate_without_methods(self):
Expand Down
6 changes: 1 addition & 5 deletions tests/unit/test_core/test_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,11 @@

import pytest

from tests.unit.test_core.testmethods import TestMethod
from wakepy.core import Method, get_method, get_methods, get_methods_for_mode
from wakepy.core.registry import register_method


class TestMethod(Method):
__test__ = False # for pytest
mode = "_test"


@pytest.mark.usefixtures("empty_method_registry")
def test_get_method_which_is_not_yet_defined():
# The method registry is empty so there is no Methods with the name
Expand Down
60 changes: 42 additions & 18 deletions tests/unit/test_core/testmethods.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,37 @@
"""This module defines two important helpers for the tests

1) get_test_method_class
A function which may used to create wakepy.Method classes using arguments.

Example
-------
Create Method which return True from Method.caniuse() and raises a
RuntimeError in Method.enter_mode()

>>> method_cls = get_test_method_class(
caniuse=True, enter_mode=RuntimeError("failed")
)

2) combinations_of_test_methods
A function which returns an iterator for testing a cross product of different
Methods. This uses get_test_method_class underneath.

Example
-------
>>> METHOD_OPTIONS = [
METHOD_MISSING,
True,
False,
RunTimeError('foo'),
]
>>> for method in combinations_of_test_methods(
enter_mode=[METHOD_MISSING],
heartbeat=[METHOD_MISSING],
exit_mode=METHOD_OPTIONS,
):
# test
"""

from __future__ import annotations

import itertools
Expand All @@ -8,6 +42,11 @@
from wakepy.core.method import Method


class TestMethod(Method):
__test__ = False # for pytest; this won't be interpreted as test class.
mode = "_test"


class WakepyMethodTestError(Exception): ...


Expand Down Expand Up @@ -105,31 +144,16 @@ def _create_class() -> Type[Method]:
return _test_method_classes[key]


def iterate_test_methods(
def combinations_of_test_methods(
enter_mode=Iterable,
heartbeat=Iterable,
exit_mode=Iterable,
) -> Iterable[Method]:
"""Create an iterator of Methods over the combinations of the given
enter_mode, heartbeat and exit_mode"""
for enter_mode_, heartbeat_, exit_mode_ in itertools.product(
enter_mode, heartbeat, exit_mode
):
yield get_test_method_class(
enter_mode=enter_mode_, heartbeat=heartbeat_, exit_mode=exit_mode_
)()


# Just test that iterating the test methods works as expected
_methods = list(
iterate_test_methods(
enter_mode=[METHOD_MISSING],
heartbeat=[
METHOD_MISSING,
False,
"Failure reason",
],
exit_mode=METHOD_OPTIONS,
)
)
assert len(_methods) == 1 * 3 * 5
assert all(isinstance(m, Method) for m in _methods)
del _methods