it-swarm.com.de

NUnit-Testlaufreihenfolge

Nunit-Tests werden standardmäßig alphabetisch ausgeführt. Kennt jemand eine Möglichkeit, die Ausführungsreihenfolge festzulegen? Gibt es dafür ein Attribut?

105
Riain McAtamney

Ihre Komponententests sollten unabhängig voneinander ausgeführt werden können. Wenn sie dieses Kriterium erfüllen, spielt die Reihenfolge keine Rolle.

Es gibt jedoch Situationen, in denen Sie bestimmte Tests zuerst ausführen möchten. Ein typisches Beispiel ist eine Continuous Integration-Situation, in der einige Tests länger laufen als andere. Wir verwenden das category-Attribut, damit wir die Tests ausführen können, bei denen das Spotting vor den Tests verwendet wird, die die Datenbank verwenden.

setzen Sie dies an den Anfang Ihrer Schnelltests

[Category("QuickTests")]

Wenn Sie Tests haben, die von bestimmten Umgebungsbedingungen abhängig sind, sollten Sie die Attribute TestFixtureSetUp und TestFixtureTearDown beachten, mit denen Sie Methoden markieren können, die vor und nach Ihren Tests ausgeführt werden sollen.

47
NeedHack

Ich möchte nur darauf hinweisen, dass die meisten der Befragten davon ausgegangen sind, dass es sich um Einzeltests handelt, die Frage war jedoch nicht angegeben.

nUnit ist ein großartiges Werkzeug, das für eine Vielzahl von Testsituationen verwendet werden kann. Ich sehe geeignete Gründe dafür, die Testreihenfolge kontrollieren zu wollen.

In diesen Situationen musste ich eine Testreihenfolge in den Testnamen integrieren. Es wäre großartig, wenn Sie die Laufreihenfolge mithilfe eines Attributs angeben können.

163
Leslie

NUnit 3.2.0 fügte eine OrderAttribute hinzu, siehe:

https://github.com/nunit/docs/wiki/Order-Attribute

Beispiel:

public class MyFixture
{
    [Test, Order(1)]
    public void TestA() { ... }


    [Test, Order(2)]
    public void TestB() { ... }

    [Test]
    public void TestC() { ... }
}
94

Wenn die Tests in einer bestimmten Reihenfolge ausgeführt werden sollen, bedeutet dies nicht, dass die Tests voneinander abhängig sind. Ich arbeite zurzeit an einem TDD-Projekt Es ist lesbarer, wenn ich die Reihenfolge angeben könnte, in der die Testergebnisse angezeigt - thematisch anstelle von alphabetisch sind. Das einzige, woran ich denken kann, ist, Klassen, Namespaces und Methoden mit a_ b_ c_ zu versehen. (Nicht schön) Ich denke, ein [TestOrderAttribute] -Attribut wäre Nizza - nicht strikt gefolgt vom Framework, aber ein Hinweis, damit wir dies erreichen können

21
William

Unabhängig davon, ob Tests von der Bestellung abhängig sind oder nicht ... einige von uns möchten einfach alles auf eine geordnete Weise kontrollieren.

Komponententests werden normalerweise in der Reihenfolge der Komplexität erstellt. Warum sollten sie nicht auch in der Reihenfolge ihrer Komplexität oder in der Reihenfolge ausgeführt werden, in der sie erstellt wurden?

Ich persönlich mag es, wenn die Tests in der Reihenfolge laufen, in der ich sie erstellt habe. In TDD wird jeder nachfolgende Test naturgemäß komplexer und benötigt mehr Zeit zum Ausführen. Ich würde eher sehen, dass der einfachere Test zuerst fehlschlägt, da er ein besserer Indikator für die Fehlerursache ist.

Ich kann jedoch auch den Vorteil erkennen, wenn sie in zufälliger Reihenfolge ausgeführt werden, insbesondere wenn Sie testen möchten, dass Ihre Tests keine Abhängigkeiten von anderen Tests haben. Wie wäre es, eine Option zum Testen von Läufern zu "Tests zufällig bis gestoppt ausführen" hinzuzufügen?

