327 lines
12 KiB
Python
327 lines
12 KiB
Python
"""Unit tests for UTEClient class."""
|
|
|
|
import time
|
|
|
|
import pytest
|
|
import requests
|
|
from pytest_mock import MockerFixture
|
|
|
|
from src.ute_wrapper.ute import (
|
|
InvalidPlanException,
|
|
InvalidPowerFactorException,
|
|
MultipleDevicesException,
|
|
ReadingRequestFailedException,
|
|
ReadingResponseInvalidException,
|
|
TariffException,
|
|
UnsupportedMethodException,
|
|
UTEClient,
|
|
)
|
|
|
|
|
|
@pytest.fixture
|
|
def ute_client(mocker: MockerFixture):
|
|
"""Return a UTEClient instance with mocked methods."""
|
|
mocker.patch.object(UTEClient, "_login", return_value="mocked_token")
|
|
mocker.patch.object(
|
|
UTEClient,
|
|
"get_devices_list",
|
|
return_value=[{"name": "Device 1", "accountServicePointId": "device_id_1"}],
|
|
)
|
|
mocker.patch.object(UTEClient, "get_account", return_value={"meterInfo": {"tariffType": "TRIPLE"}})
|
|
return UTEClient("test@example.com", "1234567890")
|
|
|
|
|
|
def test_make_request_success(ute_client, mocker: MockerFixture):
|
|
"""Test the _make_request method with a successful request."""
|
|
mocked_response = mocker.Mock(status_code=200, json=lambda: {"success": True})
|
|
mocker.patch("src.ute_wrapper.ute.requests.get", return_value=mocked_response)
|
|
response = ute_client._make_request("GET", "http://example.com")
|
|
assert response.status_code == requests.codes.ok
|
|
assert response.json()["success"] is True
|
|
|
|
|
|
def test_make_request_no_authorization(ute_client, mocker: MockerFixture):
|
|
"""Test the _make_request method when there is no authorization token."""
|
|
ute_client.authorization = None
|
|
mocked_response = mocker.Mock(status_code=requests.codes.ok, json=lambda: {"success": True})
|
|
mocker.patch("requests.get", return_value=mocked_response)
|
|
response = ute_client._make_request("GET", "http://example.com")
|
|
assert response.status_code == requests.codes.ok
|
|
assert response.json()["success"] is True
|
|
|
|
|
|
def test_make_request_all_retries_failed(ute_client, mocker: MockerFixture):
|
|
"""Test the _make_request method when all retries fail."""
|
|
mocked_response = mocker.Mock()
|
|
mocked_response.raise_for_status.side_effect = requests.RequestException
|
|
mocker.patch("requests.get", return_value=mocked_response)
|
|
mocker.patch("time.sleep")
|
|
total_call_count = 3
|
|
with pytest.raises(Exception, match="All retries failed."):
|
|
ute_client._make_request("GET", "http://example.com", retries=total_call_count)
|
|
assert mocked_response.raise_for_status.call_count == total_call_count
|
|
assert time.sleep.call_count == total_call_count - 1
|
|
|
|
|
|
def test_method_not_supported(ute_client):
|
|
"""Test the _method_not_supported method."""
|
|
with pytest.raises(UnsupportedMethodException):
|
|
ute_client._method_not_supported()
|
|
|
|
|
|
def test_login(ute_client, mocker: MockerFixture):
|
|
"""Test the _login method."""
|
|
mocked_response = mocker.Mock(text="mocked_token")
|
|
mocker.patch.object(ute_client, "_make_request", return_value=mocked_response)
|
|
token = ute_client._login()
|
|
assert token == "mocked_token"
|
|
|
|
|
|
def test_validate_power_factor(ute_client):
|
|
"""Test the _validate_power_factor method."""
|
|
with pytest.raises(InvalidPowerFactorException):
|
|
ute_client.power_factor = 1.5
|
|
ute_client._validate_power_factor()
|
|
|
|
|
|
def test_initialize_device_id(ute_client, mocker: MockerFixture):
|
|
"""Test the _initialize_device_id method."""
|
|
ute_client.device_id = ""
|
|
mocker.patch.object(ute_client, "_select_device_id", return_value="selected_device_id")
|
|
ute_client._initialize_device_id()
|
|
assert ute_client.device_id == "selected_device_id"
|
|
|
|
|
|
def test_initialize_average_cost_per_kwh(ute_client, mocker: MockerFixture):
|
|
"""Test the _initialize_average_cost_per_kwh method."""
|
|
ute_client.average_cost_per_kwh = 0.0
|
|
mocker.patch.object(ute_client, "_determine_average_cost", return_value=5.0)
|
|
ute_client._initialize_average_cost_per_kwh()
|
|
assert ute_client.average_cost_per_kwh == 5.0
|
|
|
|
|
|
def test_select_device_id_multiple_devices(ute_client, mocker: MockerFixture):
|
|
"""Test the _select_device_id method when there are multiple devices."""
|
|
mocker.patch.object(
|
|
ute_client,
|
|
"get_devices_list",
|
|
return_value=[
|
|
{"name": "Device 1", "accountServicePointId": "device_id_1"},
|
|
{"name": "Device 2", "accountServicePointId": "device_id_2"},
|
|
],
|
|
)
|
|
with pytest.raises(MultipleDevicesException):
|
|
ute_client._select_device_id()
|
|
|
|
|
|
def test_determine_average_cost_invalid_tariff(ute_client, mocker: MockerFixture):
|
|
"""Test the _determine_average_cost method with an invalid tariff."""
|
|
mocker.patch.object(ute_client, "get_account", return_value={"meterInfo": {"tariffType": "INVALID"}})
|
|
with pytest.raises(InvalidPlanException):
|
|
ute_client._determine_average_cost()
|
|
|
|
|
|
def test_determine_average_cost_invalid_tariff_key(ute_client, mocker: MockerFixture):
|
|
"""Test the _determine_average_cost method with an invalid tariff key."""
|
|
mocker.patch.object(ute_client, "get_account", side_effect=KeyError)
|
|
with pytest.raises(TariffException, match="Tariff type not standard. Explicit definition required."):
|
|
ute_client._determine_average_cost()
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"date_start, date_end",
|
|
[
|
|
("2023-05-01", "2023-05-02"),
|
|
(None, None),
|
|
],
|
|
)
|
|
def test_get_historic_consumption(ute_client, mocker: MockerFixture, date_start, date_end):
|
|
"""Test the get_historic_consumption method."""
|
|
mocked_response = {
|
|
"data": [
|
|
{"magnitudeVO": "IMPORT_ACTIVE_ENERGY", "date": "2023-05-01T00:00:00+00:00", "value": "10.0"},
|
|
{"magnitudeVO": "IMPORT_ACTIVE_ENERGY", "date": "2023-05-02T00:00:00+00:00", "value": "20.0"},
|
|
],
|
|
}
|
|
mocker.patch.object(ute_client, "_login")
|
|
mocker.patch.object(ute_client, "_make_request", return_value=mocker.Mock(json=lambda: mocked_response))
|
|
result = ute_client.get_historic_consumption(date_start, date_end)
|
|
assert result["total"]["sum_in_kwh"] == 30.0
|
|
assert result["total"]["aproximated_cost_in_uyu"] == 136.579
|
|
assert len(result["dates"]) == 2
|
|
|
|
|
|
def test_get_current_usage_info_success(ute_client, mocker: MockerFixture):
|
|
"""Test the get_current_usage_info method with a successful request."""
|
|
readings = [
|
|
{"tipoLecturaMGMI": "I1", "valor": "10"},
|
|
{"tipoLecturaMGMI": "V1", "valor": "220"},
|
|
]
|
|
mocked_reading_request = mocker.Mock(status_code=requests.codes.ok)
|
|
mocked_reading_response = mocker.Mock(json=lambda: {"success": True, "data": {"readings": readings}})
|
|
mocker.patch.object(ute_client, "_login")
|
|
mocker.patch.object(ute_client, "_make_request", side_effect=[mocked_reading_request, mocked_reading_response])
|
|
|
|
result = ute_client.get_current_usage_info()
|
|
|
|
assert result["success"] is True
|
|
assert result["data"]["readings"] == readings
|
|
assert result["data"]["power_in_watts"] == 2200.0
|
|
assert result["data"]["using_power_factor"] is True
|
|
|
|
|
|
def test_get_current_usage_info_failed_request(ute_client, mocker: MockerFixture):
|
|
"""Test the get_current_usage_info method with a failed request."""
|
|
mocker.patch.object(ute_client, "_login")
|
|
mocker.patch.object(
|
|
ute_client,
|
|
"_make_request",
|
|
side_effect=[mocker.Mock(status_code=400), mocker.Mock(json=lambda: {"success": False})],
|
|
)
|
|
with pytest.raises(ReadingRequestFailedException):
|
|
ute_client.get_current_usage_info()
|
|
|
|
|
|
def test_get_current_usage_info_invalid_response(ute_client, mocker: MockerFixture):
|
|
"""Test the get_current_usage_info method with an invalid response."""
|
|
mocker.patch.object(ute_client, "_login")
|
|
mocker.patch.object(
|
|
ute_client,
|
|
"_make_request",
|
|
side_effect=[
|
|
mocker.Mock(status_code=requests.codes.ok),
|
|
mocker.Mock(json=lambda: {"success": True, "data": {}}),
|
|
],
|
|
)
|
|
with pytest.raises(ReadingResponseInvalidException):
|
|
ute_client.get_current_usage_info()
|
|
|
|
|
|
def test_get_average_price_invalid_plan(ute_client):
|
|
"""Test the get_average_price method with an invalid plan."""
|
|
with pytest.raises(InvalidPlanException):
|
|
ute_client.get_average_price("invalid_plan")
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"plan, expected_price",
|
|
[
|
|
("triple", 4.5526324),
|
|
("doble", 5.523887),
|
|
],
|
|
)
|
|
def test_get_average_price(ute_client, plan, expected_price):
|
|
"""Test the get_average_price method."""
|
|
result = ute_client.get_average_price(plan)
|
|
assert result == expected_price
|
|
|
|
|
|
def test_get_peak(ute_client, mocker: MockerFixture):
|
|
"""Test the get_peak method."""
|
|
expected_peak_data = {
|
|
"deviceId": "test_device_id",
|
|
"peak": {
|
|
"value": 123.45,
|
|
"date": "2023-06-01T10:00:00Z",
|
|
},
|
|
}
|
|
|
|
mocked_response = mocker.Mock(json=lambda: {"data": expected_peak_data})
|
|
mocker.patch.object(ute_client, "_login")
|
|
mocker.patch.object(ute_client, "_make_request", return_value=mocked_response)
|
|
|
|
result = ute_client.get_peak()
|
|
|
|
assert result == expected_peak_data
|
|
ute_client._make_request.assert_called_once_with(
|
|
"GET",
|
|
f"https://rocme.ute.com.uy/api/v1/accounts/{ute_client.device_id}/peak",
|
|
)
|
|
|
|
|
|
def test_get_network_status(ute_client, mocker: MockerFixture):
|
|
"""Test the get_network_status method."""
|
|
expected_network_status = [
|
|
{
|
|
"departmentId": 1,
|
|
"clientsWithoutService": 100,
|
|
"percentageClientsWithoutService": 0.5,
|
|
},
|
|
{
|
|
"departmentId": 2,
|
|
"clientsWithoutService": requests.codes.ok,
|
|
"percentageClientsWithoutService": 1.0,
|
|
},
|
|
]
|
|
|
|
mocked_response = mocker.Mock(json=lambda: {"data": {"summary": expected_network_status}})
|
|
mocker.patch.object(ute_client, "_login")
|
|
mocker.patch.object(ute_client, "_make_request", return_value=mocked_response)
|
|
|
|
result = ute_client.get_network_status()
|
|
|
|
assert result == expected_network_status
|
|
ute_client._make_request.assert_called_once_with(
|
|
"GET",
|
|
"https://rocme.ute.com.uy/api/v1/info/network/status",
|
|
)
|
|
|
|
|
|
def test_get_renewable_sources(ute_client, mocker: MockerFixture):
|
|
"""Test the get_renewable_sources method."""
|
|
expected_renewable_sources = "50.0%"
|
|
|
|
mocked_response = mocker.Mock(json=lambda: {"data": {"renewableSources": expected_renewable_sources}})
|
|
mocker.patch.object(ute_client, "_login")
|
|
mocker.patch.object(ute_client, "_make_request", return_value=mocked_response)
|
|
|
|
result = ute_client.get_renewable_sources()
|
|
|
|
assert result == expected_renewable_sources
|
|
ute_client._make_request.assert_called_once_with(
|
|
"GET",
|
|
"https://rocme.ute.com.uy/api/v1/info/demand/global",
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"readings, expected_power",
|
|
[
|
|
(
|
|
[
|
|
{"tipoLecturaMGMI": "I1", "valor": "10"},
|
|
{"tipoLecturaMGMI": "V1", "valor": "220"},
|
|
],
|
|
2200.0,
|
|
),
|
|
(
|
|
[
|
|
{"tipoLecturaMGMI": "I1", "valor": "10"},
|
|
{"tipoLecturaMGMI": "I2", "valor": "10"},
|
|
{"tipoLecturaMGMI": "V1", "valor": "220"},
|
|
{"tipoLecturaMGMI": "V2", "valor": "220"},
|
|
],
|
|
2200.0,
|
|
),
|
|
(
|
|
[
|
|
{"tipoLecturaMGMI": "I1", "valor": "10"},
|
|
{"tipoLecturaMGMI": "I2", "valor": "10"},
|
|
{"tipoLecturaMGMI": "I3", "valor": "10"},
|
|
{"tipoLecturaMGMI": "V1", "valor": "220"},
|
|
{"tipoLecturaMGMI": "V2", "valor": "220"},
|
|
{"tipoLecturaMGMI": "V3", "valor": "220"},
|
|
],
|
|
3810.4,
|
|
),
|
|
(
|
|
[],
|
|
0.0,
|
|
),
|
|
],
|
|
)
|
|
def test_convert_powers_to_power_in_watts(ute_client, readings, expected_power):
|
|
"""Test the _convert_powers_to_power_in_watts method."""
|
|
result = ute_client._convert_powers_to_power_in_watts(readings)
|
|
assert result == expected_power
|