diff --git a/api/main.py b/api/main.py index 95103f0..53cc9a9 100644 --- a/api/main.py +++ b/api/main.py @@ -38,6 +38,8 @@ async def get_current_price(): "price_eur_mwh": res[1], "price_ct_kwh": round(res[1] / 10, 2) } + except HTTPException: + raise except Exception as e: raise HTTPException(status_code=500, detail=f"Database error: {str(e)}") diff --git a/pyproject.toml b/pyproject.toml index 29331c4..4286830 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,6 +33,7 @@ testpaths = ["tests"] [dependency-groups] dev = [ + "httpx>=0.28.1", "pytest>=9.0.2", "pytest-mock>=3.15.1", "requests-mock>=1.12.1", diff --git a/tests/test_api.py b/tests/test_api.py new file mode 100644 index 0000000..3fe97c9 --- /dev/null +++ b/tests/test_api.py @@ -0,0 +1,20 @@ +from fastapi.testclient import TestClient +from api.main import app +import pytest + +client = TestClient(app) + +def test_get_status(): + response = client.get("/status") + assert response.status_code == 200 + assert response.json()["status"] == "operational" + +def test_get_current_price_no_data(mocker): + # Mock database connection to return no data + mock_db = mocker.patch("utils.database.get_connection") + mock_con = mock_db.return_value.__enter__.return_value + mock_con.execute.return_value.fetchone.return_value = None + + response = client.get("/current-price") + assert response.status_code == 404 + assert response.json()["detail"] == "No data available" diff --git a/tests/test_pricing.py b/tests/test_pricing.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/test_smard.py b/tests/test_smard.py new file mode 100644 index 0000000..1afce15 --- /dev/null +++ b/tests/test_smard.py @@ -0,0 +1,20 @@ +import polars as pl +import requests_mock +from collectors.smard import fetch_smard_data + +def test_fetch_smard_data(): + with requests_mock.Mocker() as m: + # Mock index call + m.get("https://www.smard.de/app/chart_data/4169/DE-LU/index_hour.json", + json={"timestamps": [1700000000000]}) + # Mock data call + m.get("https://www.smard.de/app/chart_data/4169/DE-LU/4169_DE-LU_hour_1700000000000.json", + json={ + "series": [[1700000000000, 50.0], [1700003600000, 60.0]] + }) + + df = fetch_smard_data(filter_id=4169) + assert isinstance(df, pl.DataFrame) + assert df.shape == (2, 2) + assert "value" in df.columns + assert df["value"][0] == 50.0 diff --git a/tests/test_transformator.py b/tests/test_transformator.py index e69de29..4c18088 100644 --- a/tests/test_transformator.py +++ b/tests/test_transformator.py @@ -0,0 +1,28 @@ +import polars as pl +from transformators.transformator import ( + transform_prices, + transform_weather, +) + +def test_transform_prices(): + df = pl.DataFrame({ + "timestamp": [1700000000000], + "value": [50.0] + }) + transformed = transform_prices(df) + assert transformed.shape == (1, 2) + assert transformed["timestamp"].dtype == pl.Datetime("ms", time_zone="UTC") + +def test_transform_weather(): + df = pl.DataFrame({ + "timestamp": ["2023-11-14T22:13:20+00:00"], + "temperature": [10.5], + "wind_speed": [5.0], + "solar": [0.0], + "sunshine": [0.0], + "cloud_cover": [0.0], + "precipitation": [0.0] + }) + transformed = transform_weather(df) + assert transformed.shape == (1, 7) + assert transformed["timestamp"].dtype == pl.Datetime("ms", time_zone="UTC") diff --git a/tests/test_weather.py b/tests/test_weather.py index e69de29..02e41fc 100644 --- a/tests/test_weather.py +++ b/tests/test_weather.py @@ -0,0 +1,27 @@ +import polars as pl +import requests_mock +from collectors.weather import fetch_weather + +def test_fetch_weather(): + with requests_mock.Mocker() as m: + m.get("https://api.brightsky.dev/weather", json={ + "weather": [ + { + "timestamp": "2023-11-14T22:13:20+00:00", + "temperature": 10.5, + "wind_speed": 5.0, + "solar": 0.0, + "sunshine": 0.0, + "cloud_cover": 0.0, + "precipitation": 0.0, + "extra_field": "should_be_filtered" + } + ] + }) + + df = fetch_weather() + assert isinstance(df, pl.DataFrame) + # Check that it filtered to the schema columns (7 columns) + assert df.shape == (1, 7) + assert "temperature" in df.columns + assert "extra_field" not in df.columns diff --git a/uv.lock b/uv.lock index 2bf2be1..5192140 100644 --- a/uv.lock +++ b/uv.lock @@ -268,6 +268,34 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, ] +[[package]] +name = "httpcore" +version = "1.0.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, +] + +[[package]] +name = "httpx" +version = "0.28.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "certifi" }, + { name = "httpcore" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, +] + [[package]] name = "idna" version = "3.11" @@ -1255,6 +1283,7 @@ dependencies = [ [package.dev-dependencies] dev = [ + { name = "httpx" }, { name = "pytest" }, { name = "pytest-mock" }, { name = "requests-mock" }, @@ -1279,6 +1308,7 @@ requires-dist = [ [package.metadata.requires-dev] dev = [ + { name = "httpx", specifier = ">=0.28.1" }, { name = "pytest", specifier = ">=9.0.2" }, { name = "pytest-mock", specifier = ">=3.15.1" }, { name = "requests-mock", specifier = ">=1.12.1" },