Frage

Wir haben einige NUnit Tests, die auf die Datenbank zugreifen. Wenn einer von ihnen ausfällt kann es Datenbank in inkonsistenten Zustand - das ist kein Problem, da wir Datenbank für jeden Testlauf wieder aufbauen -. Aber es kann andere Tests dazu führen, dass im gleichen Lauf scheitern

Ist es möglich, zu erkennen, dass einer der Tests nicht bestanden und eine Art Bereinigung durchführen?

Wir wollen keinen Bereinigungscode in jedem Test zu schreiben, haben wir bereits jetzt. Ich möchte Bereinigung in Teardown perfrom aber nur, wenn der Test fehlgeschlagen ist, als Bereinigungs teuer sein könnte.

Aktualisieren : Um klären - ich würde Tests einfach sein mögen und umfassen keine Bereinigung oder Fehlerbehandlungslogik. Ich will auch nicht Datenbank-Reset auf jedem Testlauf durchführen - nur, wenn der Test fehlschlägt. Und dieser Code sollte wahrscheinlich in Teardown-Methode ausgeführt werden, aber ich bin nicht von irgendeiner Weise bewusst Informationen zu erhalten, wenn Test, den wir zur Zeit reißen aus fehlgeschlagenen oder erfolgreich waren.

Update2 :

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

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

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

Ich bin auf der Suche für die Umsetzung von HasLastTestFailed ()

War es hilfreich?

Lösung

Diese Idee hat mich interessiert, so habe ich ein wenig zu graben. NUnit verfügt nicht über diese Fähigkeit, aus der Box, aber es gibt ein ganzes erweiterbares Framework mit NUnit geliefert. Ich fand diesen großen Artikel über Verlängerung NUnit - es war ein guter Ausgangspunkt. Nachdem er mit ihm herumspielen, kam ich auf die folgende Lösung: eine Methode mit einer benutzerdefinierten CleanupOnError-Attribut versehen genannt werden, wenn einer der Tests in der Halterung fehlgeschlagen

.

Hier ist, wie der Test wie folgt aussieht:

  [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");
    }
  }

, wo das Attribut ist einfach:

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

Und hier ist, wie es aus dem Addin ausgeführt ist:

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);
    }
  }
}

Aber hier ist der schwierige Teil: die Addin muss neben dem NUnit Läufer im addins Verzeichnis platziert werden. Meins war neben dem NUnit Läufer in TestDriven.NET Verzeichnis abgelegt sind:

  

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

(Ich habe das addins Verzeichnis erstellt, es war nicht da)

Bearbeiten Eine andere Sache ist, dass das Bereinigungsverfahren static werden muss!

Ich gehackt zusammen eine einfache Addin, können Sie den Quellcode herunterladen von mein SkyDrive . Sie müssen Verweise auf nunit.framework.dll, nunit.core.dll und nunit.core.interfaces.dll an den entsprechenden Stellen hinzuzufügen.

Ein paar Anmerkungen: Die Attributklasse überall in Ihrem Code platziert werden kann. Ich wollte es nicht in der gleichen Anordnung wie die Addin platzieren selbst, weil es zwei Core NUnit Assemblys verweist, so legte ich sie in einer anderen Anordnung. Denken Sie daran, die Zeile in der CleanAddin.cs ändern, wenn Sie sich entscheiden, um es irgendwo anders.

Ich hoffe, das hilft.

Andere Tipps

Seit Version 2.5.7 erlaubt NUnit Teardown zu erkennen, ob letzter Test nicht bestanden. Eine neue Testcontext-Klasse ermöglicht Tests über sich den TestStauts einschließlich zugreifen zu können.

Weitere Informationen finden Sie unter http://nunit.org/?p=releaseNotes&r = 2.5.7

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

Während es möglich sein könnte nUnit das zu tun, dies zu zwingen, sie nicht das vernünftigste Design ist, könnten Sie immer eine temporäre Datei irgendwo gesetzt und wenn diese Datei vorhanden ist, führen Sie Ihre Bereinigung.

Ich würde empfehlen, den Code zu ändern, so dass Sie Datenbank-Transaktionen aktiviert und am Ende des Tests, einfach die Datenbank in dem ursprünglichen Zustand zurück (zum Beispiel der Transaktion verwerfen, die Ihre Gerät-Tests darstellt).

Ja, es gibt. Sie können die Teardown Attribut die wird nach jedem Test Teardown. Sie würden wollen, dass Datenbank „Reset“ Skript anwenden, die Sie haben und Abrüsten und Neueinstellung vor und nach jedem Test.

  

Dieses Attribut ist im Innern eines benutzten   TestFixture, um einen gemeinsamen Satz von   Funktionen, die ausgeführt werden, nachdem   Jede Testmethode ausgeführt wird.

