# Tests d'Intégration - veza-backend-api

**Objectif**: Tests d'intégration reproductibles validant le comportement réel du système avec dépendances externes.

---

## Contrat d'Environnement Minimal

### Services Requis

Les tests d'intégration nécessitent les services suivants:

1. **PostgreSQL** (obligatoire)
   - Version: 15+
   - Base de données: `veza_test`
   - Utilisateur: `veza` / Mot de passe: `veza`
   - Migrations: Appliquées automatiquement via testcontainers

2. **Redis** (obligatoire pour certains tests)
   - Version: 7+
   - Port: 6379 (par défaut)
   - Aucune base de données spécifique requise

3. **RabbitMQ** (optionnel)
   - Utilisé uniquement pour tests spécifiques
   - Peut être skippé si non disponible

### Méthodes de Setup

#### Option 1: Testcontainers (Recommandé)

**Avantages**:
- ✅ Reproductible (même environnement partout)
- ✅ Isolation complète (pas de pollution entre tests)
- ✅ Pas de configuration manuelle requise
- ✅ Fonctionne en CI/CD

**Prérequis**:
- Docker installé et en cours d'exécution
- Go 1.21+

**Utilisation**:
```bash
# Les tests utilisent automatiquement testcontainers
go test ./tests/integration/... -tags integration -v
```

**Configuration**:
- PostgreSQL: Démarre automatiquement via `internal/testutils/setup.go`
- Redis: Démarre automatiquement via `internal/testutils/setup_redis.go` (à créer)
- Migrations: Appliquées automatiquement depuis `migrations/`

#### Option 2: Services Locaux (Alternative)

**Quand utiliser**:
- Docker non disponible
- Tests de développement rapide
- Debugging local

**Configuration**:
```bash
# PostgreSQL
export DATABASE_URL="postgresql://veza:veza@localhost:5432/veza_test?sslmode=disable"

# Redis
export REDIS_ADDR="localhost:6379"

# RabbitMQ (optionnel)
export RABBITMQ_URL="amqp://guest:guest@localhost:5672/"
```

**Setup manuel**:
```bash
# PostgreSQL
createdb veza_test
psql veza_test < migrations/*.sql

# Redis
redis-server

# RabbitMQ (optionnel)
docker run -d --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3-management
```

---

## Exécution des Tests

### Tests d'Intégration (Tous)

```bash
# Avec testcontainers (recommandé)
go test ./tests/integration/... -tags integration -v

# Avec services locaux
export DATABASE_URL="postgresql://veza:veza@localhost:5432/veza_test?sslmode=disable"
export REDIS_ADDR="localhost:6379"
go test ./tests/integration/... -tags integration -v
```

### Tests Spécifiques

```bash
# Test upload async polling
go test ./tests/integration -tags integration -run TestUploadAsyncPollingStatus -v

# Test upload scalability
go test ./tests/integration -tags integration -run TestUploadScalability -v
```

### Via Makefile

```bash
# Tous les tests d'intégration
make test-integration

# Tests avec quarantaine (validation manuelle)
make test-quarantine
```

---

## Structure des Tests

### Tests Non-Quarantinés

Ces tests doivent **toujours passer** avant production:

- `TestUploadAsyncPollingStatus` - Upload async avec polling status
- `TestUploadScalability` - Upload distribué avec Redis

### Tests Quarantinés

Voir `QUARANTINE.md` pour la classification complète.

**Classification**:
- 🔴 **Doit passer avant prod** - Bloquant pour release
- 🟡 **CI nightly** - Exécuté en CI séparé, non-bloquant
- 🟢 **Manual only** - Exécution manuelle uniquement

---

## Dépannage

### Erreur: "Docker not running"

**Solution**: Démarrer Docker
```bash
# Linux
sudo systemctl start docker

# macOS
open -a Docker
```

### Erreur: "PostgreSQL container failed to start"

