diff --git a/homeassistant/util/distance.py b/homeassistant/util/distance.py index 38b9253ffbf..4a7445c46ed 100644 --- a/homeassistant/util/distance.py +++ b/homeassistant/util/distance.py @@ -1,7 +1,6 @@ """Distance util functions.""" from __future__ import annotations -from collections.abc import Callable from numbers import Number from homeassistant.const import ( @@ -28,26 +27,26 @@ VALID_UNITS: tuple[str, ...] = ( LENGTH_YARD, ) -TO_METERS: dict[str, Callable[[float], float]] = { - LENGTH_METERS: lambda meters: meters, - LENGTH_MILES: lambda miles: miles * 1609.344, - LENGTH_YARD: lambda yards: yards * 0.9144, - LENGTH_FEET: lambda feet: feet * 0.3048, - LENGTH_INCHES: lambda inches: inches * 0.0254, - LENGTH_KILOMETERS: lambda kilometers: kilometers * 1000, - LENGTH_CENTIMETERS: lambda centimeters: centimeters * 0.01, - LENGTH_MILLIMETERS: lambda millimeters: millimeters * 0.001, -} +MM_TO_M = 0.001 # 1 mm = 0.001 m +CM_TO_M = 0.01 # 1 cm = 0.01 m +KM_TO_M = 1000 # 1 km = 1000 m -METERS_TO: dict[str, Callable[[float], float]] = { - LENGTH_METERS: lambda meters: meters, - LENGTH_MILES: lambda meters: meters * 0.000621371, - LENGTH_YARD: lambda meters: meters * 1.09361, - LENGTH_FEET: lambda meters: meters * 3.28084, - LENGTH_INCHES: lambda meters: meters * 39.3701, - LENGTH_KILOMETERS: lambda meters: meters * 0.001, - LENGTH_CENTIMETERS: lambda meters: meters * 100, - LENGTH_MILLIMETERS: lambda meters: meters * 1000, +IN_TO_M = 0.0254 # 1 inch = 0.0254 m +FOOT_TO_M = IN_TO_M * 12 # 12 inches = 1 foot (0.3048 m) +YARD_TO_M = FOOT_TO_M * 3 # 3 feet = 1 yard (0.9144 m) +MILE_TO_M = YARD_TO_M * 1760 # 1760 yard = 1 mile (1609.344 m) + +NAUTICAL_MILE_TO_M = 1852 # 1 nautical mile = 1852 m + +UNIT_CONVERSION: dict[str, float] = { + LENGTH_METERS: 1, + LENGTH_MILLIMETERS: 1 / MM_TO_M, + LENGTH_CENTIMETERS: 1 / CM_TO_M, + LENGTH_KILOMETERS: 1 / KM_TO_M, + LENGTH_INCHES: 1 / IN_TO_M, + LENGTH_FEET: 1 / FOOT_TO_M, + LENGTH_YARD: 1 / YARD_TO_M, + LENGTH_MILES: 1 / MILE_TO_M, } @@ -64,6 +63,6 @@ def convert(value: float, unit_1: str, unit_2: str) -> float: if unit_1 == unit_2 or unit_1 not in VALID_UNITS: return value - meters: float = TO_METERS[unit_1](value) + meters: float = value / UNIT_CONVERSION[unit_1] - return METERS_TO[unit_2](meters) + return meters * UNIT_CONVERSION[unit_2] diff --git a/homeassistant/util/speed.py b/homeassistant/util/speed.py index 12618e020f8..823c65b59b0 100644 --- a/homeassistant/util/speed.py +++ b/homeassistant/util/speed.py @@ -16,6 +16,15 @@ from homeassistant.const import ( UNIT_NOT_RECOGNIZED_TEMPLATE, ) +from .distance import ( + FOOT_TO_M, + IN_TO_M, + KM_TO_M, + MILE_TO_M, + MM_TO_M, + NAUTICAL_MILE_TO_M, +) + VALID_UNITS: tuple[str, ...] = ( SPEED_FEET_PER_SECOND, SPEED_INCHES_PER_DAY, @@ -27,23 +36,19 @@ VALID_UNITS: tuple[str, ...] = ( SPEED_MILLIMETERS_PER_DAY, ) -FOOT_TO_M = 0.3048 HRS_TO_SECS = 60 * 60 # 1 hr = 3600 seconds -IN_TO_M = 0.0254 -KM_TO_M = 1000 # 1 km = 1000 m -MILE_TO_M = 1609.344 -NAUTICAL_MILE_TO_M = 1852 # 1 nautical mile = 1852 m +DAYS_TO_SECS = 24 * HRS_TO_SECS # 1 day = 24 hours = 86400 seconds # Units in terms of m/s UNIT_CONVERSION: dict[str, float] = { SPEED_FEET_PER_SECOND: 1 / FOOT_TO_M, - SPEED_INCHES_PER_DAY: (24 * HRS_TO_SECS) / IN_TO_M, + SPEED_INCHES_PER_DAY: DAYS_TO_SECS / IN_TO_M, SPEED_INCHES_PER_HOUR: HRS_TO_SECS / IN_TO_M, SPEED_KILOMETERS_PER_HOUR: HRS_TO_SECS / KM_TO_M, SPEED_KNOTS: HRS_TO_SECS / NAUTICAL_MILE_TO_M, SPEED_METERS_PER_SECOND: 1, SPEED_MILES_PER_HOUR: HRS_TO_SECS / MILE_TO_M, - SPEED_MILLIMETERS_PER_DAY: (24 * HRS_TO_SECS) * 1000, + SPEED_MILLIMETERS_PER_DAY: DAYS_TO_SECS / MM_TO_M, } diff --git a/homeassistant/util/volume.py b/homeassistant/util/volume.py index 84a3faa0951..73e89a064a2 100644 --- a/homeassistant/util/volume.py +++ b/homeassistant/util/volume.py @@ -14,6 +14,8 @@ from homeassistant.const import ( VOLUME_MILLILITERS, ) +from .distance import FOOT_TO_M, IN_TO_M + VALID_UNITS: tuple[str, ...] = ( VOLUME_LITERS, VOLUME_MILLILITERS, @@ -23,25 +25,41 @@ VALID_UNITS: tuple[str, ...] = ( VOLUME_CUBIC_FEET, ) +ML_TO_L = 0.001 # 1 mL = 0.001 L +CUBIC_METER_TO_L = 1000 # 1 m3 = 1000 L +GALLON_TO_L = 231 * pow(IN_TO_M, 3) * CUBIC_METER_TO_L # US gallon is 231 cubic inches +FLUID_OUNCE_TO_L = GALLON_TO_L / 128 # 128 fluid ounces in a US gallon +CUBIC_FOOT_TO_L = CUBIC_METER_TO_L * pow(FOOT_TO_M, 3) + +# Units in terms of L +UNIT_CONVERSION: dict[str, float] = { + VOLUME_LITERS: 1, + VOLUME_MILLILITERS: 1 / ML_TO_L, + VOLUME_GALLONS: 1 / GALLON_TO_L, + VOLUME_FLUID_OUNCE: 1 / FLUID_OUNCE_TO_L, + VOLUME_CUBIC_METERS: 1 / CUBIC_METER_TO_L, + VOLUME_CUBIC_FEET: 1 / CUBIC_FOOT_TO_L, +} + def liter_to_gallon(liter: float) -> float: """Convert a volume measurement in Liter to Gallon.""" - return liter * 0.2642 + return _convert(liter, VOLUME_LITERS, VOLUME_GALLONS) def gallon_to_liter(gallon: float) -> float: """Convert a volume measurement in Gallon to Liter.""" - return gallon * 3.785 + return _convert(gallon, VOLUME_GALLONS, VOLUME_LITERS) def cubic_meter_to_cubic_feet(cubic_meter: float) -> float: """Convert a volume measurement in cubic meter to cubic feet.""" - return cubic_meter * 35.3146667 + return _convert(cubic_meter, VOLUME_CUBIC_METERS, VOLUME_CUBIC_FEET) def cubic_feet_to_cubic_meter(cubic_feet: float) -> float: """Convert a volume measurement in cubic feet to cubic meter.""" - return cubic_feet * 0.0283168466 + return _convert(cubic_feet, VOLUME_CUBIC_FEET, VOLUME_CUBIC_METERS) def convert(volume: float, from_unit: str, to_unit: str) -> float: @@ -56,15 +74,10 @@ def convert(volume: float, from_unit: str, to_unit: str) -> float: if from_unit == to_unit: return volume + return _convert(volume, from_unit, to_unit) - result: float = volume - if from_unit == VOLUME_LITERS and to_unit == VOLUME_GALLONS: - result = liter_to_gallon(volume) - elif from_unit == VOLUME_GALLONS and to_unit == VOLUME_LITERS: - result = gallon_to_liter(volume) - elif from_unit == VOLUME_CUBIC_METERS and to_unit == VOLUME_CUBIC_FEET: - result = cubic_meter_to_cubic_feet(volume) - elif from_unit == VOLUME_CUBIC_FEET and to_unit == VOLUME_CUBIC_METERS: - result = cubic_feet_to_cubic_meter(volume) - return result +def _convert(volume: float, from_unit: str, to_unit: str) -> float: + """Convert a temperature from one unit to another, bypassing checks.""" + liters = volume / UNIT_CONVERSION[from_unit] + return liters * UNIT_CONVERSION[to_unit] diff --git a/tests/components/bmw_connected_drive/test_sensor.py b/tests/components/bmw_connected_drive/test_sensor.py index cb1299a274b..90b3f725a6d 100644 --- a/tests/components/bmw_connected_drive/test_sensor.py +++ b/tests/components/bmw_connected_drive/test_sensor.py @@ -17,7 +17,7 @@ from . import setup_mocked_integration ("sensor.i3_rex_remaining_range_total", METRIC, "279", "km"), ("sensor.i3_rex_remaining_range_total", IMPERIAL, "173.36", "mi"), ("sensor.i3_rex_mileage", METRIC, "137009", "km"), - ("sensor.i3_rex_mileage", IMPERIAL, "85133.42", "mi"), + ("sensor.i3_rex_mileage", IMPERIAL, "85133.45", "mi"), ("sensor.i3_rex_remaining_battery_percent", METRIC, "82", "%"), ("sensor.i3_rex_remaining_battery_percent", IMPERIAL, "82", "%"), ("sensor.i3_rex_remaining_range_electric", METRIC, "174", "km"), diff --git a/tests/components/here_travel_time/test_sensor.py b/tests/components/here_travel_time/test_sensor.py index 93fbd1bd204..70669a63da5 100644 --- a/tests/components/here_travel_time/test_sensor.py +++ b/tests/components/here_travel_time/test_sensor.py @@ -67,7 +67,7 @@ from tests.common import MockConfigEntry None, None, "30", - "23.903", + 23.903, "31", ), ( @@ -77,7 +77,7 @@ from tests.common import MockConfigEntry None, None, "30", - "23.903", + 23.903, "30", ), ( @@ -87,7 +87,7 @@ from tests.common import MockConfigEntry None, None, "30", - "14.852631013", + 14.85263, "30", ), ( @@ -97,7 +97,7 @@ from tests.common import MockConfigEntry "08:00:00", None, "30", - "14.852631013", + 14.85263, "30", ), ( @@ -107,7 +107,7 @@ from tests.common import MockConfigEntry None, "08:00:00", "30", - "23.903", + 23.903, "31", ), ], @@ -163,7 +163,9 @@ async def test_sensor( hass.states.get("sensor.test_duration_in_traffic").state == expected_duration_in_traffic ) - assert hass.states.get("sensor.test_distance").state == expected_distance + assert float(hass.states.get("sensor.test_distance").state) == pytest.approx( + expected_distance + ) assert hass.states.get("sensor.test_route").state == ( "US-29 - K St NW; US-29 - Whitehurst Fwy; " "I-495 N - Capital Beltway; MD-187 S - Old Georgetown Rd" diff --git a/tests/components/waze_travel_time/test_sensor.py b/tests/components/waze_travel_time/test_sensor.py index 2b28190e430..67ba7c6e311 100644 --- a/tests/components/waze_travel_time/test_sensor.py +++ b/tests/components/waze_travel_time/test_sensor.py @@ -97,7 +97,9 @@ async def test_sensor(hass): @pytest.mark.usefixtures("mock_update", "mock_config") async def test_imperial(hass): """Test that the imperial option works.""" - assert hass.states.get("sensor.waze_travel_time").attributes["distance"] == 186.4113 + assert hass.states.get("sensor.waze_travel_time").attributes[ + "distance" + ] == pytest.approx(186.4113) @pytest.mark.usefixtures("mock_update_wrcerror") diff --git a/tests/util/test_distance.py b/tests/util/test_distance.py index e1cf7ae0f6a..eb001add114 100644 --- a/tests/util/test_distance.py +++ b/tests/util/test_distance.py @@ -45,102 +45,149 @@ def test_convert_nonnumeric_value(): distance_util.convert("a", LENGTH_KILOMETERS, LENGTH_METERS) -def test_convert_from_miles(): +@pytest.mark.parametrize( + "unit,expected", + [ + (LENGTH_KILOMETERS, 8.04672), + (LENGTH_METERS, 8046.72), + (LENGTH_CENTIMETERS, 804672.0), + (LENGTH_MILLIMETERS, 8046720.0), + (LENGTH_YARD, 8800.0), + (LENGTH_FEET, 26400.0008448), + (LENGTH_INCHES, 316800.171072), + ], +) +def test_convert_from_miles(unit, expected): """Test conversion from miles to other units.""" miles = 5 - assert distance_util.convert(miles, LENGTH_MILES, LENGTH_KILOMETERS) == 8.04672 - assert distance_util.convert(miles, LENGTH_MILES, LENGTH_METERS) == 8046.72 - assert distance_util.convert(miles, LENGTH_MILES, LENGTH_CENTIMETERS) == 804672.0 - assert distance_util.convert(miles, LENGTH_MILES, LENGTH_MILLIMETERS) == 8046720.0 - assert distance_util.convert(miles, LENGTH_MILES, LENGTH_YARD) == 8799.9734592 - assert distance_util.convert(miles, LENGTH_MILES, LENGTH_FEET) == 26400.0008448 - assert distance_util.convert(miles, LENGTH_MILES, LENGTH_INCHES) == 316800.171072 + assert distance_util.convert(miles, LENGTH_MILES, unit) == pytest.approx(expected) -def test_convert_from_yards(): +@pytest.mark.parametrize( + "unit,expected", + [ + (LENGTH_KILOMETERS, 0.0045720000000000005), + (LENGTH_METERS, 4.572), + (LENGTH_CENTIMETERS, 457.2), + (LENGTH_MILLIMETERS, 4572), + (LENGTH_MILES, 0.002840908212), + (LENGTH_FEET, 15.00000048), + (LENGTH_INCHES, 180.0000972), + ], +) +def test_convert_from_yards(unit, expected): """Test conversion from yards to other units.""" yards = 5 - assert ( - distance_util.convert(yards, LENGTH_YARD, LENGTH_KILOMETERS) - == 0.0045720000000000005 - ) - assert distance_util.convert(yards, LENGTH_YARD, LENGTH_METERS) == 4.572 - assert distance_util.convert(yards, LENGTH_YARD, LENGTH_CENTIMETERS) == 457.2 - assert distance_util.convert(yards, LENGTH_YARD, LENGTH_MILLIMETERS) == 4572.0 - assert distance_util.convert(yards, LENGTH_YARD, LENGTH_MILES) == 0.002840908212 - assert distance_util.convert(yards, LENGTH_YARD, LENGTH_FEET) == 15.00000048 - assert distance_util.convert(yards, LENGTH_YARD, LENGTH_INCHES) == 180.0000972 + assert distance_util.convert(yards, LENGTH_YARD, unit) == pytest.approx(expected) -def test_convert_from_feet(): +@pytest.mark.parametrize( + "unit,expected", + [ + (LENGTH_KILOMETERS, 1.524), + (LENGTH_METERS, 1524), + (LENGTH_CENTIMETERS, 152400.0), + (LENGTH_MILLIMETERS, 1524000.0), + (LENGTH_MILES, 0.9469694040000001), + (LENGTH_YARD, 1666.66667), + (LENGTH_INCHES, 60000.032400000004), + ], +) +def test_convert_from_feet(unit, expected): """Test conversion from feet to other units.""" feet = 5000 - assert distance_util.convert(feet, LENGTH_FEET, LENGTH_KILOMETERS) == 1.524 - assert distance_util.convert(feet, LENGTH_FEET, LENGTH_METERS) == 1524 - assert distance_util.convert(feet, LENGTH_FEET, LENGTH_CENTIMETERS) == 152400.0 - assert distance_util.convert(feet, LENGTH_FEET, LENGTH_MILLIMETERS) == 1524000.0 - assert distance_util.convert(feet, LENGTH_FEET, LENGTH_MILES) == 0.9469694040000001 - assert distance_util.convert(feet, LENGTH_FEET, LENGTH_YARD) == 1666.66164 - assert distance_util.convert(feet, LENGTH_FEET, LENGTH_INCHES) == 60000.032400000004 + assert distance_util.convert(feet, LENGTH_FEET, unit) == pytest.approx(expected) -def test_convert_from_inches(): +@pytest.mark.parametrize( + "unit,expected", + [ + (LENGTH_KILOMETERS, 0.127), + (LENGTH_METERS, 127.0), + (LENGTH_CENTIMETERS, 12700.0), + (LENGTH_MILLIMETERS, 127000.0), + (LENGTH_MILES, 0.078914117), + (LENGTH_YARD, 138.88889), + (LENGTH_FEET, 416.66668), + ], +) +def test_convert_from_inches(unit, expected): """Test conversion from inches to other units.""" inches = 5000 - assert distance_util.convert(inches, LENGTH_INCHES, LENGTH_KILOMETERS) == 0.127 - assert distance_util.convert(inches, LENGTH_INCHES, LENGTH_METERS) == 127.0 - assert distance_util.convert(inches, LENGTH_INCHES, LENGTH_CENTIMETERS) == 12700.0 - assert distance_util.convert(inches, LENGTH_INCHES, LENGTH_MILLIMETERS) == 127000.0 - assert distance_util.convert(inches, LENGTH_INCHES, LENGTH_MILES) == 0.078914117 - assert ( - distance_util.convert(inches, LENGTH_INCHES, LENGTH_YARD) == 138.88846999999998 - ) - assert distance_util.convert(inches, LENGTH_INCHES, LENGTH_FEET) == 416.66668 + assert distance_util.convert(inches, LENGTH_INCHES, unit) == pytest.approx(expected) -def test_convert_from_kilometers(): +@pytest.mark.parametrize( + "unit,expected", + [ + (LENGTH_METERS, 5000), + (LENGTH_CENTIMETERS, 500000), + (LENGTH_MILLIMETERS, 5000000), + (LENGTH_MILES, 3.106855), + (LENGTH_YARD, 5468.066), + (LENGTH_FEET, 16404.2), + (LENGTH_INCHES, 196850.5), + ], +) +def test_convert_from_kilometers(unit, expected): """Test conversion from kilometers to other units.""" km = 5 - assert distance_util.convert(km, LENGTH_KILOMETERS, LENGTH_METERS) == 5000 - assert distance_util.convert(km, LENGTH_KILOMETERS, LENGTH_CENTIMETERS) == 500000 - assert distance_util.convert(km, LENGTH_KILOMETERS, LENGTH_MILLIMETERS) == 5000000 - assert distance_util.convert(km, LENGTH_KILOMETERS, LENGTH_MILES) == 3.106855 - assert distance_util.convert(km, LENGTH_KILOMETERS, LENGTH_YARD) == 5468.05 - assert distance_util.convert(km, LENGTH_KILOMETERS, LENGTH_FEET) == 16404.2 - assert distance_util.convert(km, LENGTH_KILOMETERS, LENGTH_INCHES) == 196850.5 + assert distance_util.convert(km, LENGTH_KILOMETERS, unit) == pytest.approx(expected) -def test_convert_from_meters(): +@pytest.mark.parametrize( + "unit,expected", + [ + (LENGTH_KILOMETERS, 5), + (LENGTH_CENTIMETERS, 500000), + (LENGTH_MILLIMETERS, 5000000), + (LENGTH_MILES, 3.106855), + (LENGTH_YARD, 5468.066), + (LENGTH_FEET, 16404.2), + (LENGTH_INCHES, 196850.5), + ], +) +def test_convert_from_meters(unit, expected): """Test conversion from meters to other units.""" m = 5000 - assert distance_util.convert(m, LENGTH_METERS, LENGTH_KILOMETERS) == 5 - assert distance_util.convert(m, LENGTH_METERS, LENGTH_CENTIMETERS) == 500000 - assert distance_util.convert(m, LENGTH_METERS, LENGTH_MILLIMETERS) == 5000000 - assert distance_util.convert(m, LENGTH_METERS, LENGTH_MILES) == 3.106855 - assert distance_util.convert(m, LENGTH_METERS, LENGTH_YARD) == 5468.05 - assert distance_util.convert(m, LENGTH_METERS, LENGTH_FEET) == 16404.2 - assert distance_util.convert(m, LENGTH_METERS, LENGTH_INCHES) == 196850.5 + assert distance_util.convert(m, LENGTH_METERS, unit) == pytest.approx(expected) -def test_convert_from_centimeters(): +@pytest.mark.parametrize( + "unit,expected", + [ + (LENGTH_KILOMETERS, 5), + (LENGTH_METERS, 5000), + (LENGTH_MILLIMETERS, 5000000), + (LENGTH_MILES, 3.106855), + (LENGTH_YARD, 5468.066), + (LENGTH_FEET, 16404.2), + (LENGTH_INCHES, 196850.5), + ], +) +def test_convert_from_centimeters(unit, expected): """Test conversion from centimeters to other units.""" cm = 500000 - assert distance_util.convert(cm, LENGTH_CENTIMETERS, LENGTH_KILOMETERS) == 5 - assert distance_util.convert(cm, LENGTH_CENTIMETERS, LENGTH_METERS) == 5000 - assert distance_util.convert(cm, LENGTH_CENTIMETERS, LENGTH_MILLIMETERS) == 5000000 - assert distance_util.convert(cm, LENGTH_CENTIMETERS, LENGTH_MILES) == 3.106855 - assert distance_util.convert(cm, LENGTH_CENTIMETERS, LENGTH_YARD) == 5468.05 - assert distance_util.convert(cm, LENGTH_CENTIMETERS, LENGTH_FEET) == 16404.2 - assert distance_util.convert(cm, LENGTH_CENTIMETERS, LENGTH_INCHES) == 196850.5 + assert distance_util.convert(cm, LENGTH_CENTIMETERS, unit) == pytest.approx( + expected + ) -def test_convert_from_millimeters(): +@pytest.mark.parametrize( + "unit,expected", + [ + (LENGTH_KILOMETERS, 5), + (LENGTH_METERS, 5000), + (LENGTH_CENTIMETERS, 500000), + (LENGTH_MILES, 3.106855), + (LENGTH_YARD, 5468.066), + (LENGTH_FEET, 16404.2), + (LENGTH_INCHES, 196850.5), + ], +) +def test_convert_from_millimeters(unit, expected): """Test conversion from millimeters to other units.""" mm = 5000000 - assert distance_util.convert(mm, LENGTH_MILLIMETERS, LENGTH_KILOMETERS) == 5 - assert distance_util.convert(mm, LENGTH_MILLIMETERS, LENGTH_METERS) == 5000 - assert distance_util.convert(mm, LENGTH_MILLIMETERS, LENGTH_CENTIMETERS) == 500000 - assert distance_util.convert(mm, LENGTH_MILLIMETERS, LENGTH_MILES) == 3.106855 - assert distance_util.convert(mm, LENGTH_MILLIMETERS, LENGTH_YARD) == 5468.05 - assert distance_util.convert(mm, LENGTH_MILLIMETERS, LENGTH_FEET) == 16404.2 - assert distance_util.convert(mm, LENGTH_MILLIMETERS, LENGTH_INCHES) == 196850.5 + assert distance_util.convert(mm, LENGTH_MILLIMETERS, unit) == pytest.approx( + expected + ) diff --git a/tests/util/test_unit_system.py b/tests/util/test_unit_system.py index 954df07fc9d..c4cc94636b1 100644 --- a/tests/util/test_unit_system.py +++ b/tests/util/test_unit_system.py @@ -177,13 +177,17 @@ def test_length_unknown_unit(): def test_length_to_metric(): """Test length conversion to metric system.""" assert METRIC_SYSTEM.length(100, METRIC_SYSTEM.length_unit) == 100 - assert METRIC_SYSTEM.length(5, IMPERIAL_SYSTEM.length_unit) == 8.04672 + assert METRIC_SYSTEM.length(5, IMPERIAL_SYSTEM.length_unit) == pytest.approx( + 8.04672 + ) def test_length_to_imperial(): """Test length conversion to imperial system.""" assert IMPERIAL_SYSTEM.length(100, IMPERIAL_SYSTEM.length_unit) == 100 - assert IMPERIAL_SYSTEM.length(5, METRIC_SYSTEM.length_unit) == 3.106855 + assert IMPERIAL_SYSTEM.length(5, METRIC_SYSTEM.length_unit) == pytest.approx( + 3.106855 + ) def test_wind_speed_unknown_unit(): diff --git a/tests/util/test_volume.py b/tests/util/test_volume.py index 3cbf5b72130..f78d6c4ed18 100644 --- a/tests/util/test_volume.py +++ b/tests/util/test_volume.py @@ -42,28 +42,73 @@ def test_convert_nonnumeric_value(): def test_convert_from_liters(): """Test conversion from liters to other units.""" liters = 5 - assert volume_util.convert(liters, VOLUME_LITERS, VOLUME_GALLONS) == 1.321 + assert volume_util.convert(liters, VOLUME_LITERS, VOLUME_GALLONS) == pytest.approx( + 1.32086 + ) def test_convert_from_gallons(): """Test conversion from gallons to other units.""" gallons = 5 - assert volume_util.convert(gallons, VOLUME_GALLONS, VOLUME_LITERS) == 18.925 + assert volume_util.convert(gallons, VOLUME_GALLONS, VOLUME_LITERS) == pytest.approx( + 18.92706 + ) def test_convert_from_cubic_meters(): """Test conversion from cubic meter to other units.""" cubic_meters = 5 - assert ( - volume_util.convert(cubic_meters, VOLUME_CUBIC_METERS, VOLUME_CUBIC_FEET) - == 176.5733335 - ) + assert volume_util.convert( + cubic_meters, VOLUME_CUBIC_METERS, VOLUME_CUBIC_FEET + ) == pytest.approx(176.5733335) def test_convert_from_cubic_feet(): """Test conversion from cubic feet to cubic meters to other units.""" cubic_feets = 500 - assert ( - volume_util.convert(cubic_feets, VOLUME_CUBIC_FEET, VOLUME_CUBIC_METERS) - == 14.1584233 + assert volume_util.convert( + cubic_feets, VOLUME_CUBIC_FEET, VOLUME_CUBIC_METERS + ) == pytest.approx(14.1584233) + + +@pytest.mark.parametrize( + "source_unit,target_unit,expected", + [ + (VOLUME_CUBIC_FEET, VOLUME_CUBIC_METERS, 14.1584233), + (VOLUME_CUBIC_FEET, VOLUME_FLUID_OUNCE, 478753.2467), + (VOLUME_CUBIC_FEET, VOLUME_GALLONS, 3740.25974), + (VOLUME_CUBIC_FEET, VOLUME_LITERS, 14158.42329599), + (VOLUME_CUBIC_FEET, VOLUME_MILLILITERS, 14158423.29599), + (VOLUME_CUBIC_METERS, VOLUME_CUBIC_METERS, 500), + (VOLUME_CUBIC_METERS, VOLUME_FLUID_OUNCE, 16907011.35), + (VOLUME_CUBIC_METERS, VOLUME_GALLONS, 132086.02617), + (VOLUME_CUBIC_METERS, VOLUME_LITERS, 500000), + (VOLUME_CUBIC_METERS, VOLUME_MILLILITERS, 500000000), + (VOLUME_FLUID_OUNCE, VOLUME_CUBIC_FEET, 0.52218967), + (VOLUME_FLUID_OUNCE, VOLUME_CUBIC_METERS, 0.014786764), + (VOLUME_FLUID_OUNCE, VOLUME_GALLONS, 3.90625), + (VOLUME_FLUID_OUNCE, VOLUME_LITERS, 14.786764), + (VOLUME_FLUID_OUNCE, VOLUME_MILLILITERS, 14786.764), + (VOLUME_GALLONS, VOLUME_CUBIC_FEET, 66.84027), + (VOLUME_GALLONS, VOLUME_CUBIC_METERS, 1.892706), + (VOLUME_GALLONS, VOLUME_FLUID_OUNCE, 64000), + (VOLUME_GALLONS, VOLUME_LITERS, 1892.70589), + (VOLUME_GALLONS, VOLUME_MILLILITERS, 1892705.89), + (VOLUME_LITERS, VOLUME_CUBIC_FEET, 17.65733), + (VOLUME_LITERS, VOLUME_CUBIC_METERS, 0.5), + (VOLUME_LITERS, VOLUME_FLUID_OUNCE, 16907.011), + (VOLUME_LITERS, VOLUME_GALLONS, 132.086), + (VOLUME_LITERS, VOLUME_MILLILITERS, 500000), + (VOLUME_MILLILITERS, VOLUME_CUBIC_FEET, 0.01765733), + (VOLUME_MILLILITERS, VOLUME_CUBIC_METERS, 0.0005), + (VOLUME_MILLILITERS, VOLUME_FLUID_OUNCE, 16.907), + (VOLUME_MILLILITERS, VOLUME_GALLONS, 0.132086), + (VOLUME_MILLILITERS, VOLUME_LITERS, 0.5), + ], +) +def test_convert(source_unit, target_unit, expected): + """Test conversion between units.""" + value = 500 + assert volume_util.convert(value, source_unit, target_unit) == pytest.approx( + expected )