Aktualisieren : Basierend auf den Kommentaren und Update auf die Frage, ich würde sagen, dass Sie die Teardown-Attribut verwenden können und privaten Variablen verwenden, um anzuzeigen, ob die Methode Inhalt sollte abzufeuern.

Obwohl, ich habe auch, dass Sie wollen keine komplexe Logik oder Fehlerbehandlungscode.

Da würde ich denken, dass ein Standard-Setup / Teardown würde funktionieren am besten für Sie. Es spielt keine Rolle, ob es ein Fehler ist, und Sie haben keine Fehlerbehandlung Code haben.

Wenn Sie spezielle müssen aufzuräumen, weil die nächsten Tests nach erfolgreichem Abschluss des aktuellen Tests abhängt, würde ich vorschlagen, die Tests zu überdenken -. Sie wahrscheinlich nicht voneinander abhängen sollte

Was ist ein Try-Catch-Block verwenden, Erneutes Auslösen der Ausnahme gefangen?

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

ich tun würde, wie PHSR jetzt schlägt vor, und wenn Sie es sich leisten können, Refactoring, die Tests so, dass sie nie die Ergebnisse aus Richtung auf die gleichen Daten, dass eine andere Testanforderungen oder noch besser abstrakt die Datenzugriffsschicht und verspotten verlassen müssen diese Datenbank. Es klingt wie Ihre Tests ziemlich teuer sind, und Sie sollten Sie auf die Datenbank und Business-Logik in Ihrer Assembly alle Abfragelogik tun Sie nicht wirklich, was die Ergebnisse sind, die zurückgegeben werden.

Sie können auch Ihre testen viel besser Exceptionhandling.

Eine weitere Option ist eine spezielle Funktion zu haben, die Ihre Ausnahmen werfen, die einen Schalter in dem TestFixture setzt, das sagt eine Ausnahme aufgetreten.

public abstract class CleanOnErrorFixture
{
     protected bool threwException = false;

     protected void ThrowException(Exception someException)
     {
         threwException = true;
         throw someException;
     }

     protected bool HasTestFailed()
     {
          if(threwException)
          {
               threwException = false; //So that this is reset after each teardown
               return true;
          }
          return false;
     }
}

Dann mit Ihrem Beispiel:

[TestFixture]
public class SomeFixture : CleanOnErrorFixture
{
    [Test]
    public void MyFailTest()
    {
        ThrowException(new InvalidOperationException());
    }

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

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

Das einzige Problem dabei ist, dass der Stack-Trace zum CleanOnErrorFixture führt

Eine Option bisher nicht erwähnt wird, ist der Test bis in einem Transaction Objekt zu wickeln, so dass es keine Rolle spielt, was passiert, wenn der Test nie etwas an die DB verpflichtet.

Hier ist einige Details über die Technik . Sie können sich wahrscheinlich mehr finden, wenn Sie eine Suche auf Unit-Tests und Transaction tun (obwohl Sie wirklich Integrationstests tun, wenn Sie einen DB getroffen). Ich habe es in der Vergangenheit erfolgreich eingesetzt.

Dieser Ansatz ist einfach, erfordert keine Reinigung und sorgt dafür, dass Tests isoliert sind.

Bearbeiten- Ich habe gerade bemerkt Ray Hayes Antwort ist auch ähnlich wie ich.

Wie funktioniert es nicht? Ist es möglich, sie in einem Versuch setzen (do-Test) / catch (fix gebrochen db) / finally-Block?

Sie können auch eine private Methode nennen, es zu beheben, wenn Sie Ihre scheitern Zustand überprüft haben.

Ich sage nicht, das ist eine gute Idee, aber es sollte funktionieren. Beachten Sie, dass Assertionsfehler nur Ausnahmen. Vergessen Sie auch nicht gibt es auch ein [TestFixtureTearDown] Attribut, das nur einmal ausgeführt, nachdem alle Tests in der Vorrichtung ausgeführt haben.

Unter Verwendung dieser zwei Fakten, die Sie so etwas wie Setzen eines Flags, wenn ein Tests nicht bestanden und die Überprüfung der Wert der Markierung in der Testvorrichtung abzureißen schreiben kann.

Ich empfehle dies nicht, aber es funktionieren würde. Sie sind nicht wirklich NUnit verwenden, wie beabsichtigt, aber Sie können es tun.


[TestFixture]
public class Tests {
     private bool testsFailed = false;

     [Test]
     public void ATest() {
         try {
             DoSomething();
             Assert.AreEqual(....);
         } catch {
            testFailed = true;
         }
     }

     [TestFixtureTearDown]
     public void CleanUp() {
          if (testsFailed) {
              DoCleanup();
          }
     }
}

Sie können eine [TearDown] Methode mit
if (TestContext.CurrentContext.Result.Status != TestStatus.Passed)
einige Code ausgeführt werden, wenn der Test fehlgeschlagen ist.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top