diff --git a/tests/util/test_unit_conversion.py b/tests/util/test_unit_conversion.py index 4367d166aed..40b4b53f438 100644 --- a/tests/util/test_unit_conversion.py +++ b/tests/util/test_unit_conversion.py @@ -1,4 +1,8 @@ -"""Test Home Assistant eneergy utility functions.""" +"""Test Home Assistant unit conversion utility functions.""" +from __future__ import annotations + +import inspect + import pytest from homeassistant.const import ( @@ -16,11 +20,13 @@ from homeassistant.const import ( UnitOfVolumetricFlux, ) from homeassistant.exceptions import HomeAssistantError +from homeassistant.util import unit_conversion from homeassistant.util.unit_conversion import ( BaseUnitConverter, DataRateConverter, DistanceConverter, ElectricCurrentConverter, + ElectricPotentialConverter, EnergyConverter, InformationConverter, MassConverter, @@ -28,63 +34,61 @@ from homeassistant.util.unit_conversion import ( PressureConverter, SpeedConverter, TemperatureConverter, + UnitlessRatioConverter, VolumeConverter, ) INVALID_SYMBOL = "bob" +# Dict containing all converters that need to be tested. +# The VALID_UNITS are sorted to ensure that pytest runs are consistent +# and avoid `different tests were collected between gw0 and gw1` +_ALL_CONVERTERS: dict[type[BaseUnitConverter], list[str | None]] = { + converter: sorted(converter.VALID_UNITS, key=lambda x: (x is None, x)) + for converter in ( + DataRateConverter, + DistanceConverter, + ElectricCurrentConverter, + ElectricPotentialConverter, + EnergyConverter, + InformationConverter, + MassConverter, + PowerConverter, + PressureConverter, + SpeedConverter, + TemperatureConverter, + UnitlessRatioConverter, + VolumeConverter, + ) +} + + +@pytest.mark.parametrize( + "converter", + [ + # Generate list of all converters available in + # `homeassistant.util.unit_conversion` to ensure + # that we don't miss any in the tests. + obj + for _, obj in inspect.getmembers(unit_conversion) + if inspect.isclass(obj) + and issubclass(obj, BaseUnitConverter) + and obj != BaseUnitConverter + ], +) +def test_all_converters(converter: type[BaseUnitConverter]) -> None: + """Ensure all unit converters are tested.""" + assert converter in _ALL_CONVERTERS, "converter is not present in _ALL_CONVERTERS" + + @pytest.mark.parametrize( "converter,valid_unit", [ - (DataRateConverter, UnitOfDataRate.GIBIBYTES_PER_SECOND), - (DistanceConverter, UnitOfLength.KILOMETERS), - (DistanceConverter, UnitOfLength.METERS), - (DistanceConverter, UnitOfLength.CENTIMETERS), - (DistanceConverter, UnitOfLength.MILLIMETERS), - (DistanceConverter, UnitOfLength.MILES), - (DistanceConverter, UnitOfLength.YARDS), - (DistanceConverter, UnitOfLength.FEET), - (DistanceConverter, UnitOfLength.INCHES), - (ElectricCurrentConverter, UnitOfElectricCurrent.AMPERE), - (ElectricCurrentConverter, UnitOfElectricCurrent.MILLIAMPERE), - (EnergyConverter, UnitOfEnergy.WATT_HOUR), - (EnergyConverter, UnitOfEnergy.KILO_WATT_HOUR), - (EnergyConverter, UnitOfEnergy.MEGA_WATT_HOUR), - (EnergyConverter, UnitOfEnergy.GIGA_JOULE), - (InformationConverter, UnitOfInformation.GIGABYTES), - (MassConverter, UnitOfMass.GRAMS), - (MassConverter, UnitOfMass.KILOGRAMS), - (MassConverter, UnitOfMass.MICROGRAMS), - (MassConverter, UnitOfMass.MILLIGRAMS), - (MassConverter, UnitOfMass.OUNCES), - (MassConverter, UnitOfMass.POUNDS), - (PowerConverter, UnitOfPower.WATT), - (PowerConverter, UnitOfPower.KILO_WATT), - (PressureConverter, UnitOfPressure.PA), - (PressureConverter, UnitOfPressure.HPA), - (PressureConverter, UnitOfPressure.MBAR), - (PressureConverter, UnitOfPressure.INHG), - (PressureConverter, UnitOfPressure.KPA), - (PressureConverter, UnitOfPressure.CBAR), - (PressureConverter, UnitOfPressure.MMHG), - (PressureConverter, UnitOfPressure.PSI), - (SpeedConverter, UnitOfVolumetricFlux.INCHES_PER_DAY), - (SpeedConverter, UnitOfVolumetricFlux.INCHES_PER_HOUR), - (SpeedConverter, UnitOfVolumetricFlux.MILLIMETERS_PER_DAY), - (SpeedConverter, UnitOfVolumetricFlux.MILLIMETERS_PER_HOUR), - (SpeedConverter, UnitOfSpeed.FEET_PER_SECOND), - (SpeedConverter, UnitOfSpeed.KILOMETERS_PER_HOUR), - (SpeedConverter, UnitOfSpeed.KNOTS), - (SpeedConverter, UnitOfSpeed.METERS_PER_SECOND), - (SpeedConverter, UnitOfSpeed.MILES_PER_HOUR), - (TemperatureConverter, UnitOfTemperature.CELSIUS), - (TemperatureConverter, UnitOfTemperature.FAHRENHEIT), - (TemperatureConverter, UnitOfTemperature.KELVIN), - (VolumeConverter, UnitOfVolume.LITERS), - (VolumeConverter, UnitOfVolume.MILLILITERS), - (VolumeConverter, UnitOfVolume.GALLONS), - (VolumeConverter, UnitOfVolume.FLUID_OUNCES), + # Ensure all units are tested + (converter, valid_unit) + for converter, valid_units in _ALL_CONVERTERS.items() + for valid_unit in valid_units ], ) def test_convert_same_unit(converter: type[BaseUnitConverter], valid_unit: str) -> None: @@ -95,19 +99,10 @@ def test_convert_same_unit(converter: type[BaseUnitConverter], valid_unit: str) @pytest.mark.parametrize( "converter,valid_unit", [ - (DataRateConverter, UnitOfDataRate.GIBIBYTES_PER_SECOND), - (DistanceConverter, UnitOfLength.KILOMETERS), - (ElectricCurrentConverter, UnitOfElectricCurrent.AMPERE), - (EnergyConverter, UnitOfEnergy.KILO_WATT_HOUR), - (InformationConverter, UnitOfInformation.GIBIBYTES), - (MassConverter, UnitOfMass.GRAMS), - (PowerConverter, UnitOfPower.WATT), - (PressureConverter, UnitOfPressure.PA), - (SpeedConverter, UnitOfSpeed.KILOMETERS_PER_HOUR), - (TemperatureConverter, UnitOfTemperature.CELSIUS), - (TemperatureConverter, UnitOfTemperature.FAHRENHEIT), - (TemperatureConverter, UnitOfTemperature.KELVIN), - (VolumeConverter, UnitOfVolume.LITERS), + # Ensure all units are tested + (converter, valid_unit) + for converter, valid_units in _ALL_CONVERTERS.items() + for valid_unit in valid_units ], ) def test_convert_invalid_unit( @@ -124,24 +119,9 @@ def test_convert_invalid_unit( @pytest.mark.parametrize( "converter,from_unit,to_unit", [ - ( - DataRateConverter, - UnitOfDataRate.BYTES_PER_SECOND, - UnitOfDataRate.BITS_PER_SECOND, - ), - (DistanceConverter, UnitOfLength.KILOMETERS, UnitOfLength.METERS), - (EnergyConverter, UnitOfEnergy.WATT_HOUR, UnitOfEnergy.KILO_WATT_HOUR), - ( - InformationConverter, - UnitOfInformation.GIBIBYTES, - UnitOfInformation.GIGABYTES, - ), - (MassConverter, UnitOfMass.GRAMS, UnitOfMass.KILOGRAMS), - (PowerConverter, UnitOfPower.WATT, UnitOfPower.KILO_WATT), - (PressureConverter, UnitOfPressure.HPA, UnitOfPressure.INHG), - (SpeedConverter, UnitOfSpeed.KILOMETERS_PER_HOUR, UnitOfSpeed.MILES_PER_HOUR), - (TemperatureConverter, UnitOfTemperature.CELSIUS, UnitOfTemperature.FAHRENHEIT), - (VolumeConverter, UnitOfVolume.GALLONS, UnitOfVolume.LITERS), + # Pick any two units + (converter, valid_units[0], valid_units[1]) + for converter, valid_units in _ALL_CONVERTERS.items() ], ) def test_convert_nonnumeric_value(