Testing#
It is highly recommended to write tests for your contribution. This ensures that your code works as expected and helps maintain the quality of the project.
Running Tests#
To run the tests, you can use the following command:
uv sync --extra dev
uv run pytest
Using Shared Fixtures#
Shared test fixtures are defined in tests/juice/conftest.py. Declare them as function parameters — pytest injects them automatically.
Mocking the Database#
Two fixtures cover InfluxDB interactions:
mock_write_api— a spec’dWriteApimock with.writereturningNonemock_query_api— a spec’dQueryApimock with.queryreturningNone
Writing to the database:
from influxdb_client import WriteApi
def test_my_write(mock_write_api: WriteApi) -> None:
my_function(write_api=mock_write_api)
mock_write_api.write.assert_called_once()
_, kwargs = mock_write_api.write.call_args
assert kwargs["bucket"] == "expected_bucket"
Querying the database:
By default mock_query_api.query_data_frame returns None. Set a return value before calling your function when you need the query to return data:
import pandas as pd
from influxdb_client.client.query_api import QueryApi
def test_my_query(mock_query_api: QueryApi) -> None:
mock_query_api.query_data_frame.return_value = pd.DataFrame({"value": [1.0, 2.0]}) # type: ignore
result = my_function(query_api=mock_query_api)
mock_query_api.query_data_frame.assert_called_once() # type: ignore
assert result is not None
Mocking the Publisher#
mock_publisher_async provides a Mock with an AsyncMock .publish method, suitable for testing any code that publishes messages.
from unittest.mock import Mock
async def test_my_publisher(mock_publisher_async: Mock) -> None:
await my_function(publisher=mock_publisher_async)
mock_publisher_async.publish.assert_called_once()
To verify the published payload:
async def test_publish_payload(mock_publisher_async: Mock) -> None:
await my_function(publisher=mock_publisher_async)
_, kwargs = mock_publisher_async.publish.call_args
assert kwargs["topic"] == "expected_topic"
Patching Module-Level Dependencies#
When your code under test calls module-level factory functions (e.g. influxdb2_write_api()) rather than accepting the API as a parameter, use monkeypatch to replace them with the mock fixtures:
import pytest
from unittest.mock import Mock
from influxdb_client import WriteApi
from influxdb_client.client.query_api import QueryApi
import my_module
@pytest.fixture(autouse=True)
async def setup_mocks(
mock_publisher_async: Mock,
mock_write_api: WriteApi,
mock_query_api: QueryApi,
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.setattr(my_module, "influxdb2_query_api", lambda: mock_query_api)
monkeypatch.setattr(my_module, "influxdb2_write_api", lambda: mock_write_api)
monkeypatch.setattr(my_module, "publisher_async", lambda: mock_publisher_async)
With this autouse fixture in place, every test in the module automatically gets the mocks injected without repeating the patching.