10
Mont Pierce

Ich teste mit Selenium auf einer recht komplexen Website, und die gesamte Testsuite kann länger als eine halbe Stunde laufen. Ich kann die gesamte Anwendung noch nicht abdecken. Wenn ich sicherstellen muss, dass alle vorherigen Formulare für jeden Test korrekt ausgefüllt wurden, erhöht dies den Gesamttest um viel Zeit und nicht nur um ein wenig Zeit. Wenn die Tests zu viel Aufwand verursachen, werden sie von den Benutzern nicht so oft ausgeführt, wie sie sollten.

Also ordne ich sie an und bin auf vorherige Tests angewiesen, um Textfelder und solche Felder ausfüllen zu lassen. Ich verwende Assert.Ignore (), wenn die Vorbedingungen nicht gültig sind, aber ich muss sie in der richtigen Reihenfolge ausführen.

9

Die vorherige Antwort gefällt mir sehr gut. 

Ich habe es ein wenig geändert, um den Ordnungsbereich mit einem Attribut einstellen zu können:

namespace SmiMobile.Web.Selenium.Tests
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;
    using NUnit.Framework;

    public class OrderedTestAttribute : Attribute
    {
        public int Order { get; set; }


        public OrderedTestAttribute(int order)
        {
            Order = order;
        }
    }

    public class TestStructure
    {
        public Action Test;
    }

    class Int
    {
        public int I;
    }

    [TestFixture]
    public class ControllingTestOrder
    {
        private static readonly Int MyInt = new Int();

        [TestFixtureSetUp]
        public void SetUp()
        {
            MyInt.I = 0;
        }

        [OrderedTest(0)]
        public void Test0()
        {
            Console.WriteLine("This is test zero");
            Assert.That(MyInt.I, Is.EqualTo(0));
        }

        [OrderedTest(2)]
        public void ATest0()
        {
            Console.WriteLine("This is test two");
            MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(2));
        }


        [OrderedTest(1)]
        public void BTest0()
        {
            Console.WriteLine("This is test one");
            MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(1));
        }

        [OrderedTest(3)]
        public void AAA()
        {
            Console.WriteLine("This is test three");
            MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(3));
        }


        [TestCaseSource(sourceName: "TestSource")]
        public void MyTest(TestStructure test)
        {
            test.Test();
        }

        public IEnumerable<TestCaseData> TestSource
        {
            get
            {
                var Assembly =Assembly.GetExecutingAssembly();
                Dictionary<int, List<MethodInfo>> methods = Assembly
                    .GetTypes()
                    .SelectMany(x => x.GetMethods())
                    .Where(y => y.GetCustomAttributes().OfType<OrderedTestAttribute>().Any())
                    .GroupBy(z => z.GetCustomAttribute<OrderedTestAttribute>().Order)
                    .ToDictionary(gdc => gdc.Key, gdc => gdc.ToList());

                foreach (var order in methods.Keys.OrderBy(x => x))
                {
                    foreach (var methodInfo in methods[order])
                    {
                        MethodInfo info = methodInfo;
                        yield return new TestCaseData(
                            new TestStructure
                                {
                                    Test = () =>
                                        {
                                            object classInstance = Activator.CreateInstance(info.DeclaringType, null);
                                            info.Invoke(classInstance, null);
                                        }
                                }).SetName(methodInfo.Name);
                    }
                }

            }
        }
    }
}
9
PvtVandals

Ich weiß, dass dies ein relativ alter Post ist, aber es gibt eine andere Möglichkeit, um den Test in der Reihenfolge zu halten, OHNE die Testnamen umständlich zu machen. Wenn Sie das TestCaseSource-Attribut verwenden und das übergebene Objekt über einen Delegaten (Aktion) verfügt, können Sie nicht nur die Reihenfolge steuern, sondern auch den Test benennen, wie er ist. 

