diff --git a/pyproject.toml b/pyproject.toml index 7460049..546d703 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,6 +12,8 @@ dependencies = [ "pandas>=2.3.2", "pydantic>=2.11.9", "pydantic-settings>=2.10.1", + "pytest>=8.4.2", + "pytest-asyncio>=1.2.0", "pyyaml>=6.0.2", "sqlalchemy>=2.0.43", "uvicorn>=0.37.0", diff --git a/src/settings.py b/src/settings.py index a43ee7d..5ea5512 100644 --- a/src/settings.py +++ b/src/settings.py @@ -1,12 +1,16 @@ """General application settings.""" from pydantic import Field -from pydantic_settings import BaseSettings +from pydantic_settings import BaseSettings, SettingsConfigDict class Settings(BaseSettings): """Application settings.""" + model_config = SettingsConfigDict( + env_file=".env", env_file_encoding="utf-8", extra="ignore" + ) + # --- General Settings --- # Preprocessing configuration file path. diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/dataprocessor/__init__.py b/tests/dataprocessor/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/dataprocessor/domain/__init__.py b/tests/dataprocessor/domain/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/dataprocessor/domain/test_powerbi_reader.py b/tests/dataprocessor/domain/test_powerbi_reader.py new file mode 100644 index 0000000..bdd938f --- /dev/null +++ b/tests/dataprocessor/domain/test_powerbi_reader.py @@ -0,0 +1,50 @@ +"""Simple development test for PowerBIReader.read_data()""" + +import pytest + +from src.dataprocessor.domain.powerbi_reader import PowerBIReader +from src.settings import settings + + +@pytest.mark.asyncio +async def test_read_data_prints_dataframe_info() -> None: + """Test PowerBIReader.read_data() and print DataFrame info for development.""" + # Get access token + print("\nGetting access token...") + access_token = await PowerBIReader._get_access_token_async( + tenant_id=settings.POWERBI_TENANT_ID, + client_id=settings.POWERBI_CLIENT_ID, + client_secret=settings.POWERBI_CLIENT_SECRET, + ) + print("✓ Access token acquired") + + # Create PowerBIReader instance + print("Creating PowerBIReader instance...") + reader = await PowerBIReader.create( + dataset_id=settings.POWERBI_DATASET_ID, + access_token=access_token, + table_name=settings.POWERBI_TABLE_NAME, + ) + print(f"✓ Reader created for table: {settings.POWERBI_TABLE_NAME}") + + # Call read_data() once + print("Fetching data from Power BI...") + df = await reader.read_data() + print("✓ Data fetched successfully") + + # Print DataFrame information + print("=" * 80) + print("DATAFRAME INFO") + print("=" * 80) + print(f"\nShape: {df.shape}") + print(f"Columns: {df.columns.tolist()}") + print(f"\nData Types:\n{df.dtypes}") + print("\n" + "=" * 80) + print("DATAFRAME HEAD (5 rows)") + print("=" * 80) + print(df.head(5)) + print("\n") + + # Basic assertions to make it a valid test + assert df is not None + assert len(df.columns) > 0 diff --git a/uv.lock b/uv.lock index 748faf3..2e1e780 100644 --- a/uv.lock +++ b/uv.lock @@ -282,6 +282,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" }, ] +[[package]] +name = "iniconfig" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793, upload-time = "2025-03-19T20:09:59.721Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" }, +] + [[package]] name = "msal" version = "1.34.0" @@ -348,6 +357,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/06/b9/33bba5ff6fb679aa0b1f8a07e853f002a6b04b9394db3069a1270a7784ca/numpy-2.3.3-cp314-cp314t-win_arm64.whl", hash = "sha256:78c9f6560dc7e6b3990e32df7ea1a50bbd0e2a111e05209963f5ddcab7073b0b", size = 10545953, upload-time = "2025-09-09T15:58:40.576Z" }, ] +[[package]] +name = "packaging" +version = "25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, +] + [[package]] name = "pandas" version = "2.3.2" @@ -375,6 +393,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/cd/d7/612123674d7b17cf345aad0a10289b2a384bff404e0463a83c4a3a59d205/pandas-2.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d2c3554bd31b731cd6490d94a28f3abb8dd770634a9e06eb6d2911b9827db370", size = 13186141, upload-time = "2025-08-21T10:28:05.377Z" }, ] +[[package]] +name = "pluggy" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, +] + [[package]] name = "pycparser" version = "2.23" @@ -441,6 +468,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/58/f0/427018098906416f580e3cf1366d3b1abfb408a0652e9f31600c24a1903c/pydantic_settings-2.10.1-py3-none-any.whl", hash = "sha256:a60952460b99cf661dc25c29c0ef171721f98bfcb52ef8d9ea4c943d7c8cc796", size = 45235, upload-time = "2025-06-24T13:26:45.485Z" }, ] +[[package]] +name = "pygments" +version = "2.19.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, +] + [[package]] name = "pyjwt" version = "2.10.1" @@ -455,6 +491,34 @@ crypto = [ { name = "cryptography" }, ] +[[package]] +name = "pytest" +version = "8.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a3/5c/00a0e072241553e1a7496d638deababa67c5058571567b92a7eaa258397c/pytest-8.4.2.tar.gz", hash = "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01", size = 1519618, upload-time = "2025-09-04T14:34:22.711Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a8/a4/20da314d277121d6534b3a980b29035dcd51e6744bd79075a6ce8fa4eb8d/pytest-8.4.2-py3-none-any.whl", hash = "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79", size = 365750, upload-time = "2025-09-04T14:34:20.226Z" }, +] + +[[package]] +name = "pytest-asyncio" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/42/86/9e3c5f48f7b7b638b216e4b9e645f54d199d7abbbab7a64a13b4e12ba10f/pytest_asyncio-1.2.0.tar.gz", hash = "sha256:c609a64a2a8768462d0c99811ddb8bd2583c33fd33cf7f21af1c142e824ffb57", size = 50119, upload-time = "2025-09-12T07:33:53.816Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/93/2fa34714b7a4ae72f2f8dad66ba17dd9a2c793220719e736dda28b7aec27/pytest_asyncio-1.2.0-py3-none-any.whl", hash = "sha256:8e17ae5e46d8e7efe51ab6494dd2010f4ca8dae51652aa3c8d55acf50bfb2e99", size = 15095, upload-time = "2025-09-12T07:33:52.639Z" }, +] + [[package]] name = "python-dateutil" version = "2.9.0.post0" @@ -632,6 +696,8 @@ dependencies = [ { name = "pandas" }, { name = "pydantic" }, { name = "pydantic-settings" }, + { name = "pytest" }, + { name = "pytest-asyncio" }, { name = "pyyaml" }, { name = "sqlalchemy" }, { name = "uvicorn" }, @@ -646,6 +712,8 @@ requires-dist = [ { name = "pandas", specifier = ">=2.3.2" }, { name = "pydantic", specifier = ">=2.11.9" }, { name = "pydantic-settings", specifier = ">=2.10.1" }, + { name = "pytest", specifier = ">=8.4.2" }, + { name = "pytest-asyncio", specifier = ">=1.2.0" }, { name = "pyyaml", specifier = ">=6.0.2" }, { name = "sqlalchemy", specifier = ">=2.0.43" }, { name = "uvicorn", specifier = ">=0.37.0" },