28 votes

NUnit - nettoyage après échec du test

Nous avons quelques tests NUnit que l'accès à la base de données. Quand l'un d'eux échoue, il peut laisser la base de données en état incohérent - ce qui n'est pas un problème, puisque nous reconstruire la base de données pour chaque série de tests - mais il peut causer d'autres tests à l'échec dans la même course.

Est-il possible de détecter que l'un des tests d'échec et d'effectuer une sorte de nettoyage?

Nous ne voulons pas écrire de code de nettoyage dans chaque test, nous avons déjà le faire maintenant. J'aimerais perfrom de nettoyage, Démontage, mais seulement si le test a échoué, comme l'opération de nettoyage peut être coûteux.

Mise à jour: À préciser - je voudrais des tests pour être simple et de ne PAS inclure tout le nettoyage ou le traitement des erreurs de logique. Aussi, je ne veux pas effectuer de la base de données réinitialiser à chaque essai, uniquement si le test échoue. Et ce code doit probablement être exécutée dans le Démontage de la méthode, mais je ne suis pas au courant d'une quelconque manière à obtenir des infos si nous sommes actuellement en train de déchirer vers le bas à partir échoué ou a été un succès.

Update2:

        [Test]
        public void MyFailTest()
        {
            throw new InvalidOperationException();
        }

        [Test]
        public void MySuccessTest()
        {
            Assert.That(true, Is.True);
        }

        [TearDown]
        public void CleanUpOnError()
        {
            if (HasLastTestFailed()) CleanUpDatabase();
        }

Je suis à la recherche pour la mise en œuvre de HasLastTestFailed()

46voto

Ran Points 261

Depuis la version 2.5.7, NUnit permet à Teardown de détecter si le dernier test a échoué. Une nouvelle classe TestContext permet aux tests d'accéder aux informations les concernant, y compris les TestStauts.

Pour plus de détails, veuillez consulter http://nunit.org/?p=releaseNotes&r=2.5.7

 [TearDown]
public void TearDown()
{
    if (TestContext.CurrentContext.Result.Status == TestStatus.Failed)
    {
        PerformCleanUpFromTest();
    }
}
 

17voto

Igal Tabachnik Points 15160

Cette idée m'a intéressé, j'ai donc fait un peu de creuser. NUnit n'ont pas cette possibilité de sortir de la boîte, mais il y a toute une extensibility framework fourni avec NUnit. J'ai trouvé cet excellent article sur l'extension de NUnit - c'était un bon point de départ. Après avoir joué un peu avec elle, je suis venu avec la solution suivante: une méthode décoré avec une coutume CleanupOnError attribut sera appelée si l'un des tests de l'appareil a échoué.

Voici comment le test ressemble:

  [TestFixture]
  public class NUnitAddinTest
  {
    [CleanupOnError]
    public static void CleanupOnError()
    {
      Console.WriteLine("There was an error, cleaning up...");
      // perform cleanup logic
    }

    [Test]
    public void Test1_this_test_passes()
    {
      Console.WriteLine("Hello from Test1");
    }

    [Test]
    public void Test2_this_test_fails()
    {
      throw new Exception("Test2 failed");
    }

    [Test]
    public void Test3_this_test_passes()
    {
      Console.WriteLine("Hello from Test3");
    }
  }

où l'attribut est tout simplement:

  [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
  public sealed class CleanupOnErrorAttribute : Attribute
  {
  }

Et voici comment il est exécuté à partir de l'addin:

public void RunFinished(TestResult result)
{
  if (result.IsFailure)
  {
    if (_CurrentFixture != null)
    {
      MethodInfo[] methods = Reflect.GetMethodsWithAttribute(_CurrentFixture.FixtureType,
                                                             CleanupAttributeFullName, false);
      if (methods == null || methods.Length == 0)
      {
        return;
      }

      Reflect.InvokeMethod(methods[0], _CurrentFixture);
    }
  }
}

Mais ici, la partie la plus délicate: le complément doit être placé dans l' addins répertoire à côté de la NUnit coureur. Le mien était placé à côté de la NUnit coureur en TestDriven.NET répertoire:

C:\Program Files\TestDriven.NET 2.0\NUnit\addins

(J'ai créé l' addins répertoire, il n'était pas là)

MODIFIER une Autre chose est que la méthode de nettoyage doit être static!

J'ai bidouillé un simple complément, vous pouvez télécharger la source de mon SkyDrive. Vous devrez ajouter des références à nunit.framework.dll, nunit.core.dll et nunit.core.interfaces.dll dans les endroits appropriés.

Quelques remarques: L'attribut de classe peut être placé n'importe où dans votre code. Je ne voulais pas le placer dans la même assemblée que le complément lui-même, car il fait référence à deux Core NUnit assemblées, donc je l'ai placé dans un montage différent. N'oubliez pas de modifier la ligne dans l' CleanAddin.cs, si vous décider de le mettre n'importe où ailleurs.

Espérons que cela aide.

2voto

Frank V Points 9690

Oui, il est. Vous pouvez utiliser le Démontage de l'attribut qui sera le démontage après chaque test. Vous voulez appliquer la Base de données "reset" script que vous avez et le démontage et re-installation avant et après chaque test.

Cet attribut est utilisé à l'intérieur d'un TestFixture à fournir un ensemble commun de les fonctions qui sont exécutées après chaque méthode de test est exécuté.

Mise à jour: sur la Base des commentaires et de mettre à jour à la question, je dirais que vous pouvez utiliser le démontage de l'attribut et d'utiliser les variables pour indiquer si la méthode le contenu de feu.

Cependant, je ne vois aussi que vous ne voulez pas de logique complexe ou code de gestion d'erreur.

Étant donné que, je pense qu'une norme d'Installation/Démontage qui fonctionnent le mieux pour vous. Il n'a pas d'importance si il y a une erreur et que vous n'avez pas besoin de tout code de gestion d'erreur.

Si vous avez besoin de spécial nettoyer parce que les prochains tests dépend de la réussite de l'essai de courant, je te suggère de revoir votre tests-ils probablement ne devrait pas dépendre les uns des autres.

2voto

Ray Hayes Points 9819

Bien qu'il soit possible de contraindre nUnit à le faire, ce n'est pas la conception la plus judicieuse, vous pouvez toujours définir un fichier temporaire quelque part et si ce fichier existe, exécutez votre nettoyage.

Je recommanderais de changer votre code pour que les transactions de base de données soient activées et à la fin du test, il suffit de ramener la base de données à son état d'origine (par exemple, annuler la transaction qui représente vos tests unitaires).

1voto

Dan McClain Points 7036

Qu'en est-il de l'utilisation d'un bloc Try-Catch et de la levée de l'exception interceptée?

 try
{
//Some assertion
}
catch
{
     CleanUpMethod();
     throw;
}
 

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