Dies funktioniert, da gemäß der Dokumentation die von der Testquelle zurückgegebenen Elemente in der Sammlung immer in der Reihenfolge ausgeführt werden, in der sie aufgelistet sind.

Hier ist eine Demo von einer Präsentation, die ich morgen gebe:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;

namespace NUnitTest
{
    public class TestStructure
    {
        public Action Test;
    }

    class Int
    {
        public int I;
    }

    [TestFixture]
    public class ControllingTestOrder
    {
        private static readonly Int MyInt= new Int();

        [TestFixtureSetUp]
        public void SetUp()
        {
            MyInt.I = 0;
        }

        [TestCaseSource(sourceName: "TestSource")]
        public void MyTest(TestStructure test)
        {
            test.Test();
        }

        public IEnumerable<TestCaseData> TestSource
        {
            get
            {
                yield return new TestCaseData(
                    new TestStructure
                    {
                        Test = () =>
                        {
                            Console.WriteLine("This is test one");
                            MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(1));
                        }
                    }).SetName(@"Test One");
                yield return new TestCaseData(
                    new TestStructure
                    {
                        Test = () =>
                        {
                            Console.WriteLine("This is test two");
                            MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(2));
                        }
                    }).SetName(@"Test Two");
                yield return new TestCaseData(
                    new TestStructure
                    {
                        Test = () =>
                        {
                            Console.WriteLine("This is test three");
                            MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(3));
                        }
                    }).SetName(@"Test Three");
            }
        }
    }
}
7
Dave Bush

Ich arbeite mit End-to-End-UI-Testfällen von Selenium WebDriver, die in C # geschrieben wurden und mit dem NUnit-Framework ausgeführt werden. (Nicht Einzelfälle als solche)

Diese UI-Tests hängen sicherlich von der Reihenfolge der Ausführung ab, da andere Tests einige Daten als Voraussetzung hinzufügen müssen. (Es ist nicht möglich, die Schritte in jedem Test durchzuführen.)

Nach dem Hinzufügen des 10. Testfalls sehe ich, dass NUnit in dieser Reihenfolge ausgeführt werden soll: Test_1 Test_10 Test_2 Test_3 ..

Ich schätze, ich muss die Namen der Testfälle vorerst alphabetisieren, aber es wäre gut, wenn ich diese kleine Funktion zur Steuerung der Ausführungsreihenfolge in NUnit hätte.

5
Hexa

Es gibt sehr gute Gründe, einen Testbestellungsmechanismus zu verwenden. Die meisten meiner eigenen Tests verwenden bewährte Methoden wie das Einrichten/Abnehmen. Andere erfordern große Datenmengen, die zum Testen einer Reihe von Funktionen verwendet werden können. Bisher habe ich umfangreiche Tests durchgeführt, um diese Integrationstests (Selenium Webdriver) durchzuführen. Ich denke jedoch, dass der oben vorgeschlagene Beitrag auf https://github.com/nunit/docs/wiki/Order-Attribute viel Verdienst hat. Hier ein Beispiel, warum eine Bestellung äußerst wertvoll ist:

  • Verwenden von Selenium Webdriver zum Ausführen eines Tests zum Herunterladen eines Berichts
  • Der Status des Berichts (ob er heruntergeladen werden kann oder nicht) wird für 10 Minuten zwischengespeichert.
  • Das heißt, vor jedem Test muss ich den Berichtsstatus zurücksetzen und dann bis 10 Minuten warten, bis sich der Status als geändert bestätigt hat, und dann überprüfen, ob der Bericht ordnungsgemäß heruntergeladen wird.
  • Die Berichte können aufgrund ihrer Komplexität nicht durch Spott oder andere Mechanismen innerhalb des Testrahmens praktisch/zeitnah erstellt werden.