**Solution**: Vérifier logs testcontainers
```bash
docker ps -a | grep postgres
docker logs <container_id>
```

**Cause commune**: Port 5432 déjà utilisé
```bash
# Vérifier processus utilisant le port
lsof -i :5432

# Arrêter processus ou changer port dans test
```

### Erreur: "Redis not available"

**Solution 1**: Utiliser testcontainers (recommandé)
- Les tests utilisent automatiquement testcontainers si disponible

**Solution 2**: Démarrer Redis localement
```bash
redis-server
# ou
docker run -d -p 6379:6379 redis:7-alpine
```

### Test Flaky (intermittent)

**Actions**:
1. Vérifier logs testcontainers pour timeouts
2. Augmenter timeouts dans setup si nécessaire
3. Vérifier ressources système (CPU, mémoire)
4. Documenter dans `QUARANTINE.md` si non-résolvable

---

## Variables d'Environnement

### Pour Tests avec Services Locaux

| Variable | Description | Défaut |
|----------|-------------|--------|
| `DATABASE_URL` | PostgreSQL connection string | `postgresql://veza:veza@localhost:5432/veza_test?sslmode=disable` |
| `REDIS_ADDR` | Redis address | `localhost:6379` |
| `RABBITMQ_URL` | RabbitMQ connection string | `amqp://guest:guest@localhost:5672/` |
| `SKIP_TESTCONTAINERS` | Forcer services locaux (si `true`) | `false` |

### Pour Tests avec Testcontainers

Aucune variable requise - testcontainers démarre automatiquement les services.

---

## CI/CD

### Pipeline Normal

```yaml
- name: Run unit tests
  run: go test ./internal/... -short -tags '!integration'
```

### Pipeline Intégration (Séparé)

```yaml
- name: Run integration tests
  run: go test ./tests/integration/... -tags integration -v
  services:
    docker:
      image: docker:latest
```

**Note**: Les tests d'intégration peuvent être exécutés:
- En CI nightly (tous les tests)
- En CI sur demande (workflow_dispatch)
- En CI sur PR (tests non-quarantinés uniquement)

---

## Bonnes Pratiques

### 1. Isolation des Tests

- ✅ Chaque test utilise sa propre base de données (via testcontainers)
- ✅ Nettoyage automatique après chaque test
- ✅ Pas de dépendances entre tests

### 2. Reproductibilité

- ✅ Utiliser testcontainers pour environnement identique
- ✅ Éviter les timeouts courts (< 1s)
- ✅ Éviter les sleeps fixes (utiliser polling avec timeout)

### 3. Performance

- ✅ Tests parallèles quand possible (`t.Parallel()`)
- ✅ Timeouts raisonnables (5-10s max par test)
- ✅ Nettoyer ressources (containers, fichiers) après test

### 4. Fiabilité

- ✅ Tests non-flaky (passent 100% du temps)
- ✅ Messages d'erreur clairs
- ✅ Skip si dépendances manquantes (avec message)

---

## Exemples

### Exemple 1: Test avec Testcontainers

```go
func TestMyIntegration(t *testing.T) {
    ctx := context.Background()
    
    // PostgreSQL via testcontainers
    dsn, err := testutils.GetTestContainerDB(ctx)
    require.NoError(t, err)
    
    db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
    require.NoError(t, err)
    
    // Test...
}
```

### Exemple 2: Test avec Services Locaux

```go
func TestMyIntegration(t *testing.T) {
    dsn := os.Getenv("DATABASE_URL")
    if dsn == "" {
        t.Skip("DATABASE_URL not set, skipping integration test")
    }
    
    db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
    require.NoError(t, err)
    
    // Test...
}
```

---

## Références

- Testcontainers Go: https://golang.testcontainers.org/
- Quarantaine: `tests/integration/QUARANTINE.md`
- Setup helpers: `internal/testutils/setup.go`

---

**Dernière mise à jour**: 2025-12-15  
**Maintenu par**: Veza Backend Team
