Add flake8-pytest-style (PT) for ruff (#1105)

This will catch common issues with pytest code.

* Use `match` when using `pytest.raises()` for base exception types like
`TypeError` or `ValueError`
* Use tuples for `parametrize()`
* Enforces `pytest.raises()` to contain simple statements, using `noqa`
to skip this on some cases for now.
* Fixes incorrect exception type (valueerror instead of typeerror) for
iotdimmer.
* Adds check valid types for `iotbulb.set_hsv` and `color` smart module.
* Consolidate exception messages for common interface modules.
This commit is contained in:
Teemu R.
2024-08-30 17:30:07 +02:00
committed by GitHub
parent 3e43781bb2
commit 6a86ffbbba
36 changed files with 248 additions and 150 deletions

View File

@@ -18,17 +18,18 @@ async def test_brightness_component(dev: SmartDevice):
# Test getting the value
feature = brightness._device.features["brightness"]
assert isinstance(feature.value, int)
assert feature.value > 1 and feature.value <= 100
assert feature.value > 1
assert feature.value <= 100
# Test setting the value
await feature.set_value(10)
await dev.update()
assert feature.value == 10
with pytest.raises(ValueError):
with pytest.raises(ValueError, match="out of range"):
await feature.set_value(feature.minimum_value - 10)
with pytest.raises(ValueError):
with pytest.raises(ValueError, match="out of range"):
await feature.set_value(feature.maximum_value + 10)
@@ -41,15 +42,16 @@ async def test_brightness_dimmable(dev: IotDevice):
# Test getting the value
feature = dev.features["brightness"]
assert isinstance(feature.value, int)
assert feature.value > 0 and feature.value <= 100
assert feature.value > 0
assert feature.value <= 100
# Test setting the value
await feature.set_value(10)
await dev.update()
assert feature.value == 10
with pytest.raises(ValueError):
with pytest.raises(ValueError, match="out of range"):
await feature.set_value(feature.minimum_value - 10)
with pytest.raises(ValueError):
with pytest.raises(ValueError, match="out of range"):
await feature.set_value(feature.maximum_value + 10)

View File

@@ -23,8 +23,8 @@ async def test_colortemp_component(dev: SmartDevice):
await dev.update()
assert feature.value == new_value
with pytest.raises(ValueError):
with pytest.raises(ValueError, match="out of range"):
await feature.set_value(feature.minimum_value - 10)
with pytest.raises(ValueError):
with pytest.raises(ValueError, match="out of range"):
await feature.set_value(feature.maximum_value + 10)

View File

@@ -18,7 +18,7 @@ autooff = parametrize(
@autooff
@pytest.mark.parametrize(
"feature, prop_name, type",
("feature", "prop_name", "type"),
[
("auto_off_enabled", "enabled", bool),
("auto_off_minutes", "delay", int),

View File

@@ -10,7 +10,7 @@ contact = parametrize(
@contact
@pytest.mark.parametrize(
"feature, type",
("feature", "type"),
[
("is_open", bool),
],

View File

@@ -76,8 +76,8 @@ async def test_fan_module(dev: SmartDevice, mocker: MockerFixture):
await dev.update()
assert not device.is_on
with pytest.raises(ValueError):
with pytest.raises(ValueError, match="Invalid level"):
await fan.set_fan_speed_level(-1)
with pytest.raises(ValueError):
with pytest.raises(ValueError, match="Invalid level"):
await fan.set_fan_speed_level(5)

View File

@@ -19,11 +19,10 @@ firmware = parametrize(
@firmware
@pytest.mark.parametrize(
"feature, prop_name, type, required_version",
("feature", "prop_name", "type", "required_version"),
[
("auto_update_enabled", "auto_update_enabled", bool, 2),
("update_available", "update_available", bool, 1),
("update_available", "update_available", bool, 1),
("current_firmware_version", "current_firmware", str, 1),
("available_firmware_version", "latest_firmware", str, 1),
],

View File

@@ -10,7 +10,7 @@ humidity = parametrize(
@humidity
@pytest.mark.parametrize(
"feature, type",
("feature", "type"),
[
("humidity", int),
("humidity_warning", bool),

View File

@@ -37,7 +37,7 @@ async def test_light_effect(dev: Device, mocker: MockerFixture):
assert light_effect.effect == effect
assert feature.value == effect
with pytest.raises(ValueError):
with pytest.raises(ValueError, match="The effect foobar is not a built in effect"):
await light_effect.set_effect("foobar")

View File

@@ -54,7 +54,7 @@ async def test_light_strip_effect(dev: Device, mocker: MockerFixture):
assert light_effect.effect == effect
assert feature.value == effect
with pytest.raises(ValueError):
with pytest.raises(ValueError, match="The effect foobar is not a built in effect"):
await light_effect.set_effect("foobar")

View File

@@ -10,7 +10,7 @@ motion = parametrize(
@motion
@pytest.mark.parametrize(
"feature, type",
("feature", "type"),
[
("motion_detected", bool),
],

View File

@@ -16,7 +16,7 @@ temperature_warning = parametrize(
@temperature
@pytest.mark.parametrize(
"feature, type",
("feature", "type"),
[
("temperature", float),
("temperature_unit", str),

View File

@@ -1,4 +1,5 @@
import logging
import re
import pytest
@@ -15,7 +16,7 @@ temperature = parametrize(
@thermostats_smart
@pytest.mark.parametrize(
"feature, type",
("feature", "type"),
[
("target_temperature", float),
("temperature_offset", int),
@@ -59,10 +60,14 @@ async def test_set_temperature_invalid_values(dev):
"""Test that out-of-bounds temperature values raise errors."""
temp_module: TemperatureControl = dev.modules["TemperatureControl"]
with pytest.raises(ValueError):
with pytest.raises(
ValueError, match="Invalid target temperature -1, must be in range"
):
await temp_module.set_target_temperature(-1)
with pytest.raises(ValueError):
with pytest.raises(
ValueError, match="Invalid target temperature 100, must be in range"
):
await temp_module.set_target_temperature(100)
@@ -70,10 +75,14 @@ async def test_set_temperature_invalid_values(dev):
async def test_temperature_offset(dev):
"""Test the temperature offset API."""
temp_module: TemperatureControl = dev.modules["TemperatureControl"]
with pytest.raises(ValueError):
with pytest.raises(
ValueError, match=re.escape("Temperature offset must be [-10, 10]")
):
await temp_module.set_temperature_offset(100)
with pytest.raises(ValueError):
with pytest.raises(
ValueError, match=re.escape("Temperature offset must be [-10, 10]")
):
await temp_module.set_temperature_offset(-100)
await temp_module.set_temperature_offset(5)
@@ -83,7 +92,7 @@ async def test_temperature_offset(dev):
@thermostats_smart
@pytest.mark.parametrize(
"mode, states, frost_protection",
("mode", "states", "frost_protection"),
[
pytest.param(ThermostatState.Idle, [], False, id="idle has empty"),
pytest.param(
@@ -114,7 +123,7 @@ async def test_thermostat_mode(dev, mode, states, frost_protection):
@thermostats_smart
@pytest.mark.parametrize(
"mode, states, msg",
("mode", "states", "msg"),
[
pytest.param(
ThermostatState.Heating,

View File

@@ -12,7 +12,7 @@ waterleak = parametrize(
@waterleak
@pytest.mark.parametrize(
"feature, prop_name, type",
("feature", "prop_name", "type"),
[
("water_alert", "alert", int),
("water_leak", "status", Enum),