Standardmäßig werden Nunit-Tests alphabetisch ausgeführt. Kennt jemand eine Möglichkeit, die Ausführungsreihenfolge festzulegen? Gibt es dafür ein Attribut?
Standardmäßig werden Nunit-Tests alphabetisch ausgeführt. Kennt jemand eine Möglichkeit, die Ausführungsreihenfolge festzulegen? Gibt es dafür ein Attribut?
Antworten:
Ihre Unit-Tests sollten jeweils unabhängig und eigenständig ausgeführt werden können. Wenn sie dieses Kriterium erfüllen, spielt die Reihenfolge keine Rolle.
Es gibt jedoch Fälle, in denen Sie zuerst bestimmte Tests ausführen möchten. Ein typisches Beispiel ist eine Situation mit kontinuierlicher Integration, in der einige Tests länger ausgeführt werden als andere. Wir verwenden das Attribut category, damit wir die Tests, bei denen Mocking verwendet wird, vor den Tests ausführen können, bei denen die Datenbank verwendet wird.
dh setzen Sie dies zu Beginn Ihrer Schnelltests
[Category("QuickTests")]
Berücksichtigen Sie bei Tests, die von bestimmten Umgebungsbedingungen abhängen , die Attribute TestFixtureSetUp und TestFixtureTearDown , mit denen Sie Methoden markieren können, die vor und nach Ihren Tests ausgeführt werden sollen.
Ich möchte nur darauf hinweisen, dass die meisten Befragten zwar davon ausgegangen sind, dass es sich um Komponententests handelt, in der Frage jedoch nicht angegeben wurde, dass dies der Fall ist.
nUnit ist ein großartiges Tool, das für eine Vielzahl von Testsituationen verwendet werden kann. Ich kann geeignete Gründe dafür sehen, die Testreihenfolge kontrollieren zu wollen.
In solchen Situationen musste ich darauf zurückgreifen, eine Ausführungsreihenfolge in den Testnamen aufzunehmen. Es wäre großartig, die Ausführungsreihenfolge mithilfe eines Attributs angeben zu können.
001_first_test
002_second_test
und so weiter?
NUnit 3.2.0 hat eine hinzugefügt OrderAttribute
, 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() { ... }
}
Wenn die Tests in einer bestimmten Reihenfolge ausgeführt werden sollen, bedeutet dies nicht, dass die Tests voneinander abhängig sind. Ich arbeite derzeit an einem TDD-Projekt und bin ein guter TDDer. Ich habe alles verspottet / gestoppt, aber es würde funktionieren Es ist besser lesbar, wenn ich die Reihenfolge angeben könnte, in der die Testergebnisse angezeigt werden - thematisch statt alphabetisch. Bisher kann ich mir nur vorstellen, a_ b_ c_ Klassen Klassen, Namespaces und Methoden voranzustellen. (Nicht schön) Ich denke, ein [TestOrderAttribute] -Attribut wäre schön - nicht streng gefolgt vom Framework, sondern ein Hinweis, damit wir dies erreichen können
Unabhängig davon, ob Tests auftragsabhängig sind oder nicht ... einige von uns möchten einfach alles auf geordnete Weise kontrollieren.
Unit-Tests werden normalerweise in der Reihenfolge ihrer Komplexität erstellt. Warum sollten sie nicht auch in der Reihenfolge ihrer Komplexität oder der Reihenfolge, in der sie erstellt wurden, ausgeführt werden?
Persönlich möchte ich, dass die Tests in der Reihenfolge ausgeführt werden, in der ich sie erstellt habe. In TDD wird jeder nachfolgende Test natürlich komplexer und benötigt mehr Zeit zum Ausführen. Ich würde es vorziehen, wenn der einfachere Test zuerst fehlschlägt, da er ein besserer Indikator für die Ursache des Fehlers ist.
Ich kann aber auch den Vorteil erkennen, dass sie in zufälliger Reihenfolge ausgeführt werden, insbesondere wenn Sie testen möchten, dass Ihre Tests keine Abhängigkeiten von anderen Tests aufweisen. Wie wäre es mit einer Option zum Testen von Läufern zu "Tests nach dem Zufallsprinzip ausführen, bis sie gestoppt werden"?
Ich teste mit Selenium auf einer ziemlich komplexen Website und die gesamte Testsuite kann länger als eine halbe Stunde dauern, und ich bin noch nicht in der Nähe, die gesamte Anwendung abzudecken. Wenn ich sicherstellen muss, dass alle vorherigen Formulare für jeden Test korrekt ausgefüllt werden, wird dem Gesamttest viel Zeit und nicht nur wenig Zeit hinzugefügt. Wenn das Ausführen der Tests zu viel Aufwand bedeutet, werden sie nicht so oft ausgeführt, wie sie sollten.
Also ordne ich sie und verlasse mich auf frühere Tests, um Textfelder und dergleichen auszufüllen. Ich verwende Assert.Ignore (), wenn die Voraussetzungen nicht gültig sind, aber ich muss sie in der richtigen Reihenfolge ausführen.
Die vorherige Antwort gefällt mir sehr gut.
Ich habe es ein wenig geändert, um ein Attribut zum Festlegen des Bestellbereichs verwenden 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);
}
}
}
}
}
}
OrderedTest
wird in NUnit 3 nicht mehr unterstützt.
Ich weiß, dass dies ein relativ alter Beitrag ist, aber hier ist eine andere Möglichkeit, Ihren Test in Ordnung 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 so 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");
}
}
}
}
TestCaseSource
geordneten Tests ist ein Geniestreich. Gut gemacht. Ich habe diesen Ansatz zusammen mit dem folgenden gewählt und einige zusätzliche Modifikationen hinzugefügt, um die Verwendung zu vereinfachen. Weitere Informationen finden Sie unter den Links in meiner Antwort. Die zugrunde liegende Idee stammt jedoch aus dieser großartigen Antwort!
TestCaseSource
statisch sein, was die Verwendung von Mustern ausschließt. Schade.
TestCaseSource
muss ein statisches Objekt in NUnit 3 sein, sonst werden die Tests nicht ausgeführt. Und Sie können keine dynamischen Objekte innerhalb eines statischen Objekts erstellen. Deshalb wird es in V. 3 nicht funktionieren.
Ich arbeite mit in C # geschriebenen End-to-End-UI-Testfällen von Selenium WebDriver, die mit dem NUnit-Framework ausgeführt werden. (Nicht Einheitsfälle als solche)
Diese UI-Tests hängen sicherlich von der Ausführungsreihenfolge ab, da andere Tests als Voraussetzung einige Daten hinzufügen müssen. (Es ist nicht möglich, die Schritte in jedem Test durchzuführen.)
Nachdem ich den 10. Testfall hinzugefügt habe, sehe ich, dass NUnit in dieser Reihenfolge ausgeführt werden möchte: Test_1 Test_10 Test_2 Test_3 ..
Ich denke, ich muss die Namen der Testfälle vorerst zu alphabetisch sortieren, aber es wäre gut, wenn diese kleine Funktion zur Steuerung der Ausführungsreihenfolge zu NUnit hinzugefügt würde.
Normalerweise sollte Unit Test unabhängig sein, aber wenn Sie müssen, können Sie Ihre Methoden in alphabetischer Reihenfolge benennen, z.
[Test]
public void Add_Users(){}
[Test]
public void Add_UsersB(){}
[Test]
public void Process_Users(){}
oder du kannst tun ..
private void Add_Users(){}
private void Add_UsersB(){}
[Test]
public void Process_Users()
{
Add_Users();
Add_UsersB();
// more code
}
a_
b_
t1_
, t2_
statt oder auf diese angewiesen leicht nachfolgende Zeichen zu verpassen
Es gibt sehr gute Gründe, einen Testbestellungsmechanismus zu verwenden. Die meisten meiner eigenen Tests verwenden bewährte Methoden wie Einrichten / Herunterfahren. Andere erfordern große Datenmengen, mit denen dann eine Reihe von Funktionen getestet werden können. Bisher habe ich große Tests verwendet, 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 ist ein Beispiel, warum eine Bestellung äußerst wertvoll wäre:
Diese Wartezeit von 10 Minuten verlangsamt die Testsuite. Wenn Sie ähnliche Caching-Verzögerungen über eine Vielzahl von Tests hinweg multiplizieren, nimmt dies viel Zeit in Anspruch. Durch das Bestellen von Tests kann die Dateneinrichtung direkt zu Beginn der Testsuite als "Test" durchgeführt werden, wobei Tests, die darauf beruhen, dass der Cache gegen Ende des Testlaufs kaputt geht.
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 meiner eigenen Updates einem GitHub-Repository hinzugefügt . Ich habe auch einen zugehörigen Blog-Beitrag mit einigen zusätzlichen Informationen erstellt, die Sie für weitere Informationen einsehen können.
Hoffe das ist hilfreich für euch alle. Außerdem verwende ich häufig das Attribut "Kategorie", um meine Integrationstests oder andere End-to-End-Tests von meinen tatsächlichen Komponententests zu unterscheiden. Andere haben darauf hingewiesen, dass Komponententests keine Auftragsabhängigkeit haben sollten, andere Testtypen jedoch häufig. Dies bietet eine gute Möglichkeit, nur die gewünschte Testkategorie auszuführen und auch diese End-to-End-Tests zu bestellen.
Ich bin überrascht, dass sich die NUnit-Community nichts ausgedacht hat, also habe ich selbst so etwas erstellt.
Ich entwickle derzeit eine Open-Source-Bibliothek , mit der Sie Ihre Tests bei NUnit bestellen können. Sie können Testvorrichtungen und "bestellte Testspezifikationen" gleichermaßen bestellen.
Die Bibliothek bietet folgende Funktionen:
Die Bibliothek ist tatsächlich davon inspiriert, wie MSTest die Bestellung mit .orderedtest
Dateien testet . 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
}
Wenn Sie verwenden [TestCase]
, 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 steuern:
[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 das Methodennamensuffix "ExpressionTest"
mit einer Nummer verwendet.
Sie können alle alphabetisch geordneten Namen verwenden, siehe TestCase-Attribut
Sie sollten nicht von der Reihenfolge abhängen, in der das Testframework Tests zur Ausführung auswählt. Tests sollten isoliert und unabhängig sein. Insofern sollten sie nicht von einem anderen Test abhängig sein, der die Bühne für sie bereitet oder nach ihnen aufräumt. Sie sollten auch unabhängig von der Reihenfolge der Testdurchführung (für einen bestimmten Schnappschuss des SUT) das gleiche Ergebnis liefern.
Ich habe ein bisschen gegoogelt. Wie üblich haben einige Leute auf hinterhältige Tricks zurückgegriffen (anstatt das zugrunde liegende Testbarkeits- / Designproblem zu lösen
Siehe auch: Eigenschaften eines guten Tests
Im Falle der Verwendung TestCaseSource
des Schlüssels ist override string ToString
Methode, wie das funktioniert:
Angenommen, Sie haben eine 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
}
};
}
Verwenden wir es jetzt mit einer Testmethode 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:
Wenn wir also override string ToString
unserer Klasse Folgendes hinzufügen :
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:
Hinweis: