Cela semble être un problème de poulet et d'oeuf.
Vous pouvez faire écrire une fonction d'écriture dans un magasin de données, mais ne savez jamais que vous l'avez enregistrée correctement sans fonction de lecture testée.
Vous pouvez faire lire une fonction de lecture à partir d'un magasin de données, mais comment mettre des choses dans ce magasin de données, à lire, sans fonction d'écriture testée?
ÉDITER:
Je me connecte et effectue des transactions avec une base de données SQL pour enregistrer et charger des objets à utiliser. Il n'y a aucun intérêt à tester les fonctions d'accès fournies par la base de données, mais j'encapsule ces fonctions de base de données pour sérialiser / désérialiser les objets. Je veux être sûr d'écrire et de lire correctement les bonnes choses vers et depuis la base de données.
Ce n'est pas comme ajouter / supprimer, comme le mentionne @snowman. Je veux savoir que le contenu que j'ai écrit est correct, mais cela nécessite une fonction de lecture bien testée. Quand je lis, je veux être sûr que ma lecture a correctement créé un objet égal à ce qui a été écrit; mais cela nécessite une fonction d'écriture bien testée.
Réponses:
Commencez avec la fonction de lecture.
Dans la configuration de test : créez la base de données et ajoutez les données de test. soit via des scripts de migration, soit à partir d'une sauvegarde. Comme ce n'est pas votre code, il ne nécessite pas de test en TDD
Dans le test : instanciez votre référentiel, pointez sur votre base de données de test et appelez la méthode Read. Vérifiez que les données de test sont renvoyées.
Maintenant que vous avez une fonction de lecture entièrement testée, vous pouvez passer à la fonction d'écriture, qui peut utiliser la lecture existante pour vérifier ses propres résultats
la source
Je fais souvent juste une écriture suivie d'une lecture. par exemple (pseudocode)
Ajouté plus tard
En plus que cette solution soit "prgamatique" et "assez bonne", on pourrait soutenir que les autres solutions testent la mauvaise chose . Tester si les chaînes ou les instructions SQL correspondent n'est pas une idée terrible, je l'ai fait moi-même, mais cela teste un effet secondaire et est fragile. Que faire si vous modifiez la capitalisation, ajoutez un champ ou mettez à jour un numéro de version dans vos données? Que faire si votre pilote SQL change l'ordre des appels pour plus d'efficacité ou si votre sérialiseur XML mis à jour ajoute un espace supplémentaire ou modifie une version de schéma?
Maintenant, si vous devez respecter très strictement certaines spécifications officielles, je conviens que la vérification des détails est appropriée.
la source
Non. Ne pas tester les E / S unitaires. C'est une perte de temps.
Logique de test unitaire. S'il y a beaucoup de logique que vous voulez tester dans le code d'E / S, vous devez refactoriser votre code pour séparer la logique de la façon dont vous effectuez les E / S et ce que vous faites des E / S de l'activité réelle de faire des E / S (qui est quasiment impossible à tester).
Pour élaborer un peu, si vous souhaitez tester un serveur HTTP, vous devez le faire à travers deux types de tests: les tests d'intégration et les tests unitaires. Les tests unitaires ne doivent pas du tout interagir avec les E / S. C'est lent et introduit de nombreuses conditions d'erreur qui n'ont rien à voir avec l'exactitude de votre code. Les tests unitaires ne doivent pas être soumis à l'état de votre réseau!
Votre code doit séparer:
Les deux premiers impliquent la logique et les décisions et nécessitent des tests unitaires. Le dernier n'implique pas de prendre de nombreuses décisions, le cas échéant, et peut être testé à merveille à l'aide de tests d'intégration.
En fait, c'est juste un bon design en général, mais l'une des raisons en est qu'il facilite le test.
Voici quelques exemples:
la source
Je ne sais pas si c'est une pratique standard ou non, mais cela fonctionne bien pour moi.
Dans mes implémentations de méthodes de lecture / écriture non basées sur une base de données, j'utilise mes propres méthodes
toString()
etfromString()
méthodes spécifiques au type comme détails d'implémentation.Ceux-ci peuvent être facilement testés isolément:
Pour les méthodes de lecture et d'écriture, j'ai un test d'intégration qui lit et écrit physiquement en un seul test
Au fait: y a-t-il quelque chose de mal à avoir un test qui teste la lecture / écriture ensemble?
la source
Les données connues doivent être formatées de manière connue. La manière la plus simple de l'implémenter est d'utiliser une chaîne constante et de comparer le résultat, comme décrit @ k3b.
Vous n'êtes cependant pas limité aux constantes. Il peut y avoir un certain nombre de propriétés des données écrites que vous pouvez extraire à l'aide d'un autre type d'analyseur, comme des expressions régulières ou même des sondes ad hoc à la recherche de fonctionnalités des données.
En ce qui concerne la lecture ou l'écriture des données, il peut être utile d'avoir un système de fichiers en mémoire qui vous permet d'exécuter vos tests sans possibilité d'interférence d'autres parties du système. Si vous n'avez pas accès à un bon système de fichiers en mémoire, utilisez une arborescence de répertoires temporaire.
la source
Utilisez l'injection de dépendance et la moquerie.
Vous ne voulez pas tester votre pilote SQL et vous ne voulez pas tester si votre base de données SQL est en ligne et configurée correctement. Cela ferait partie d'un test d'intégration ou de système. Vous voulez tester si votre code envoie les instructions SQL qu'il est censé envoyer et s'il interprète les réponses comme il est censé le faire.
Donc, lorsque vous avez une méthode / classe qui est censée faire quelque chose avec une base de données, ne lui demandez pas d'obtenir cette connexion de base de données par elle-même. Modifiez-le afin que l'objet qui représente la connexion à la base de données lui soit transmis.
Dans votre code de production, passez l'objet de base de données réel.
Dans vos tests unitaires, passez un objet factice qui se comporte comme si une base de données réelle ne contactait pas réellement un serveur de base de données. Demandez-lui simplement de vérifier s'il reçoit les instructions SQL qu'il est censé recevoir, puis répond avec des réponses codées en dur.
De cette façon, vous pouvez tester votre couche d'abstraction de base de données sans même avoir besoin d'une base de données réelle.
la source
Si vous utilisez un mappeur relationnel objet, il existe généralement une bibliothèque associée qui peut être utilisée pour tester le bon fonctionnement de vos mappages en créant un agrégat, en le conservant et en le rechargeant à partir d'une nouvelle session, suivie d'une vérification de l'état par rapport à l'objet d'origine.
NHibernate propose des tests de spécification de persistance . Il peut être configuré pour fonctionner avec un magasin en mémoire pour des tests unitaires rapides.
Si vous suivez la version la plus simple des modèles de référentiel et d'unité de travail et testez tous vos mappages, vous pouvez compter sur des choses qui fonctionnent à peu près.
la source