core/tests/components/plant/test_init.py

227 lines
7.8 KiB
Python
Raw Normal View History

"""Unit tests for platform/plant.py."""
from datetime import datetime, timedelta
import homeassistant.components.plant as plant
from homeassistant.components.recorder import Recorder
2019-07-31 19:25:30 +00:00
from homeassistant.const import (
ATTR_UNIT_OF_MEASUREMENT,
CONDUCTIVITY,
LIGHT_LUX,
STATE_OK,
STATE_PROBLEM,
2019-07-31 19:25:30 +00:00
STATE_UNAVAILABLE,
)
from homeassistant.core import HomeAssistant, State
2020-04-28 17:31:22 +00:00
from homeassistant.setup import async_setup_component
plant - check history for min_brightness (#9534) * Added option to create a group for the plant and all of it's sensors so that they appear together in the UI * fixed warnings from the hound * added check for min_brightness over several days * fixed hound complaints * 1) added missing dependency on recorder 2) using group.Group instead of hass.states.async_set as requested by @pvizeli * fixed pylint error in docstring * changed the way the groups are created * fixed requirements issue * Changed the way the groups are implemented. This is proposal number 4... * Data read from recorder only on startup. We now only store one data point per day. If a recorder is configured, this data is initialized from the database. If not the list is empty on startup. * added missing documentation * fixed typo in comment * removed group fature * added group dependency since it's still needed * fixed bug: now "None" is no longer added to the DailyHistory * now also outputting unit of measurement if defined by the sensors * removed iconss * fixed line length * Implemented changes requested in code reviews. These changes affect the interface to the UI: * renamed attribute for units of measurement to "unit_of_measurement_dict" * renamed attribute for maximum in brightness history to "max_brightness" * only loading the history if a brightness sensor was configured * fixed testcase * fixed stupid bug in check of brightness history Also added test for this bug * added missing docstring * Fixed sporadic failure in test case. Sometimes the component was created before the data was stored in the history. This lead to an empty history being read. * removed unused import statement in testcase * reverted change to test case * Changed startup behavior of the component. No failed tests after 20 local test runs. * added missing docstring * fixed tests * added hass.start() to Setup * fixed call parameters in constructor * added time.sleep * removed sleep * fixed typo in variable name * disabled loading from database as it's not stable at the moment and nobody knows why :( * fixed flake8 * now using pytest.mark.skipif to skip test
2018-01-19 07:46:12 +00:00
from tests.components.recorder.common import async_wait_recording_done
GOOD_DATA = {
2019-07-31 19:25:30 +00:00
"moisture": 50,
"battery": 90,
"temperature": 23.4,
"conductivity": 777,
"brightness": 987,
}
2019-07-31 19:25:30 +00:00
BRIGHTNESS_ENTITY = "sensor.mqtt_plant_brightness"
MOISTURE_ENTITY = "sensor.mqtt_plant_moisture"
plant - check history for min_brightness (#9534) * Added option to create a group for the plant and all of it's sensors so that they appear together in the UI * fixed warnings from the hound * added check for min_brightness over several days * fixed hound complaints * 1) added missing dependency on recorder 2) using group.Group instead of hass.states.async_set as requested by @pvizeli * fixed pylint error in docstring * changed the way the groups are created * fixed requirements issue * Changed the way the groups are implemented. This is proposal number 4... * Data read from recorder only on startup. We now only store one data point per day. If a recorder is configured, this data is initialized from the database. If not the list is empty on startup. * added missing documentation * fixed typo in comment * removed group fature * added group dependency since it's still needed * fixed bug: now "None" is no longer added to the DailyHistory * now also outputting unit of measurement if defined by the sensors * removed iconss * fixed line length * Implemented changes requested in code reviews. These changes affect the interface to the UI: * renamed attribute for units of measurement to "unit_of_measurement_dict" * renamed attribute for maximum in brightness history to "max_brightness" * only loading the history if a brightness sensor was configured * fixed testcase * fixed stupid bug in check of brightness history Also added test for this bug * added missing docstring * Fixed sporadic failure in test case. Sometimes the component was created before the data was stored in the history. This lead to an empty history being read. * removed unused import statement in testcase * reverted change to test case * Changed startup behavior of the component. No failed tests after 20 local test runs. * added missing docstring * fixed tests * added hass.start() to Setup * fixed call parameters in constructor * added time.sleep * removed sleep * fixed typo in variable name * disabled loading from database as it's not stable at the moment and nobody knows why :( * fixed flake8 * now using pytest.mark.skipif to skip test
2018-01-19 07:46:12 +00:00
GOOD_CONFIG = {
2019-07-31 19:25:30 +00:00
"sensors": {
"moisture": MOISTURE_ENTITY,
"battery": "sensor.mqtt_plant_battery",
"temperature": "sensor.mqtt_plant_temperature",
"conductivity": "sensor.mqtt_plant_conductivity",
"brightness": BRIGHTNESS_ENTITY,
},
2019-07-31 19:25:30 +00:00
"min_moisture": 20,
"max_moisture": 60,
"min_battery": 17,
"min_conductivity": 500,
"min_temperature": 15,
"min_brightness": 500,
}
async def test_valid_data(hass: HomeAssistant) -> None:
2020-04-28 17:31:22 +00:00
"""Test processing valid data."""
sensor = plant.Plant("my plant", GOOD_CONFIG)
sensor.entity_id = "sensor.mqtt_plant_battery"
sensor.hass = hass
for reading, value in GOOD_DATA.items():
2019-07-31 19:25:30 +00:00
sensor.state_changed(
2020-04-28 17:31:22 +00:00
GOOD_CONFIG["sensors"][reading],
State(GOOD_CONFIG["sensors"][reading], value),
2019-07-31 19:25:30 +00:00
)
2020-04-28 17:31:22 +00:00
assert sensor.state == "ok"
attrib = sensor.extra_state_attributes
2020-04-28 17:31:22 +00:00
for reading, value in GOOD_DATA.items():
# battery level has a different name in
# the JSON format than in hass
assert attrib[reading] == value
async def test_low_battery(hass: HomeAssistant) -> None:
2020-04-28 17:31:22 +00:00
"""Test processing with low battery data and limit set."""
sensor = plant.Plant("other plant", GOOD_CONFIG)
sensor.entity_id = "sensor.mqtt_plant_battery"
sensor.hass = hass
assert sensor.extra_state_attributes["problem"] == "none"
2020-04-28 17:31:22 +00:00
sensor.state_changed(
2020-08-27 11:56:20 +00:00
"sensor.mqtt_plant_battery",
State("sensor.mqtt_plant_battery", 10),
2020-04-28 17:31:22 +00:00
)
assert sensor.state == "problem"
assert sensor.extra_state_attributes["problem"] == "battery low"
plant - check history for min_brightness (#9534) * Added option to create a group for the plant and all of it's sensors so that they appear together in the UI * fixed warnings from the hound * added check for min_brightness over several days * fixed hound complaints * 1) added missing dependency on recorder 2) using group.Group instead of hass.states.async_set as requested by @pvizeli * fixed pylint error in docstring * changed the way the groups are created * fixed requirements issue * Changed the way the groups are implemented. This is proposal number 4... * Data read from recorder only on startup. We now only store one data point per day. If a recorder is configured, this data is initialized from the database. If not the list is empty on startup. * added missing documentation * fixed typo in comment * removed group fature * added group dependency since it's still needed * fixed bug: now "None" is no longer added to the DailyHistory * now also outputting unit of measurement if defined by the sensors * removed iconss * fixed line length * Implemented changes requested in code reviews. These changes affect the interface to the UI: * renamed attribute for units of measurement to "unit_of_measurement_dict" * renamed attribute for maximum in brightness history to "max_brightness" * only loading the history if a brightness sensor was configured * fixed testcase * fixed stupid bug in check of brightness history Also added test for this bug * added missing docstring * Fixed sporadic failure in test case. Sometimes the component was created before the data was stored in the history. This lead to an empty history being read. * removed unused import statement in testcase * reverted change to test case * Changed startup behavior of the component. No failed tests after 20 local test runs. * added missing docstring * fixed tests * added hass.start() to Setup * fixed call parameters in constructor * added time.sleep * removed sleep * fixed typo in variable name * disabled loading from database as it's not stable at the moment and nobody knows why :( * fixed flake8 * now using pytest.mark.skipif to skip test
2018-01-19 07:46:12 +00:00
2020-04-28 17:31:22 +00:00
async def test_initial_states(hass: HomeAssistant) -> None:
2020-04-28 17:31:22 +00:00
"""Test plant initialises attributes if sensor already exists."""
hass.states.async_set(MOISTURE_ENTITY, 5, {ATTR_UNIT_OF_MEASUREMENT: CONDUCTIVITY})
plant_name = "some_plant"
assert await async_setup_component(
hass, plant.DOMAIN, {plant.DOMAIN: {plant_name: GOOD_CONFIG}}
2019-07-31 19:25:30 +00:00
)
2020-04-28 17:31:22 +00:00
await hass.async_block_till_done()
state = hass.states.get(f"plant.{plant_name}")
assert state.attributes[plant.READING_MOISTURE] == 5
2020-04-28 17:31:22 +00:00
async def test_update_states(hass: HomeAssistant) -> None:
2020-04-28 17:31:22 +00:00
"""Test updating the state of a sensor.
Make sure that plant processes this correctly.
"""
plant_name = "some_plant"
assert await async_setup_component(
hass, plant.DOMAIN, {plant.DOMAIN: {plant_name: GOOD_CONFIG}}
)
hass.states.async_set(MOISTURE_ENTITY, 5, {ATTR_UNIT_OF_MEASUREMENT: CONDUCTIVITY})
await hass.async_block_till_done()
state = hass.states.get(f"plant.{plant_name}")
assert state.state == STATE_PROBLEM
assert state.attributes[plant.READING_MOISTURE] == 5
2020-04-28 17:31:22 +00:00
async def test_unavailable_state(hass: HomeAssistant) -> None:
2020-04-28 17:31:22 +00:00
"""Test updating the state with unavailable.
Make sure that plant processes this correctly.
"""
plant_name = "some_plant"
assert await async_setup_component(
hass, plant.DOMAIN, {plant.DOMAIN: {plant_name: GOOD_CONFIG}}
)
hass.states.async_set(
MOISTURE_ENTITY, STATE_UNAVAILABLE, {ATTR_UNIT_OF_MEASUREMENT: CONDUCTIVITY}
)
await hass.async_block_till_done()
state = hass.states.get(f"plant.{plant_name}")
assert state.state == STATE_PROBLEM
assert state.attributes[plant.READING_MOISTURE] == STATE_UNAVAILABLE
async def test_state_problem_if_unavailable(hass: HomeAssistant) -> None:
2020-04-28 17:31:22 +00:00
"""Test updating the state with unavailable after setting it to valid value.
Make sure that plant processes this correctly.
"""
plant_name = "some_plant"
assert await async_setup_component(
hass, plant.DOMAIN, {plant.DOMAIN: {plant_name: GOOD_CONFIG}}
)
hass.states.async_set(MOISTURE_ENTITY, 42, {ATTR_UNIT_OF_MEASUREMENT: CONDUCTIVITY})
await hass.async_block_till_done()
state = hass.states.get(f"plant.{plant_name}")
assert state.state == STATE_OK
assert state.attributes[plant.READING_MOISTURE] == 42
hass.states.async_set(
MOISTURE_ENTITY, STATE_UNAVAILABLE, {ATTR_UNIT_OF_MEASUREMENT: CONDUCTIVITY}
)
await hass.async_block_till_done()
state = hass.states.get(f"plant.{plant_name}")
assert state.state == STATE_PROBLEM
assert state.attributes[plant.READING_MOISTURE] == STATE_UNAVAILABLE
async def test_load_from_db(recorder_mock: Recorder, hass: HomeAssistant) -> None:
2020-04-28 17:31:22 +00:00
"""Test bootstrapping the brightness history from the database.
This test can should only be executed if the loading of the history
is enabled via plant.ENABLE_LOAD_HISTORY.
"""
plant_name = "wise_plant"
for value in [20, 30, 10]:
hass.states.async_set(
BRIGHTNESS_ENTITY, value, {ATTR_UNIT_OF_MEASUREMENT: "Lux"}
2019-07-31 19:25:30 +00:00
)
2020-04-28 17:31:22 +00:00
await hass.async_block_till_done()
# wait for the recorder to really store the data
await async_wait_recording_done(hass)
2020-04-28 17:31:22 +00:00
assert await async_setup_component(
hass, plant.DOMAIN, {plant.DOMAIN: {plant_name: GOOD_CONFIG}}
)
await hass.async_block_till_done()
state = hass.states.get(f"plant.{plant_name}")
assert state.state == STATE_PROBLEM
2020-04-28 17:31:22 +00:00
max_brightness = state.attributes.get(plant.ATTR_MAX_BRIGHTNESS_HISTORY)
assert max_brightness == 30
2020-04-28 17:31:22 +00:00
async def test_brightness_history(hass: HomeAssistant) -> None:
2020-04-28 17:31:22 +00:00
"""Test the min_brightness check."""
plant_name = "some_plant"
assert await async_setup_component(
hass, plant.DOMAIN, {plant.DOMAIN: {plant_name: GOOD_CONFIG}}
)
hass.states.async_set(BRIGHTNESS_ENTITY, 100, {ATTR_UNIT_OF_MEASUREMENT: LIGHT_LUX})
2020-04-28 17:31:22 +00:00
await hass.async_block_till_done()
state = hass.states.get(f"plant.{plant_name}")
assert state.state == STATE_PROBLEM
2020-04-28 17:31:22 +00:00
hass.states.async_set(BRIGHTNESS_ENTITY, 600, {ATTR_UNIT_OF_MEASUREMENT: LIGHT_LUX})
2020-04-28 17:31:22 +00:00
await hass.async_block_till_done()
state = hass.states.get(f"plant.{plant_name}")
assert state.state == STATE_OK
2020-04-28 17:31:22 +00:00
hass.states.async_set(BRIGHTNESS_ENTITY, 100, {ATTR_UNIT_OF_MEASUREMENT: LIGHT_LUX})
2020-04-28 17:31:22 +00:00
await hass.async_block_till_done()
state = hass.states.get(f"plant.{plant_name}")
assert state.state == STATE_OK
2020-04-28 17:31:22 +00:00
def test_daily_history_no_data(hass: HomeAssistant) -> None:
2020-04-28 17:31:22 +00:00
"""Test with empty history."""
dh = plant.DailyHistory(3)
assert dh.max is None
def test_daily_history_one_day(hass: HomeAssistant) -> None:
2020-04-28 17:31:22 +00:00
"""Test storing data for the same day."""
dh = plant.DailyHistory(3)
values = [-2, 10, 0, 5, 20]
for i in range(len(values)):
dh.add_measurement(values[i])
max_value = max(values[0 : i + 1])
assert len(dh._days) == 1
2020-04-28 17:31:22 +00:00
assert dh.max == max_value
def test_daily_history_multiple_days(hass: HomeAssistant) -> None:
2020-04-28 17:31:22 +00:00
"""Test storing data for different days."""
dh = plant.DailyHistory(3)
today = datetime.now()
today_minus_1 = today - timedelta(days=1)
today_minus_2 = today_minus_1 - timedelta(days=1)
today_minus_3 = today_minus_2 - timedelta(days=1)
days = [today_minus_3, today_minus_2, today_minus_1, today]
values = [10, 1, 7, 3]
max_values = [10, 10, 10, 7]
for i in range(len(days)):
dh.add_measurement(values[i], days[i])
assert max_values[i] == dh.max