Diese Wartezeit von 10 Minuten verlangsamt die Testsuite. Wenn Sie ähnliche Caching-Verzögerungen über eine Vielzahl von Tests hinweg multiplizieren, kostet dies viel Zeit. Durch das Anordnen von Tests könnte das Einrichten der Daten direkt zu Beginn der Testsuite als "Test" durchgeführt werden, wobei die Tests darauf beruhen, dass der Cache-Speicher zum Ende des Testlaufs ausgeführt wird.

3
user2986256

Normalerweise sollte Unit Test unabhängig sein, aber wenn Sie müssen, können Sie Ihre Methoden in alphabetischer Reihenfolge benennen.

[Test]
public void Add_Users(){}

[Test]
public void Add_UsersB(){}

[Test]
public void Process_Users(){}

oder du kannst es tun ..

        private void Add_Users(){}

        private void Add_UsersB(){}

        [Test]
        public void Process_Users()
        {
           Add_Users();
           Add_UsersB();
           // more code
        }
3

Diese Frage ist jetzt wirklich alt, aber für Leute, die dies durch Suchen erreichen können, habe ich die hervorragenden Antworten von user3275462 und PvtVandals/Rico genommen und sie zusammen mit einigen eigenen Updates zu einem GitHub-Repository hinzugefügt. Ich habe auch einen zugehörigen Blogbeitrag mit einigen zusätzlichen Informationen erstellt, die Sie für weitere Informationen einsehen können.

Ich hoffe, das ist für alle hilfreich. Außerdem benutze ich häufig das Category-Attribut, um meine Integrationstests oder andere End-to-End-Tests von meinen tatsächlichen Komponententests zu unterscheiden. Andere haben darauf hingewiesen, dass Unit-Tests nicht von der Reihenfolge der Bestellung abhängig sein sollten. Andere Testtypen tun dies jedoch häufig. Dies ist eine gute Möglichkeit, nur die gewünschte Testkategorie auszuführen und die End-to-End-Tests zu ordnen.

2
Chrispy

Ich bin überrascht, dass die NUnit-Community noch nichts gefunden hat, also habe ich mir selbst so etwas vorgenommen. 

Ich bin derzeit Entwickelt eine Open-Source-Bibliothek , mit der Sie Ihre Tests bei NUnit bestellen können. Sie können Testzubehör bestellen und "bestellte Testspezifikationen" gleich bestellen. 

Die Bibliothek bietet folgende Funktionen:

  • Erstellen Sie komplexe Testreihenhierarchien
  • Überspringen Sie nachfolgende Tests, wenn ein Test in der Reihenfolge fehlschlägt
  • Bestellen Sie Ihre Testmethoden nach Abhängigkeit statt nach ganzzahliger Reihenfolge
  • Unterstützt die Verwendung nebeneinander bei ungeordneten Tests. Ungeordnete Tests werden zuerst ausgeführt.

Die Bibliothek ist in der Tat inspiriert, wie MSTest die Bestellung von .orderedtest-Dateien durchführt. Bitte schauen Sie sich ein Beispiel unten an.

[OrderedTestFixture]
public sealed class MyOrderedTestFixture : TestOrderingSpecification {
    protected override void DefineTestOrdering() {
        TestFixture<Fixture1>();

        OrderedTestSpecification<MyOtherOrderedTestFixture>();

        TestFixture<Fixture2>();
        TestFixture<Fixture3>();
    }

    protected override bool ContinueOnError => false; // Or true, if you want to continue even if a child test fails
}
1
Sebazzz

Im Falle der Verwendung von TestCaseSource lautet der Schlüssel zur override string ToString -Methode.

Angenommen, Sie haben die TestCase-Klasse

public class TestCase
{
    public string Name { get; set; }
    public int Input { get; set; }
    public int Expected { get; set; }
}

Und eine Liste von Testfällen:

private static IEnumerable<TestCase> TestSource()
{
    return new List<TestCase>
    {
        new TestCase()
        {
           Name = "Test 1",
           Input = 2,
           Expected = 4
        },
        new TestCase()
        {
            Name = "Test 2",
            Input = 4,
            Expected = 16
        },
        new TestCase()
        {
            Name = "Test 3",
            Input = 10,
            Expected = 100
        }
    };
}

