32 votes

Test unitaire des bases de données

L'été dernier, j'ai développé une application CRUD ASP.NET/SQL Server de base, et les tests unitaires étaient l'une des exigences. J'ai rencontré quelques problèmes lorsque j'ai essayé de tester contre la base de données. D'après ce que j'ai compris, les tests unitaires doivent être :

  • apatride
  • indépendants les uns des autres
  • répétable avec les mêmes résultats, c'est-à-dire sans changement persistant.

Ces exigences semblent être contradictoires lors du développement pour une base de données. Par exemple, je ne peux pas tester Insert() sans m'assurer que les lignes à insérer ne sont pas encore là, et je dois donc appeler Delete() en premier. Mais, que se passe-t-il s'ils ne sont pas déjà là ? Dans ce cas, je dois d'abord appeler la fonction Exists().

Ma solution finale impliquait de très grandes fonctions de configuration (beurk !) et un scénario de test vide qui s'exécuterait en premier et indiquerait que la configuration s'est déroulée sans problème. C'est un sacrifice sur l'indépendance des tests tout en maintenant leur absence d'état.

Une autre solution que j'ai trouvée consiste à intégrer les appels de fonctions dans une transaction qui peut être facilement annulée, comme suit XtUnit de Roy Osherove . Cela fonctionne, mais cela implique une autre bibliothèque, une autre dépendance, et cela semble une solution un peu trop lourde pour le problème en question.

Alors, qu'a fait la communauté des OS lorsqu'elle a été confrontée à cette situation ?


a dit tgmdbm :

Vous utilisez généralement votre cadre de test unitaire automatisé préféré pour effectuer des tests d'intégration, ce qui est pourquoi certaines personnes sont confuses, mais ils ne suivent pas les mêmes règles. Vous êtes autorisé à impliquer l'implémentation concrète l'implémentation concrète de plusieurs de vos classes (parce qu'elles ont été testées unitairement). Vous testez comment votre béton classes concrètes interagissent entre elles et avec la base de données .

Donc si je lis correctement, il n'y a pas vraiment de moyen de efficacement Test unitaire d'une couche d'accès aux données. Ou bien, un "test unitaire" d'une couche d'accès aux données consisterait-il à tester, par exemple, le SQL/les commandes générées par les classes, indépendamment de l'interaction réelle avec la base de données ?

25voto

tgmdbm Points 1115

Il n'y a pas de véritable moyen de tester une base de données autrement qu'en vérifiant que les tables existent, qu'elles contiennent les colonnes attendues et qu'elles ont les contraintes appropriées. Mais cela ne vaut généralement pas la peine d'être fait.

Vous n'avez pas l'habitude unité tester la base de données. Vous faites généralement intervenir la base de données dans intégration tests.

Vous utilisez généralement votre framework de tests unitaires automatisés préféré pour effectuer les tests d'intégration, ce qui explique la confusion de certains, mais ils ne suivent pas les mêmes règles. Vous êtes autorisé à faire intervenir l'implémentation concrète d'un grand nombre de vos classes (parce qu'elles ont fait l'objet de tests unitaires). Vous testez comment vos classes concrètes interagissent entre elles et avec la base de données.

11voto

Gap_Tooth Points 121

DBunit

Vous pouvez utiliser cet outil pour exporter l'état d'une base de données à un moment donné, puis lorsque vous effectuez des tests unitaires, elle peut être ramenée à son état précédent automatiquement au début des tests. Nous l'utilisons assez souvent là où je travaille.

5voto

Wing Points 1529

La solution habituelle aux dépendances externes dans les tests unitaires consiste à utiliser des objets fantaisie, c'est-à-dire des bibliothèques qui imitent le comportement des objets réels contre lesquels vous effectuez vos tests. Ce n'est pas toujours simple et cela demande parfois un peu d'ingéniosité, mais il existe plusieurs bonnes bibliothèques d'objets fantaisie (gratuites) pour .Net si vous ne voulez pas "créer votre propre bibliothèque". Deux d'entre elles me viennent immédiatement à l'esprit :

Rhino Mocks est une entreprise qui a une assez bonne réputation.

NMock en est une autre.

Il existe également de nombreuses bibliothèques commerciales de simulateurs. Une partie de l'écriture de bons tests unitaires consiste à concevoir votre code pour eux - par exemple, en utilisant des interfaces lorsque cela a du sens, de sorte que vous puissiez "simuler" un objet dépendant en implémentant une "fausse" version de son interface qui se comporte néanmoins de manière prévisible, à des fins de test.

Dans le cas des bases de données, cela signifie "simuler" votre propre couche d'accès à la base de données avec des objets qui renvoient des objets de table, de ligne ou de jeu de données pour que vos tests unitaires puissent les traiter.

Là où je travaille, nous créons généralement nos propres librairies de simulation à partir de rien, mais cela ne veut pas dire que vous devez le faire.

4voto

tgmdbm Points 1115

Oui, vous devriez refactoriser votre code pour accéder aux référentiels et aux services qui accèdent à la base de données et vous pouvez ensuite simuler ou bloquer ces objets afin que l'objet testé ne touche jamais la base de données. C'est beaucoup plus rapide que de stocker l'état de la base de données et de le réinitialiser après chaque test !

Je recommande vivement Moq comme cadre de simulation. J'ai utilisé Rhino Mocks et NMock. Moq était si simple et a résolu tous les problèmes que j'avais avec les autres frameworks.

2voto

Je me suis posé la même question et je suis arrivé aux mêmes conclusions de base que les autres personnes qui ont répondu ici : Ne vous embêtez pas à tester la couche de communication de la base de données, mais si vous voulez tester vos fonctions de modèle (pour vous assurer qu'elles extraient les données correctement, les formatent correctement, etc.), utilisez une sorte de source de données factice et configurez des tests pour vérifier les données récupérées.

Je trouve aussi que la définition de base des tests unitaires ne convient pas à de nombreuses activités de développement web. Mais cette page décrit des modèles de tests unitaires plus "avancés" et peut aider à trouver des idées pour appliquer les tests unitaires dans diverses situations :

Modèles de tests unitaires

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X