Comment s'assurer que la base de données nettoyage est toujours effectuée après un test?
Considérons l'exemple suivant d'un test unitaire. Les commentaires assez bien expliquer mon problème.
[TestMethod]
public void MyTestMethod()
{
//generate some objects in the database
...
//make an assert that fails sometimes (for example purposes, this fails always)
Assert.IsTrue(false);
//TODO: how do we clean up the data generated in the database now that the test has ended here?
}
- Vous devez également utiliser le
TearDown
(ou son équivalent dans votre suite) pour nettoyer, parce que si le test échoue, le nettoyage de code ne sera pas exécuté. - Comment au sujet de l'interception d'une exception, puis re-jeter après le nettoyage?
- Jimmy Bogard (auteur de AutoMapper) a un excellent article et de l'outil: base de données Fiable des tests avec Respawn
Vous devez vous connecter pour publier un commentaire.
Il y a deux façons de le faire. Un est à l'aide de TestInitialize et TestCleanup attributs sur les méthodes dans la classe de test. Ils seront toujours exécuter avant et après le test, respectivement.
Une autre méthode consiste à utiliser le fait que les échecs de tests sont propagées à l'épreuve coureur via des exceptions. Cela signifie qu'un try { } finally { } bloc dans votre test peut être utilisé nettoyer quoi que ce soit après une assertion échoue.
Le try/finally de nettoyage peut être vraiment salissant est qu'il y a beaucoup d'objets à nettoyer. Ce que mon équipe a penché vers l'est d'une aide de la classe qui implémente IDisposable. Il effectue le suivi des objets ont été créés et les pousse sur une pile. Lorsque Disposer est appelé les éléments sont sauté hors de la pile et retiré de la base de données.
Ceci a l'avantage supplémentaire d'envelopper les constructeurs dans les appels de méthode. Si le constructeur signatures de changement, on peut facilement modifier le code de test.
Je pense que la meilleure réponse à ce genre de situations est de réfléchir très attentivement à ce que vous êtes en train de tester. Idéalement, un test unitaire doit être en train de tester un fait unique sur une seule méthode ou d'une fonction. Lorsque vous commencez à les combiner beaucoup de choses ensemble, il croise dans le monde des tests d'intégration (qui sont tout aussi précieux, mais différent).
Pour l'unité des fins de test, afin de vous permettre de ne tester que la chose que vous voulez tester, vous aurez besoin de la conception pour la testabilité. Cela implique généralement l'utilisation supplémentaire d'interfaces (je suis en supposant que .NET à partir du code que vous a montré) et une certaine forme d'injection de dépendance (mais ne l'exige pas un Cio/DI conteneur sauf si vous en voulez un). Il bénéficie également d', et vous encourage à créer très cohérent (simple effet) et découplées (soft dépendances) des classes dans votre système.
De sorte que lorsque vous les tests de logique d'entreprise qui repose sur des données provenant d'une base de données, vous utilisez généralement quelque chose comme la Modèle De Référentiel et injecter un faux/stub/maquette IXXXRepository pour les tests unitaires. Lorsque vous testez le béton référentiel, vous avez besoin de faire le type de base de données nettoyage, vous vous demandez ou vous avez besoin de cale/stub de la base de données d'appel. C'est vraiment à vous.
Lorsque vous avez besoin de créer/remplir/nettoyage de la base de données, vous pourriez envisager de prendre avantage de la configuration et des méthodes de démontage disponible dans la plupart des tests de cadres. Mais soyez prudent, car certains d'entre eux sont exécutés avant et après chaque test, qui peut sérieusement affecter les performances de vos tests unitaires. Les Tests qui tournent trop lentement ne sera pas très souvent, et c'est mauvais.
Dans MS-Test, les attributs que vous pouvez utiliser pour déclarer l'installation/démontage sont ClassInitialize, ClassCleanUp, TestInitialize, TestCleanUp. D'autres cadres ont nommé de la même manière constructions.
Il y a un certain nombre de cadres de qui peut vous aider avec le moqueur/stubbing: Moq, Rhino Se Moque De, NMock, TypeMock, Les taupes et les Talons de (VS2010), VS11 Faux (VS11 Bêta), etc. Si vous êtes à la recherche pour l'injection de dépendances cadres, regardez des choses comme Ninject, L'unité, Le Château De Windsor, etc.
Un couple de réponses:
Si c'est à l'aide d'une base de données réelle, je dirais que ce n'est pas un "test unitaire" dans le sens le plus strict du terme. C'est un test d'intégration. Un test unitaire devraient pas avoir de tels effets secondaires. Pensez à utiliser un moqueur de la bibliothèque pour simuler la base de données réelle. Rhino Se Moque De est un, mais il ya beaucoup d'autres.
Si, toutefois, l'ensemble de la point de ce test est de réellement interagir avec une base de données, alors vous aurez envie d'interagir avec un test transitoire seule base de données. Dans ce cas, une partie de votre test automatisé permettrait d'inclure du code pour construire la base de données de test à partir de zéro, puis exécutez les tests, puis de détruire la base de données de test. Encore une fois, l'idée est d'avoir aucun effets secondaires. Il y a sans doute de multiples façons d'aller à ce sujet, et je ne suis pas assez familier avec les tests unitaires des cadres pour vraiment donner une suggestion concrète. Mais si vous êtes en utilisant le test qui est intégré à Visual Studio, puis peut-être un Visual Studio Projet De Base De Données serait d'utilisation.
Votre question est un peu trop général. Habituellement, vous devez nettoyer après chaque test. Habituellement, vous ne pouvez pas compter que tous les tests sont toujours exécutées dans le même ordre, et vous devez être sûr de ce qui est dans votre base de données. Pour le général de l'installation ou nettoyage de la plupart des infrastructures de test unitaire fournir l'installation et le démontage des méthodes que vous pouvez remplacer et sera automatiquement appelé. Je ne sais pas comment ça fonctionne en C# mais l'e. g. dans JUnit (Java) vous avez une de ces méthodes.
Je suis d'accord avec David. Vos tests devrait normalement pas avoir d'effets secondaires. Vous devez mettre en place une nouvelle base de données pour chaque test.
Que vous aurez à faire un nettoyage manuel dans cette circonstance. C'est à dire, à l'opposé de la génération de certains objets dans la base de données.
L'alternative est d'utiliser les Moqueries des outils tels que la Rhino se moque de sorte que la base de données est seulement dans la mémoire de la base de données
Cela dépend de ce que vous êtes fait tests. La recherche sur les commentaires, je dirais oui, mais par la façon dont il est difficile de déduire de la recherche sur les commentaires. Le nettoyage de l'objet que vous venez d'insérer vous, dans la pratique, la réinitialisation de l'état du test. Donc, si vous le nettoyage, vous commencer à tester de nettoyage du système.
Je pense que le nettoyage dépend de la façon dont vous êtes en train de construire les données, de sorte que si "vieux données de test" n'interagissent pas avec l'avenir des tests fonctionne, je pense que c'est bien de le laisser derrière.
Une approche que j'ai été prise lors de l'écriture de tests d'intégration est d'avoir de l'exécution des tests contre un autre db que l'application db. J'ai tendance à reconstruire le test db en tant que condition préalable à chaque essai. De cette façon, vous n'avez pas besoin de granulés de nettoyage système pour chaque test, comme chaque essai obtient une ardoise propre entre les courses.
La plupart de mon développement, j'ai fait à l'aide de SQL server, mais j'ai, dans certains cas, exécuter mes tests sur un SQL Compact edition db, ce qui est rapide et efficace pour reconstruire entre les courses.
mbUnit a un très pratique attribut de Restauration qui nettoie la base de données après avoir terminé le test. Cependant, vous devrez configurer le DTC (Distributed Transaction Coordinator) afin d'être en mesure de l'utiliser.
J'ai eu, comparable à une question où un test de l'affirmation était empêche le nettoyage et causant d'autres tests à l'échec.
Espérons que cela est utile à quelqu'un, à un moment donné.
Le bloc finally sera exécuter si l'affirmation passe ou échoue, il également ne pas présenter un risque de faux laissez - passer qui catch cause!
Ce qui suit est un squelette d'une méthode de test que j'utilise. ceci me permet d'utiliser un try catch enfin faire le nettoyage de code dans le bloc finally sans perdre mes affirmer que l'échec.