diff --git a/export/progress.md b/export/progress.md index 94cea7e..5a0019d 100644 --- a/export/progress.md +++ b/export/progress.md @@ -8,13 +8,13 @@ | Metrica | Valore | |---------|--------| -| **Stato** | 🟡 In Progress | -| **Progresso** | 5% | +| **Stato** | 🟢 Setup Completato | +| **Progresso** | 7% | | **Data Inizio** | 2024-04-07 | | **Data Target** | TBD | | **Task Totali** | 74 | -| **Task Completati** | 4 | -| **Task In Progress** | 1 | +| **Task Completati** | 5 | +| **Task In Progress** | 0 | --- @@ -37,12 +37,12 @@ ## 📋 Task Pianificate -### 🔧 Setup Progetto (T01-T05) - 4/5 completati +### 🔧 Setup Progetto (T01-T05) - 5/5 completati - [x] T01: Creare struttura cartelle progetto (2024-04-07) - [x] T02: Inizializzare virtual environment e .gitignore (2024-04-07) - [x] T03: Creare requirements.txt con dipendenze (2024-04-07) - [x] T04: Setup file configurazione (.env, config.py) (2024-04-07) -- [ ] T05: Configurare pytest e struttura test +- [x] T05: Configurare pytest e struttura test (2024-04-07) ### 🗄️ Database & Models (T06-T11) - 0/6 completati - [ ] T06: Creare database.py (connection & session) diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..4be2cda --- /dev/null +++ b/pytest.ini @@ -0,0 +1,32 @@ +[pytest] +# Test discovery settings +testpaths = tests +python_files = test_*.py +python_classes = Test* +python_functions = test_* + +# Asyncio settings +asyncio_mode = auto +asyncio_default_fixture_loop_scope = function + +# Coverage settings +addopts = + -v + --strict-markers + --tb=short + --cov=src/openrouter_monitor + --cov-report=term-missing + --cov-report=html:htmlcov + --cov-fail-under=90 + +# Markers +testmarkers = + unit: Unit tests (no external dependencies) + integration: Integration tests (with mocked dependencies) + e2e: End-to-end tests (full workflow) + slow: Slow tests (skip in quick mode) + +# Filter warnings +filterwarnings = + ignore::DeprecationWarning:passlib.* + ignore::UserWarning diff --git a/tests/__pycache__/conftest.cpython-313-pytest-9.0.2.pyc b/tests/__pycache__/conftest.cpython-313-pytest-9.0.2.pyc index 4199cbd..6c2093e 100644 Binary files a/tests/__pycache__/conftest.cpython-313-pytest-9.0.2.pyc and b/tests/__pycache__/conftest.cpython-313-pytest-9.0.2.pyc differ diff --git a/tests/conftest.py b/tests/conftest.py index e69de29..c7bade0 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -0,0 +1,50 @@ +"""Pytest configuration and fixtures. + +This module contains shared fixtures and configuration for all tests. +""" +import sys +import os +import pytest +import pytest_asyncio + +# Add src to path for importing in tests +sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'src')) + +# Markers for test organization +pytest_plugins = ['pytest_asyncio'] + + +def pytest_configure(config): + """Configure pytest with custom markers.""" + config.addinivalue_line("markers", "unit: Unit tests (no external dependencies)") + config.addinivalue_line("markers", "integration: Integration tests (with mocked dependencies)") + config.addinivalue_line("markers", "e2e: End-to-end tests (full workflow)") + config.addinivalue_line("markers", "slow: Slow tests (skip in quick mode)") + + +@pytest.fixture(scope='session') +def project_root(): + """Return the project root directory.""" + return os.path.dirname(os.path.dirname(__file__)) + + +@pytest.fixture(scope='session') +def src_path(project_root): + """Return the src directory path.""" + return os.path.join(project_root, 'src') + + +@pytest.fixture +def temp_dir(tmp_path): + """Provide a temporary directory for tests.""" + return tmp_path + + +@pytest.fixture +def mock_env_vars(monkeypatch): + """Set up mock environment variables for testing.""" + monkeypatch.setenv('SECRET_KEY', 'test-secret-key-min-32-characters-long') + monkeypatch.setenv('ENCRYPTION_KEY', 'test-32-byte-encryption-key!!') + monkeypatch.setenv('DATABASE_URL', 'sqlite:///./test.db') + monkeypatch.setenv('DEBUG', 'true') + monkeypatch.setenv('LOG_LEVEL', 'DEBUG') diff --git a/tests/unit/test_pytest_config.py b/tests/unit/test_pytest_config.py new file mode 100644 index 0000000..5c735ca --- /dev/null +++ b/tests/unit/test_pytest_config.py @@ -0,0 +1,103 @@ +"""Test for pytest configuration (T05).""" +import os +import sys +import pytest + + +@pytest.mark.unit +class TestPytestConfiguration: + """Test pytest configuration and setup.""" + + def test_pytest_ini_exists(self): + """Verify pytest.ini file exists.""" + ini_path = "/home/google/Sources/LucaSacchiNet/openrouter-watcher/pytest.ini" + assert os.path.isfile(ini_path), f"File {ini_path} does not exist" + + def test_pytest_ini_has_testpaths(self): + """Verify pytest.ini contains testpaths configuration.""" + ini_path = "/home/google/Sources/LucaSacchiNet/openrouter-watcher/pytest.ini" + with open(ini_path, 'r') as f: + content = f.read() + assert 'testpaths' in content, "pytest.ini should contain testpaths" + + def test_pytest_ini_has_python_files(self): + """Verify pytest.ini contains python_files configuration.""" + ini_path = "/home/google/Sources/LucaSacchiNet/openrouter-watcher/pytest.ini" + with open(ini_path, 'r') as f: + content = f.read() + assert 'python_files' in content, "pytest.ini should contain python_files" + + def test_pytest_ini_has_python_functions(self): + """Verify pytest.ini contains python_functions configuration.""" + ini_path = "/home/google/Sources/LucaSacchiNet/openrouter-watcher/pytest.ini" + with open(ini_path, 'r') as f: + content = f.read() + assert 'python_functions' in content, "pytest.ini should contain python_functions" + + def test_pytest_ini_has_addopts(self): + """Verify pytest.ini contains addopts configuration.""" + ini_path = "/home/google/Sources/LucaSacchiNet/openrouter-watcher/pytest.ini" + with open(ini_path, 'r') as f: + content = f.read() + assert 'addopts' in content, "pytest.ini should contain addopts" + + def test_pytest_ini_has_cov_config(self): + """Verify pytest.ini contains coverage configuration.""" + ini_path = "/home/google/Sources/LucaSacchiNet/openrouter-watcher/pytest.ini" + with open(ini_path, 'r') as f: + content = f.read() + assert 'cov' in content.lower(), "pytest.ini should contain coverage config" + + def test_conftest_py_exists(self): + """Verify conftest.py file exists.""" + conf_path = "/home/google/Sources/LucaSacchiNet/openrouter-watcher/tests/conftest.py" + assert os.path.isfile(conf_path), f"File {conf_path} does not exist" + + def test_conftest_py_has_pytest_plugins(self): + """Verify conftest.py contains pytest_plugins.""" + conf_path = "/home/google/Sources/LucaSacchiNet/openrouter-watcher/tests/conftest.py" + with open(conf_path, 'r') as f: + content = f.read() + assert 'pytest_plugins' in content or 'fixture' in content, \ + "conftest.py should contain pytest plugins or fixtures" + + def test_conftest_py_imports_pytest_asyncio(self): + """Verify conftest.py imports pytest_asyncio.""" + conf_path = "/home/google/Sources/LucaSacchiNet/openrouter-watcher/tests/conftest.py" + with open(conf_path, 'r') as f: + content = f.read() + assert 'pytest_asyncio' in content or 'asyncio' in content.lower(), \ + "conftest.py should import pytest_asyncio" + + def test_pytest_can_run_tests(self): + """Verify pytest can actually run tests.""" + import subprocess + result = subprocess.run( + ['python3', '-m', 'pytest', '--version'], + capture_output=True, + text=True + ) + assert result.returncode == 0, "pytest should be runnable" + assert 'pytest' in result.stdout.lower(), "pytest version should be displayed" + + def test_pytest_can_discover_tests(self): + """Verify pytest can discover tests in the project.""" + import subprocess + result = subprocess.run( + ['python3', '-m', 'pytest', '--collect-only', '-q'], + capture_output=True, + text=True, + cwd='/home/google/Sources/LucaSacchiNet/openrouter-watcher' + ) + assert result.returncode == 0, "pytest should collect tests without errors" + # Should find at least some tests + assert 'test' in result.stdout.lower(), "pytest should find tests" + + def test_coverage_is_configured(self): + """Verify coverage is configured in pytest.""" + ini_path = "/home/google/Sources/LucaSacchiNet/openrouter-watcher/pytest.ini" + with open(ini_path, 'r') as f: + content = f.read() + # Check for coverage report configuration + assert any(term in content.lower() for term in ['cov-report', 'coverage', 'cov=']), \ + "pytest.ini should configure coverage reporting"