Bruno Charest ecefbc8611
Some checks failed
Tests / Backend Tests (Python) (3.10) (push) Has been cancelled
Tests / Backend Tests (Python) (3.11) (push) Has been cancelled
Tests / Backend Tests (Python) (3.12) (push) Has been cancelled
Tests / Frontend Tests (JS) (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / All Tests Passed (push) Has been cancelled
Clean up test files and debug artifacts, add node_modules to gitignore, export DashboardManager for testing, and enhance pytest configuration with comprehensive test markers and settings
2025-12-15 08:15:49 -05:00

205 lines
5.0 KiB
Markdown

# Tests - Homelab Automation Dashboard
Architecture de tests complète pour le backend FastAPI et le frontend JavaScript.
## Structure
```
tests/
├── backend/ # Tests Python (pytest)
│ ├── conftest.py # Fixtures partagées (DB, client, mocks)
│ ├── test_routes_auth.py # Tests authentification JWT
│ ├── test_routes_hosts.py # Tests CRUD hôtes
│ ├── test_routes_schedules.py # Tests planificateur
│ ├── test_services_ansible.py # Tests service Ansible
│ ├── test_services_scheduler.py # Tests APScheduler
│ ├── test_services_notification.py # Tests ntfy
│ └── test_websocket.py # Tests WebSocket
├── frontend/ # Tests JavaScript (Vitest)
│ ├── setup.js # Configuration (mocks fetch, WS, localStorage)
│ ├── main.test.js # Tests DashboardManager
│ └── dom.test.js # Tests rendu DOM
└── README.md # Ce fichier
```
## Prérequis
### Backend (Python)
```bash
pip install pytest pytest-asyncio pytest-cov httpx respx freezegun pytest-mock
```
### Frontend (Node.js)
```bash
sudo apt-get install nodejs npm
npm install
```
## Commandes
### Exécuter tous les tests
```bash
make test-all
# Ou avec coverage:
make test-cov
# Ou séparément:
make test-backend
make test-frontend
```
### Avec couverture
```bash
make test-cov
```
### Mode watch (développement)
```bash
make test-watch # Frontend Vitest watch
pytest-watch tests/backend # Backend (nécessite pytest-watch)
```
### Tests rapides
```bash
make test-quick
```
### Tests backend uniquement
```bash
pytest tests/backend -v -m "unit"
# Avec coverage:
pytest tests/backend --cov=app --cov-report=html
```
### Tests frontend uniquement
```bash
npm test
# Avec coverage:
npm run test:coverage
```
## Marqueurs pytest
| Marqueur | Description |
|----------|-------------|
| `@pytest.mark.unit` | Tests unitaires (rapides, isolés) |
| `@pytest.mark.integration` | Tests d'intégration |
| `@pytest.mark.slow` | Tests lents (skippés en CI fast) |
Exécuter par marqueur:
```bash
pytest tests/backend -m "unit"
pytest tests/backend -m "integration"
pytest tests/backend -m "not slow"
```
## Fixtures Principales (Backend)
### `db_session`
Session SQLAlchemy async avec SQLite in-memory. Rollback automatique après chaque test.
### `client`
AsyncClient httpx avec authentification mockée. Dépendances FastAPI overridées.
### `unauthenticated_client`
AsyncClient sans authentification pour tester les erreurs 401.
### `mock_ansible_service`
Mock complet du service Ansible (pas de subprocess réel).
### `mock_notification_service`
Mock du service ntfy (pas de HTTP réel).
### `host_factory`, `user_factory`, etc.
Factories pour créer des données de test.
```python
async def test_example(db_session, host_factory):
host = await host_factory.create(db_session, name="test.local")
assert host.name == "test.local"
```
## Mocks Frontend
### `setupFetchMock(responses)`
Configure les réponses fetch mockées:
```javascript
setupFetchMock({
'/api/hosts': [{ id: 'h1', name: 'server1' }],
'/api/auth/status': { authenticated: true }
});
```
### `MockWebSocket`
Classe WebSocket mockée avec helpers:
```javascript
const ws = new MockWebSocket('ws://localhost/ws');
ws._receiveMessage({ type: 'host_updated', data: {...} });
```
### `localStorageMock`
Mock localStorage avec espions:
```javascript
expect(localStorageMock.setItem).toHaveBeenCalledWith('accessToken', 'token');
```
## Ajouter un Nouveau Test
### Backend
1. Créer le fichier `tests/backend/test_<module>.py`
2. Importer les fixtures depuis `conftest.py`
3. Utiliser les marqueurs appropriés
```python
import pytest
from httpx import AsyncClient
pytestmark = [pytest.mark.unit, pytest.mark.asyncio]
class TestMyFeature:
async def test_something(self, client: AsyncClient, db_session):
response = await client.get("/api/my-endpoint")
assert response.status_code == 200
```
### Frontend
1. Créer le fichier `tests/frontend/<name>.test.js`
2. Importer les utilitaires depuis `setup.js`
```javascript
import { describe, it, expect } from 'vitest';
import { setupFetchMock } from './setup.js';
describe('MyFeature', () => {
it('does something', async () => {
setupFetchMock({ '/api/data': { value: 42 } });
// Test...
});
});
```
## Seuils de Couverture
| Composant | Seuil |
|-----------|-------|
| Backend global | 80% |
| Services critiques | 90% |
| Frontend global | 60% |
## CI/CD
Les tests s'exécutent automatiquement via GitHub Actions sur:
- Push sur `main` ou `develop`
- Pull requests vers `main` ou `develop`
Voir `.github/workflows/tests.yml`
## Bonnes Pratiques
1. **Isolation**: Chaque test est indépendant (DB rollback, mocks reset)
2. **Pas de réseau**: Tous les appels HTTP/SSH sont mockés
3. **Déterminisme**: Utiliser `freezegun` pour les tests liés au temps
4. **AAA Pattern**: Arrange, Act, Assert clairement séparés
5. **Nommage explicite**: `test_<action>_<condition>_<expected_result>`