Automatic test for custom integration - how to use recorder / REST API

Hi,

I am currently having a hard time to write tests for my custom integration to import long-term statistics.

Pytest is working, and I can test local methods.

But I would like to test if the import of statistical data really worked, and the imported data are available in the HA database. For that, I have to at least get the recorder up and running from the test (the recorder is of course a dependency of the import integration). And the only way to read the historical data I found is the HA REST API, so I would need this as well.

But I did not even manage to setup the recorder. When I do this:

async def test_async_setup(hass):
    """Test the component gets setup."""
    assert await async_setup_component(hass, DOMAIN, {}) is True

I get this:

tests/test_test.py:16: AssertionError
----------------------------------------------------------------------------- Captured stderr call -----------------------------------------------------------------------------
INFO:homeassistant.loader:Loaded import_statistics from custom_components.import_statistics
WARNING:homeassistant.loader:We found a custom integration import_statistics which has not been tested by Home Assistant. This component might cause stability problems, be sure to disable it if you experience issues with Home Assistant
INFO:homeassistant.loader:Loaded recorder from homeassistant.components.recorder
INFO:homeassistant.setup:Setting up recorder
ERROR:homeassistant.setup:Error during setup of component recorder
Traceback (most recent call last):
  File "/home/vscode/.local/lib/python3.11/site-packages/homeassistant/setup.py", line 333, in _async_setup_component
    result = await task
             ^^^^^^^^^^
  File "/home/vscode/.local/lib/python3.11/site-packages/homeassistant/components/recorder/__init__.py", line 152, in async_setup
    instance = hass.data[DATA_INSTANCE] = Recorder(
                                          ^^^^^^^^^
  File "/home/vscode/.local/lib/python3.11/site-packages/homeassistant/components/recorder/core.py", line 198, in __init__
    db_connected: asyncio.Future[bool] = hass.data[DOMAIN].db_connected
                                         ~~~~~~~~~^^^^^^^^
KeyError: 'recorder'
ERROR:homeassistant.setup:Unable to set up dependencies of 'import_statistics'. Setup failed for dependencies: recorder
ERROR:homeassistant.setup:Setup failed for custom integration 'import_statistics': (DependencyError(...), 'Could not setup dependencies: recorder')

(repo see https://github.com/klausj1/homeassistant-statistics/tree/addtests)

Probably I need the whole HA core up and running, but I have no idea how to do this.

Can please somebody help for the above problem, and also for the REST API (or point me to a better API to read long term statistical data)?

Thanks!

I think you should use recorder_mock eg async def test_async_setup(recorder_mock, hass):

Thanks for pointing me to that.

I think I got the point, please confirm:

  • For unit-tests, use recorder_mock. In these tests, I will not initialize my custom integration at all (it anyhow throws an error, see above), but call the method implementing the service directly, and check the result via recorder_mock
  • In addition, I would like to create an integration test, which uses a running HA instance. For this, I would start HA in a separate process, call the service via REST and check the DB content via REST

Does that make sense?

The proper way of testing is always to setup hass and then assert what should be happening.
Just with the fixtures the sequence has a point so both recorder_mock and the one for enabling custom components (don’t remember the fixture name now) should go before hass.

Thanks, I appreciate your support, but I really would need a documentation or an example.

When I use recorder_mock like in your proposal:

async def test_main(recorder_mock, hass):

I get this error, even without any code in the method:

pytestconfig = <_pytest.config.Config object at 0x7f9415e290d0>, hass_fixture_setup = [True]

    @pytest.fixture
    def recorder_db_url(
        pytestconfig: pytest.Config,
        hass_fixture_setup: list[bool],
    ) -> Generator[str, None, None]:
        """Prepare a default database for tests and return a connection URL."""
>       assert not hass_fixture_setup
E       assert not [True]

/home/vscode/.local/lib/python3.11/site-packages/pytest_homeassistant_custom_component/plugins.py:1253: AssertionError

I also tried this:

@pytest.mark.parametrize("recorder_config", [{recorder.CONF_DB_URL: "sqlite://no_file", recorder.CONF_AUTO_PURGE: False }])
async def test_main(recorder_mock, hass):

But this does not make a difference.

Take a look at the sql integration tests in core to see examples how to use it.