File: test_devices.py

package info (click to toggle)
python-asusrouter 1.21.3-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 1,856 kB
  • sloc: python: 20,497; makefile: 3
file content (178 lines) | stat: -rw-r--r-- 4,851 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
"""Test AsusRouter with real devices data."""

from contextlib import contextmanager
from dataclasses import dataclass
from enum import Enum
import importlib
import logging
from pathlib import Path
import re
from typing import Any

import pytest

from asusrouter import AsusData
from asusrouter.modules.endpoint import (
    Endpoint,
    EndpointControl,
    EndpointService,
    EndpointTools,
    EndpointType,
    process,
    read,
)

# Create a logger
_LOGGER = logging.getLogger(__name__)
_LOGGER.setLevel(logging.INFO)


class FileExtensions(Enum):
    """File extensions used in the test data."""

    CONTENT = ".content"
    PYTHON = ".py"


@dataclass
class DataItem:
    """A class used to represent a test item."""

    content: str
    result: dict[AsusData, Any]
    endpoint: EndpointType
    label: str

    def __repr__(self) -> str:
        """Return a string representation of the data item."""

        return self.label


@contextmanager
def log_test_data_loading():
    """Log the start and end of loading test data."""

    _LOGGER.info("Starting to load test data")
    yield
    _LOGGER.info("Finished loading test data")


def load_content_data(device_path: Path, module_name: str) -> str:
    """Load content data from a file."""

    content_file = device_path / f"{module_name}{FileExtensions.CONTENT.value}"
    with content_file.open("r", encoding="utf-8") as f:
        return f.read()


def load_expected_result(device_path: Path, module_name: str) -> Any:
    """Load expected result from a module."""

    result_module = importlib.import_module(
        f".test_data.{'.'.join([device_path.name, module_name])}",
        package="tests",
    )
    return result_module.expected_result


def load_test_item(device_path: Path, module_name: str) -> DataItem | None:
    """Load a single test item."""

    try:
        endpoint_name = re.match(r"(.*)_\d+", module_name).group(1)

        endpoint = None
        for endpoint_enum in [
            Endpoint,
            EndpointControl,
            EndpointService,
            EndpointTools,
        ]:
            try:
                endpoint = endpoint_enum[endpoint_name.upper()]
                break
            except KeyError:
                continue

        if endpoint is None:
            raise ValueError("Failed to load test item ", module_name)

        content_data = load_content_data(device_path, module_name)
        expected_result = load_expected_result(device_path, module_name)

        return DataItem(
            content=content_data,
            result=expected_result,
            endpoint=endpoint,
            label=f"{device_path.name}_{module_name}",
        )
    except Exception as ex:  # noqa: BLE001
        _LOGGER.error("Failed to load test item %s: %s", module_name, ex)
        return None


def load_test_data() -> list[DataItem]:
    """Load the test data."""

    with log_test_data_loading():
        test_data_path = Path(__file__).resolve().parent / "test_data"
        data = []

        for device_path in test_data_path.iterdir():
            if device_path.is_dir():
                device_test_count = 0
                for content_file in device_path.glob("*.content"):
                    module_name = content_file.stem

                    # Check if both .content and .py files exist
                    if (
                        not (device_path / f"{module_name}.content").exists()
                        or not (device_path / f"{module_name}.py").exists()
                    ):
                        continue

                    item = load_test_item(device_path, module_name)
                    data.append(item)
                    device_test_count += 1

                _LOGGER.info(
                    "Found %s test items for device: %s",
                    device_test_count,
                    device_path.name,
                )

        _LOGGER.info("Total test items found: %s", len(data))
        return data


# Load the test data only once
test_data = load_test_data()

# Create a list of ids for the test data
test_ids = [item.label for item in test_data]


@pytest.fixture(params=test_data, ids=test_ids)
def test_item(request) -> DataItem:
    """Yield each item in the test data."""

    return request.param


def test_asusrouter(test_item: DataItem) -> None:  # pylint: disable=redefined-outer-name
    """
    Test the asusrouter module with the given test item.

    Args:
        test_item (DataItem): The test item to use for the test.

    Raises:
        AssertionError: If the actual processed data does not match
        the expected result.
    """

    actual_read = read(test_item.endpoint, test_item.content)
    actual_processed = process(test_item.endpoint, actual_read)

    assert actual_processed == test_item.result, print(actual_processed)  # noqa: T201