Festlegen einer Reihenfolge von Komponententests
Gelegentlich kann es erforderlich sein, dass Komponententests in einer bestimmten Reihenfolge ausgeführt werden. Im Idealfall sollte die Reihenfolge, in der Komponententests ausgeführt werden, keine Rolle spielen, und es ist ein bewährte Methode, das Festlegen einer Reihenfolge von Komponententests zu vermeiden. Nichtsdestoweniger kann es im Einzelfall erforderlich sein. In diesem Artikel erfahren Sie, wie Sie die Reihenfolge von Komponententests festlegen.
Wenn Sie lieber den Quellcode durchsuchen möchten, finden Sie weitere Informationen im Beispielrepository Festlegen der Reihenfolge von .NET Core-Komponententests.
Tipp
Zusätzlich zu den in diesem Artikel beschriebenen Funktionen zum Festlegen der Reihenfolge sollten Sie das Erstellen benutzerdefinierter Wiedergabelisten mit Visual Studio als Alternative berücksichtigen.
Alphabetisches Sortieren
MSTest ermittelt Tests in derselben Reihenfolge, in der sie in der Testklasse definiert sind.
Beim Ausführen des Test-Explorers (in Visual Studio oder in Visual Studio Code) werden die Tests basierend auf ihrem Testnamen in alphabetischer Reihenfolge sortiert.
Wenn Sie außerhalb des Test-Explorers ausgeführt werden, werden Tests in der Reihenfolge ausgeführt, in der sie in der Testklasse definiert sind.
Hinweis
Ein Test mit dem Namen Test14
wird vor Test2
ausgeführt, auch wenn die Zahl 2
kleiner als 14
ist. Dies liegt daran, dass beim Festlegen der Reihenfolge der Textname des Tests verwendet wird.
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace MSTest.Project;
[TestClass]
public class ByAlphabeticalOrder
{
public static bool Test1Called;
public static bool Test2Called;
public static bool Test3Called;
[TestMethod]
public void Test2()
{
Test2Called = true;
Assert.IsTrue(Test1Called);
Assert.IsFalse(Test3Called);
}
[TestMethod]
public void Test1()
{
Test1Called = true;
Assert.IsFalse(Test2Called);
Assert.IsFalse(Test3Called);
}
[TestMethod]
public void Test3()
{
Test3Called = true;
Assert.IsTrue(Test1Called);
Assert.IsTrue(Test2Called);
}
}
Das xUnit-Testframework ermöglicht eine höhere Genauigkeit und Steuerung der Testreihenfolge. Sie implementieren die Schnittstellen ITestCaseOrderer
und ITestCollectionOrderer
, um die Reihenfolge von Testfällen für eine Klasse oder Testsammlungen zu steuern.
Alphabetisches Sortieren nach Testfall
Um Testfälle nach dem Methodennamen zu sortieren, implementieren Sie den ITestCaseOrderer
und stellen einen Sortiermechanismus bereit.
using Xunit.Abstractions;
using Xunit.Sdk;
namespace XUnit.Project.Orderers;
public class AlphabeticalOrderer : ITestCaseOrderer
{
public IEnumerable<TTestCase> OrderTestCases<TTestCase>(
IEnumerable<TTestCase> testCases) where TTestCase : ITestCase =>
testCases.OrderBy(testCase => testCase.TestMethod.Method.Name);
}
In einer Testklasse legen Sie dann die Testfallreihenfolge mit dem TestCaseOrdererAttribute
fest.
using Xunit;
namespace XUnit.Project;
[TestCaseOrderer(
ordererTypeName: "XUnit.Project.Orderers.AlphabeticalOrderer",
ordererAssemblyName: "XUnit.Project")]
public class ByAlphabeticalOrder
{
public static bool Test1Called;
public static bool Test2Called;
public static bool Test3Called;
[Fact]
public void Test1()
{
Test1Called = true;
Assert.False(Test2Called);
Assert.False(Test3Called);
}
[Fact]
public void Test2()
{
Test2Called = true;
Assert.True(Test1Called);
Assert.False(Test3Called);
}
[Fact]
public void Test3()
{
Test3Called = true;
Assert.True(Test1Called);
Assert.True(Test2Called);
}
}
Alphabetisches Sortieren nach Sammlung
Um Testsammlungen nach dem Anzeigenamen zu sortieren, implementieren Sie den ITestCollectionOrderer
und stellen einen Sortiermechanismus bereit.
using Xunit;
using Xunit.Abstractions;
namespace XUnit.Project.Orderers;
public class DisplayNameOrderer : ITestCollectionOrderer
{
public IEnumerable<ITestCollection> OrderTestCollections(
IEnumerable<ITestCollection> testCollections) =>
testCollections.OrderBy(collection => collection.DisplayName);
}
Da Testsammlungen möglicherweise parallel ausgeführt werden, müssen Sie die Testparallelisierung der Sammlungen mit dem CollectionBehaviorAttribute
explizit deaktivieren. Geben Sie dann die Implementierung des TestCollectionOrdererAttribute
an.
using Xunit;
// Need to turn off test parallelization so we can validate the run order
[assembly: CollectionBehavior(DisableTestParallelization = true)]
[assembly: TestCollectionOrderer(
ordererTypeName: "XUnit.Project.Orderers.DisplayNameOrderer",
ordererAssemblyName: "XUnit.Project")]
namespace XUnit.Project;
[Collection("Xzy Test Collection")]
public class TestsInCollection1
{
public static bool Collection1Run;
[Fact]
public static void Test()
{
Assert.True(TestsInCollection2.Collection2Run); // Abc
Assert.True(TestsInCollection3.Collection3Run); // Mno
Assert.False(TestsInCollection1.Collection1Run); // Xyz
Collection1Run = true;
}
}
[Collection("Abc Test Collection")]
public class TestsInCollection2
{
public static bool Collection2Run;
[Fact]
public static void Test()
{
Assert.False(TestsInCollection2.Collection2Run); // Abc
Assert.False(TestsInCollection3.Collection3Run); // Mno
Assert.False(TestsInCollection1.Collection1Run); // Xyz
Collection2Run = true;
}
}
[Collection("Mno Test Collection")]
public class TestsInCollection3
{
public static bool Collection3Run;
[Fact]
public static void Test()
{
Assert.True(TestsInCollection2.Collection2Run); // Abc
Assert.False(TestsInCollection3.Collection3Run); // Mno
Assert.False(TestsInCollection1.Collection1Run); // Xyz
Collection3Run = true;
}
}
Sortieren nach benutzerdefiniertem Attribut
Um xUnit-Tests mit benutzerdefinierten Attributen zu sortieren, benötigen Sie zuerst ein Attribut, auf das Sie sich verlassen können. Definieren Sie wie folgt ein TestPriorityAttribute
:
namespace XUnit.Project.Attributes;
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class TestPriorityAttribute : Attribute
{
public int Priority { get; private set; }
public TestPriorityAttribute(int priority) => Priority = priority;
}
Erwägen Sie als Nächstes die folgende PriorityOrderer
-Implementierung der ITestCaseOrderer
-Schnittstelle:
using Xunit.Abstractions;
using Xunit.Sdk;
using XUnit.Project.Attributes;
namespace XUnit.Project.Orderers;
public class PriorityOrderer : ITestCaseOrderer
{
public IEnumerable<TTestCase> OrderTestCases<TTestCase>(
IEnumerable<TTestCase> testCases) where TTestCase : ITestCase
{
string assemblyName = typeof(TestPriorityAttribute).AssemblyQualifiedName!;
var sortedMethods = new SortedDictionary<int, List<TTestCase>>();
foreach (TTestCase testCase in testCases)
{
int priority = testCase.TestMethod.Method
.GetCustomAttributes(assemblyName)
.FirstOrDefault()
?.GetNamedArgument<int>(nameof(TestPriorityAttribute.Priority)) ?? 0;
GetOrCreate(sortedMethods, priority).Add(testCase);
}
foreach (TTestCase testCase in
sortedMethods.Keys.SelectMany(
priority => sortedMethods[priority].OrderBy(
testCase => testCase.TestMethod.Method.Name)))
{
yield return testCase;
}
}
private static TValue GetOrCreate<TKey, TValue>(
IDictionary<TKey, TValue> dictionary, TKey key)
where TKey : struct
where TValue : new() =>
dictionary.TryGetValue(key, out TValue? result)
? result
: (dictionary[key] = new TValue());
}
In einer Testklasse legen Sie dann die Testfallreihenfolge mit dem TestCaseOrdererAttribute
auf PriorityOrderer
fest.
using Xunit;
using XUnit.Project.Attributes;
namespace XUnit.Project;
[TestCaseOrderer(
ordererTypeName: "XUnit.Project.Orderers.PriorityOrderer",
ordererAssemblyName: "XUnit.Project")]
public class ByPriorityOrder
{
public static bool Test1Called;
public static bool Test2ACalled;
public static bool Test2BCalled;
public static bool Test3Called;
[Fact, TestPriority(5)]
public void Test3()
{
Test3Called = true;
Assert.True(Test1Called);
Assert.True(Test2ACalled);
Assert.True(Test2BCalled);
}
[Fact, TestPriority(0)]
public void Test2B()
{
Test2BCalled = true;
Assert.True(Test1Called);
Assert.True(Test2ACalled);
Assert.False(Test3Called);
}
[Fact]
public void Test2A()
{
Test2ACalled = true;
Assert.True(Test1Called);
Assert.False(Test2BCalled);
Assert.False(Test3Called);
}
[Fact, TestPriority(-5)]
public void Test1()
{
Test1Called = true;
Assert.False(Test2ACalled);
Assert.False(Test2BCalled);
Assert.False(Test3Called);
}
}
Sortieren nach Priorität
Zum expliziten Sortieren von Tests stellt NUnit ein OrderAttribute
bereit. Tests mit diesem Attribut werden vor Tests ohne gestartet. Der Wert für die Reihenfolge wird verwendet, um die Reihenfolge zum Ausführen der Komponententests zu bestimmen.
using NUnit.Framework;
namespace NUnit.Project;
public class ByOrder
{
public static bool Test1Called;
public static bool Test2ACalled;
public static bool Test2BCalled;
public static bool Test3Called;
[Test, Order(5)]
public void Test1()
{
Test1Called = true;
Assert.That(Test2ACalled, Is.False);
Assert.That(Test2BCalled, Is.True);
Assert.That(Test3Called, Is.True);
}
[Test, Order(0)]
public void Test2B()
{
Test2BCalled = true;
Assert.That(Test1Called, Is.False);
Assert.That(Test2ACalled, Is.False);
Assert.That(Test3Called, Is.True);
}
[Test]
public void Test2A()
{
Test2ACalled = true;
Assert.That(Test1Called, Is.True);
Assert.That(Test2BCalled, Is.True);
Assert.That(Test3Called, Is.True);
}
[Test, Order(-5)]
public void Test3()
{
Test3Called = true;
Assert.That(Test1Called, Is.False);
Assert.That(Test2ACalled, Is.False);
Assert.That(Test2BCalled, Is.False);
}
}