Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Někdy můžete chtít mít testy jednotek spuštěné v určitém pořadí. V ideálním případě by na pořadí, ve kterém jednotkové testy běží, nemělo záležet, a je nejlepší praxe se vyhnout řazení jednotkových testů. Bez ohledu na to může být potřeba to udělat. V takovém případě tento článek ukazuje, jak uspořádat testovací běhy.
Poznámka:
Řazení testů a paralelizace testů jsou samostatné aspekty. Určení pořadí provádění určuje posloupnost, ve které se testy spustí, ale pokud je povolená paralelizace, může několik testů běžet souběžně. Chcete-li zaručit, že testy běží po jednom v zadaném pořadí, musíte také zakázat paralelizaci.
Pokud chcete zdrojový kód procházet, přečtěte si ukázkové úložiště order .NET Core unit tests.
Návod
Kromě možností řazení popsaných v tomto článku zvažte vytvoření vlastních seznamů skladeb s Visual Studio jako alternativu.
Pořadí podle abecedy
Poznámka:
MSTest spouští testy ve výchozím nastavení postupně v rámci třídy. Pokud konfigurujete paralelismus pomocí <Parallelize> nastavení v .runsettings souboru, testy napříč třídami se můžou spouštět souběžně a řazení ovlivní pouze sekvenci v rámci každé třídy.
MSTest vyhledá testy ve stejném pořadí, v jakém jsou definovány v testovací třídě.
Při spouštění prostřednictvím Průzkumníka testů (v Visual Studio nebo v Visual Studio Code) jsou testy seřazené v abecedním pořadí podle názvu testu.
Při spuštění mimo Průzkumníka testů se testy spustí v pořadí, v jakém jsou definovány v testovací třídě.
Poznámka:
Test s názvem Test14 se spustí před Test2, i když je číslo 2 menší než 14. Důvodem je to, že řazení názvů testů používá textový název testu.
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);
}
}
Počínaje verzí MSTest 3.6 umožňuje nová možnost runsettings spouštět testy podle názvů testů v Průzkumníkech testů i na příkazovém řádku. Pokud chcete tuto funkci povolit, přidejte OrderTestsByNameInClass nastavení do souboru runsettings:
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<MSTest>
<OrderTestsByNameInClass>true</OrderTestsByNameInClass>
</MSTest>
</RunSettings>
Testovací architektura xUnit umožňuje větší členitost a kontrolu pořadí spuštění testů. Implementujete rozhraní ITestCaseOrderer a ITestCollectionOrderer pro řízení pořadí testovacích případů pro třídu nebo testovací kolekce.
Poznámka:
xUnit spouští testovací třídy paralelně ve výchozím nastavení. Testy v rámci jedné třídy vždy běží postupně, takže ITestCaseOrderer řídí sekvenci v rámci této třídy. Chcete-li zakázat paralelismus napříč všemi třídami, použijte [assembly: CollectionBehavior(DisableTestParallelization = true)] na úrovni sestavení, například v AssemblyInfo.cs libovolném zdrojovém souboru v testovacím projektu.
Seřazení podle testovacího případu podle abecedy
Pokud chcete testovací případy objednat podle názvu metody, implementujete ITestCaseOrderer a zadáte mechanismus řazení.
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);
}
Pak v testovací třídě nastavíte pořadí testovacího případu pomocí TestCaseOrdererAttribute.
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);
}
}
Seřadit podle sbírek abecedně
Pokud chcete uspořádat testovací kolekce podle jejich zobrazovaného názvu, implementujete ITestCollectionOrderer a zadáte mechanismus řazení.
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);
}
Vzhledem k tomu, že testovací kolekce potenciálně běží paralelně, je nutné explicitně zakázat paralelizaci testů kolekcí pomocí CollectionBehaviorAttribute. Pak určete implementaci pro TestCollectionOrdererAttribute.
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;
}
}
Pořadí podle vlastního atributu
Pokud chcete organizovat testy xUnit s vlastními atributy, musíte nejprve mít atribut, na který se můžete spolehnout. Definujte TestPriorityAttribute následující:
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;
}
Dále zvažte následující PriorityOrderer implementaci ITestCaseOrderer rozhraní.
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());
}
Pak v testovací třídě nastavíte pořadí testovacího případu s TestCaseOrdererAttribute na PriorityOrderer.
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);
}
}
Pořadí podle priority
Poznámka:
NUnit spouští testy postupně v rámci jednoho vlákna ve výchozím nastavení. Pokud jste nepoužili [Parallelizable] atributy, [Order] je samotný atribut dostatečný k zajištění sériového spuštění v zadané sekvenci.
NUnit poskytuje nástroj pro explicitní vyvolání testů OrderAttribute. Testy s tímto atributem jsou spuštěny před testy bez. Hodnota objednávky se používá k určení pořadí spuštění testů jednotek.
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);
}
}