Le forum est en lecture seule depuis l'été 2026. Les archives restent en ligne, mais il n'est plus possible de s'inscrire ni de publier.

Tests d'intégration sur une base SQL : vos stratégies ?

Bases de données Sujet ouvert par marion_dev le · 5 messages · sujet verrouillé (archives)

RépondrePage 1 sur 1

Bonjour, je cherche des retours d'expérience sur les tests d'intégration qui touchent réellement une base SQL (PostgreSQL chez nous, mais je pense que la question est générale). Aujourd'hui on a une base de test partagée par toute la suite, remplie une fois au début, et les tests s'exécutent dessus dans un ordre fixe.

Résultat : dès qu'un test échoue à moitié, il laisse des lignes qui font échouer les suivants, et personne n'ose lancer la suite en parallèle. Comment vous isolez vos tests entre eux ? Base recréée à chaque fois ? Transactions ? Autre chose ? Je prends aussi les mauvaises expériences, ça évite de les refaire.

Citer

On a eu le même historique et on est passés à une base recréée à chaque exécution de la suite (pas à chaque test) à partir des migrations, puis un TRUNCATE ... RESTART IDENTITY CASCADE entre les tests. C'est simple à mettre en place et ça a supprimé la quasi-totalité des tests instables.

Le point faible, c'est le temps : rejouer trois cents migrations avant chaque suite prend chez nous près d'une minute. On envisage de partir d'un dump plutôt que des migrations, mais on perd alors la garantie que les migrations elles-mêmes sont testées, et c'est justement ce qui nous a sauvés deux fois.

Citer

Bonjour marion_dev. Trois pratiques qui, combinées, ont réglé le problème pour nous sur une API PostgreSQL d'une centaine de tables.

Une base jetable par test (ou par fichier de tests, selon la granularité qui vous convient). Avec PostgreSQL, CREATE DATABASE test_42 TEMPLATE test_modele est quasi instantané, parce que c'est une copie de fichiers et non un rejeu de migrations. On prépare une base modèle une seule fois au démarrage de la suite (migrations, puis données de référence), et chaque test se voit attribuer un clone nommé avec un identifiant unique, qu'il supprime à la fin. Ça rend la parallélisation triviale : chaque processus de test a sa propre base, aucune interférence possible. Le coût est de quelques dizaines de millisecondes par clone. Ça répond aussi à la remarque de dbjulien : les migrations sont rejouées une fois par suite, pas une fois par test.

Des transactions annulées pour les tests qui n'ont besoin que d'une connexion. Pour la majorité des tests, plus légers, on ouvre une transaction avant, on exécute le test dedans, et on fait un ROLLBACK après, quoi qu'il arrive. Aucun nettoyage à écrire, la base revient exactement à son état initial. La limite est bien connue : ça ne marche pas si le code testé ouvre lui-même des transactions ou utilise plusieurs connexions (un pool, une file de travail). Pour ces cas-là, on retombe sur la base jetable du point précédent ; c'est précisément pour ça qu'on garde les deux mécanismes côte à côte.

Des données de référence figées et versionnées. La base modèle contient un jeu de données minimal mais réaliste, généré par un script versionné avec le code, jamais par une copie de la production. Chaque test qui a besoin de données particulières les crée lui-même à partir de fabriques, sur ce socle commun. On a arrêté d'avoir des tests qui dépendent d'une ligne « client 17 » que personne ne se souvient avoir insérée.

Pour ton problème de tests laissés à moitié : avec le rollback systématique, un test qui échoue ne laisse rien derrière lui ; et avec les clones, même un test qui plante brutalement ne pollue que sa propre base, qu'on supprime en masse au démarrage suivant (les noms suivent un préfixe, une boucle de DROP DATABASE suffit).

Back-end depuis Amsterdam · Mon site
Citer

Complément côté infrastructure : si votre CI tourne dans des conteneurs, montez le répertoire de données de PostgreSQL en tmpfs et désactivez fsync pour l'instance de test uniquement (jamais ailleurs, évidemment). Chez nous la suite est passée de six minutes à deux sans changer une ligne de test. Et l'approche par TEMPLATE décrite par Ritchie Dagonia marche d'autant mieux que les fichiers copiés sont en mémoire.

Citer

Merci, c'est très clair. On part sur base modèle plus clones pour les tests qui ont besoin de plusieurs connexions, et rollback pour tout le reste. J'ai fait un essai rapide hier : le clone prend trente millisecondes chez nous, et la suite complète tourne enfin en parallèle sur quatre processus.

Reste à réécrire les tests qui dépendaient de l'ordre d'exécution, mais au moins on sait maintenant lesquels c'est : ce sont ceux qui échouent depuis qu'on a mélangé l'ordre. Je reviendrai avec les chiffres quand tout sera passé.

Citer
RépondrePage 1 sur 1