Jetzt können Sie es mit einer Testmethode verwenden und sehen, was passiert:

[TestCaseSource(nameof(TestSource))]
public void MethodXTest(TestCase testCase)
{
    var x = Power(testCase.Input);
    x.ShouldBe(testCase.Expected);
}

Dies wird nicht in der richtigen Reihenfolge getestet und die Ausgabe sieht folgendermaßen aus:

enter image description here

Wenn wir also override string ToString zu unserer Klasse hinzufügen, wie:

public class TestCase
{
    public string Name { get; set; }
    public int Input { get; set; }
    public int Expected { get; set; }

    public override string ToString()
    {
        return Name;
    }
}

Das Ergebnis ändert sich und wir erhalten die Reihenfolge und den Namen des Tests wie folgt:

enter image description here

Hinweis:

  1. Dies ist nur ein Beispiel, um zu veranschaulichen, wie Name und Reihenfolge im Test ermittelt werden. Die Reihenfolge ist numerisch/alphabetisch. Wenn Sie also mehr als zehn Tests haben, empfehle ich, Test 01, Test 02 .... Test 10, Test 11 usw. durchzuführen, denn wenn Sie machen Test 1 und irgendwann Test 10, dann lautet die Reihenfolge Test 1, Test 10, Test 2 usw.
  2. Die Eingabe und "Erwartet" können ein beliebiger Typ, eine Zeichenfolge, ein Objekt oder eine benutzerdefinierte Klasse sein.
  3. Neben der Ordnung ist das Gute hier, dass Sie den Testnamen sehen, der wichtiger ist.

Wenn Sie [TestCase] verwenden, gibt das Argument TestName einen Namen für den Test an. 

Wenn nicht angegeben, wird ein Name basierend auf dem Methodennamen und den angegebenen Argumenten generiert. 

Sie können die Reihenfolge der Testausführung wie folgt festlegen:

                    [Test]
            [TestCase("value1", TestName = "ExpressionTest_1")]
            [TestCase("value2", TestName = "ExpressionTest_2")]
            [TestCase("value3", TestName = "ExpressionTest_3")]
            public void ExpressionTest(string  v)
            {
                //do your stuff
            }

Hier habe ich den Methodennamen "ExpressionTest"-Suffix mit einer Nummer verwendet. 

Sie können beliebige Namen verwenden, die alphabetisch geordnet sind Siehe TestCase Attribute

0
M.Hassan

Sie sollten sich nicht auf die Reihenfolge verlassen, in der das Test-Framework Tests zur Ausführung auswählt. Tests sollten isoliert und unabhängig sein. Dabei sollten sie nicht darauf angewiesen sein, dass ein anderer Test die Bühne für sie bereitstellt oder nach ihnen aufräumt. Sie sollten auch unabhängig von der Reihenfolge der Testausführung dasselbe Ergebnis liefern (für eine bestimmte Momentaufnahme des SUT).

Ich habe ein bisschen gegoogelt. Wie üblich haben einige Leute auf hinterlistige Tricks zurückgegriffen (anstatt das zugrunde liegende Testbarkeits-/Designproblem zu lösen 

  • benennung der Tests in alphabetischer Reihenfolge, so dass die Tests in der Reihenfolge erscheinen, in der sie ausgeführt werden müssen. NUnit kann sich jedoch dazu entscheiden, dieses Verhalten in einer späteren Version zu ändern, und Ihre Tests werden dann abgehängt. Überprüfen Sie besser die aktuellen NUnit-Binaries in Source Control.
  • VS (IMHO, das mit ihren "agilen Tools" das falsche Verhalten anregt) hat in seinem MS-Test-Framework etwas "geordnete Tests" genannt. Ich habe keine Zeit verschwendet, um mich vorzulesen

Siehe auch: Eigenschaften eines guten Tests

0
Gishu