Bruno Charest 6d8432169b
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
Add enhanced terminal history panel UI with animations, keyboard navigation, advanced filtering, search highlighting, and improved storage metrics display with detailed filesystem tables and ZFS/LVM support
2025-12-21 12:31:08 -05:00
..

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)

pip install pytest pytest-asyncio pytest-cov httpx respx freezegun pytest-mock

Frontend (Node.js)

sudo apt-get install nodejs npm
npm install

Commandes

Exécuter tous les tests

make test-all
# Ou avec coverage:
make test-cov
# Ou séparément:
make test-backend
make test-frontend

Avec couverture

make test-cov

Mode watch (développement)

make test-watch          # Frontend Vitest watch
pytest-watch tests/backend  # Backend (nécessite pytest-watch)

Tests rapides

make test-quick

Tests backend uniquement

pytest tests/backend -v -m "unit"
# Avec coverage:
pytest tests/backend --cov=app --cov-report=html

Tests frontend uniquement

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:

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.

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:

setupFetchMock({
  '/api/hosts': [{ id: 'h1', name: 'server1' }],
  '/api/auth/status': { authenticated: true }
});

MockWebSocket

Classe WebSocket mockée avec helpers:

const ws = new MockWebSocket('ws://localhost/ws');
ws._receiveMessage({ type: 'host_updated', data: {...} });

localStorageMock

Mock localStorage avec espions:

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
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
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>