2010-02-18 9 views
3

Supposons que j'ai plusieurs tests unitaires dans une classe de test ([TestClass] dans VSUnit dans mon cas). J'essaye de tester juste une chose dans chaque test (ne signifie pas juste un Assert cependant). Imaginez qu'il y ait un test (par exemple Test_MethodA()) qui teste également une méthode utilisée dans d'autres tests. Je ne veux pas mettre une affirmation sur cette méthode dans d'autres tests qui l'utilisent pour éviter les problèmes de duplicité/maintenabilité, donc j'ai l'affirmer dans ce seul test. Maintenant, lorsque ce test échoue, tous les tests qui dépendent de l'exécution correcte de cette méthode testée échouent également. Je veux être en mesure de localiser le problème plus rapidement, donc je veux être en quelque sorte pointé vers Test_MethodA. Ce serait par exemple aider si je pouvais exécuter certains tests dans la classe de test dans un ordre particulier et quand ils échouent, je commencerais à chercher la cause de l'échec du premier test. Avez-vous une idée de comment faire cela? Edit: En suggérant qu'une solution serait d'exécuter les tests dans un ordre particulier, je suis probablement allé trop loin et dans la mauvaise direction. Je me fiche de l'ordre des tests. C'est juste que certains tests échoueront toujours si un pré-requis n'est pas valide. Par exemple. J'ai une classe de test qui teste une classe DAO (ok, probablement pas un test UNIT, mais il y a une logique dans les procédures stockées de la base de données qui doit être testée mais ce n'est pas le point ici je pense). J'ai besoin d'insérer des enregistrements dans une table afin de tester qu'une méthode responsable de la récupération des enregistrements (appelons-la GetAll()) les récupère tous dans le bon ordre, par exemple. Je fais l'insertion en utilisant une méthode sur la classe DAO. Appelons-le Insert(). J'ai des tests en place qui vérifient que la méthode Insert() fonctionne comme prévu. Maintenant, je veux tester la méthode GetAll(). Afin d'obtenir la base de données dans un état désiré, j'utilise la méthode Insert(). Si Insert() ne fonctionne pas, la plupart des tests de GetAll() échoueront. Je préférerais marquer les tests qui ne peuvent pas passer car Insert() ne fonctionne pas comme non concluant plutôt que comme échoué. Cela faciliterait la recherche de la cause du problème si je connaissais la méthode/test à examiner en premier.Organiser le test unitaire dans une classe de test

Répondre

1

Je pense que je aurait en effet l'affirmation sur le résultat method_A() dans tous les tests reposant sur son résultat, même si cela introduit une certaine duplication. Ensuite, je voudrais utiliser le message d'assertion pour pointer vers le method_A() échec.

assert("method_A() returned true", true, rc); 

Peut-être vais-je mettre fin à l'extraction de la method_A() et appeler l'affirmation dans une fonction d'aide pour éliminer la duplication.

Maintenant, imaginons que method_A() interroge un objet et le renvoie, ou NULL quand aucun objet n'est trouvé. Alors cette assertion est guard; et il est nécessaire avec des langages tels que C, C++ qui n'ont pas NullPointerException.

0

Je crains que vous ne puissiez pas faire cela. La seule solution consiste à reconcevoir votre code et à le décomposer en méthodes plus petites afin que les tests unitaires puissent les appeler un par un. Bien sûr, ce n'est pas toujours souhaitable.

Avec Visual Studio, vous pouvez commander vos tests: see here. Mais je voudrais vous conseiller de rester à l'écart de cette technique autant que possible: les tests unitaires sont destinés à être exécutés n'importe où, n'importe quand et dans n'importe quel ordre.

EDIT: pourquoi est-ce un problème pour vous? Tous les tests défaillants pointent vers la même méthode de toute façon ...

3

Vous ne pouvez pas (et ne devez pas) exécuter des tests unitaires dans un ordre spécifique. La raison sous-jacente de ceci est d'empêcher Interacting Tests - Je réalise que votre motivation pour demander une telle fonctionnalité est différente, mais c'est la raison pour laquelle les frameworks de test unitaires ne vous permettent pas de commander des tests. En fait, la dernière fois que j'ai vérifié, xUnit.net même randomise la commande.

On pourrait argumenter que le fait que certains de vos tests dépendent d'un appel de méthode différent sur la même classe est un symptôme de couplage serré, mais ce n'est pas toujours le cas (les machines d'état me viennent à l'esprit). Toutefois, si possible, envisagez d'utiliser un Back Door au lieu de l'autre méthode en question.

Si vous ne pouvez pas faire cela ou découpler l'interdépendance (par exemple en rendant la première méthode virtuelle et en utilisant la technique Extract and Override), vous devrez vivre avec.

Voici un exemple:

public class MyClass 
{ 
    public virtual void FirstMethod() { // do something... } 

    public void SecondMethod() {} 
} 

Depuis FirstMethod est virtuel, vous pouvez dériver de MyClass et outrepasser son comportement. Vous pouvez également utiliser un simulacre dynamique pour le faire pour vous. Avec Moq, il ressemblerait à ceci:

var sutStub = new Mock<MyClass>(); 
// by default, Moq overrides all virtual methods without calling base 

// Now invoke both methods in sequence: 
sutStub.Object.FirstMethod(); // overriden by Moq, so it does nothing 
sutSutb.Object.SecondMethod(); 
+0

Merci pour le lien vers le site de Gerard Meszaros ... – trendl

Questions connexes