Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Időnként előfordulhat, hogy az egységtesztek egy adott sorrendben futnak. Ideális esetben az egységtesztek futtatásának sorrendje nem számít, és ajánlott elkerülni az egységtesztek sorrendjét. Ettől függetlenül szükség lehet erre. Ebben az esetben ez a cikk bemutatja, hogyan rendelheti meg a tesztfuttatásokat.
Megjegyzés
A tesztelés sorrendje és a párhuzamos tesztelés külön szempontok. A végrehajtási sorrend megadása határozza meg a tesztek indításának sorrendjét, de ha a párhuzamosítás engedélyezve van, több teszt is futhat egyidejűleg. Annak érdekében, hogy a tesztek egyenként fussanak a megadott sorrendben, le kell tiltania a párhuzamosítást is.
Ha inkább a forráskódban szeretne böngészni, tekintse meg a order .NET Core unit tests mintaadattárat.
Tipp.
A cikkben ismertetett rendezési képességek mellett érdemes lehet egyéni lejátszási listákat létrehozni Visual Studio alternatívaként.
Rendezés betűrendben
Megjegyzés
Az MSTest alapértelmezés szerint szekvenciálisan futtat teszteket egy osztályon belül. Ha egy <Parallelize> fájlban a beállítással konfigurálja a .runsettings párhuzamosságot, az osztályok közötti tesztek párhuzamosan futhatnak, és a sorrend csak az egyes osztályokon belüli sorrendre van hatással.
Az MSTest a tesztosztályban definiált sorrendben észleli a teszteket.
Ha a Test Explorerben (Visual Studio vagy Visual Studio Code) fut, a tesztek betűrendbe vannak rendezve a teszt neve alapján.
Ha a Tesztkezelőn kívül fut, a tesztek a tesztosztályban meghatározott sorrendben lesznek végrehajtva.
Megjegyzés
A Test14 nevű teszt Test2 előtt is le fog futni, még akkor is, ha a 2 szám kisebb 14-nál. Ennek az az oka, hogy a tesztnévsorrendezés a teszt szövegnevét használja.
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);
}
}
Az MSTest 3.6-tól kezdve az új runsettings beállítással tesztnevekkel futtathatja a teszteket mind a Test Explorersben, mind a parancssorban. A funkció engedélyezéséhez adja hozzá a beállítást a OrderTestsByNameInClass runsettings-fájlhoz:
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<MSTest>
<OrderTestsByNameInClass>true</OrderTestsByNameInClass>
</MSTest>
</RunSettings>
Az xUnit tesztelési keretrendszer lehetővé teszi a tesztfuttatási sorrend részletesebbségét és szabályozását. Az osztály vagy tesztgyűjtemény teszteseteinek sorrendjének szabályozásához a ITestCaseOrderer és ITestCollectionOrderer felületeket implementálhatja.
Megjegyzés
Az xUnit alapértelmezés szerint párhuzamosan futtat tesztosztályokat. Az egy osztályon belüli tesztek mindig egymás után futnak, ezért ITestCaseOrderer az osztályon belül vezérli a sorrendet. A párhuzamosság minden osztályban való letiltásához alkalmazza [assembly: CollectionBehavior(DisableTestParallelization = true)] az assembly szinten, például a AssemblyInfo.cs vagy a tesztprojekt bármely forrásfájljában.
A teszteseteket betűrendben rendezze
Ha a vizsgálati eseteket a metódus neve alapján szeretné sorrendbe állítani, akkor implementálja a ITestCaseOrderer-t, és biztosítson egy rendezési mechanizmust.
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);
}
Ezután egy tesztosztályban beállítod a teszteset sorrendjét a 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);
}
}
Rendezés gyűjtemény szerint betűrendben
Ha a tesztgyűjteményeket megjelenítendő név alapján szeretné megrendelni, implementálhatja a ITestCollectionOrderer rendezési mechanizmust.
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);
}
Mivel a tesztgyűjtemények esetleg párhuzamosan futnak, explicit módon le kell tiltania a gyűjtemények tesztek párhuzamosítását a CollectionBehaviorAttribute. Ezután adja meg az implementációt a 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;
}
}
Rendelés egyéni attribútum szerint
Az xUnit-tesztek egyéni attribútumokkal való rendeléséhez először egy attribútumra van szüksége, amelyre támaszkodnia kell. Definiálja a TestPriorityAttribute következőt:
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;
}
Ezt követően fontolja meg a(z) PriorityOrderer felület következő ITestCaseOrderer implementációját.
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());
}
Ezután egy tesztosztályban beállítja a tesztesetek sorrendjét: a TestCaseOrdererAttribute-ról a PriorityOrderer-ra.
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);
}
}
Sorrend prioritás szerint
Megjegyzés
Az NUnit alapértelmezés szerint szekvenciálisan futtat teszteket egyetlen szálon belül. Ha nem alkalmazott [Parallelizable] attribútumokat, az [Order] attribútum önmagában elegendő a megadott sorrendben történő sorozatvégrehajtás garantálásához.
A tesztek explicit módon történő rendeléséhez az NUnit biztosít egy OrderAttribute. Az ezzel az attribútummal végzett tesztek az attribútum nélküli tesztek előtt kezdődnek. A rendelés értéke határozza meg az egységtesztek futtatásának sorrendjét.
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);
}
}