Bagikan melalui


Pengujian unit pesanan

Terkadang, Anda mungkin ingin menjalankan pengujian unit dalam urutan tertentu. Idealnya, urutan pengujian unit yang dijalankan seharusnya tidak menjadi masalah, dan praktik terbaik adalah menghindari pengurutan pengujian unit. Terlepas dari itu, mungkin ada kebutuhan untuk melakukannya. Dalam hal ini, artikel ini menunjukkan cara memesan eksekusi pengujian.

Jika Anda lebih suka menelusuri kode sumber, lihat repositori sampel pengujian unit .NET Core pesanan.

Tip

Selain kemampuan pemesanan yang diuraikan dalam artikel ini, pertimbangkan untuk membuat daftar putar kustom dengan Visual Studio sebagai alternatif.

Memesan menurut abjad

Dengan MSTest, pengujian secara otomatis diurutkan berdasarkan nama pengujiannya.

Catatan

Pengujian bernama Test14 akan berjalan sebelum Test2 meskipun angkanya 2 kurang dari 14. Ini karena pengurutan nama pengujian menggunakan nama teks pengujian.

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);
    }
}

Kerangka kerja pengujian xUnit memungkinkan lebih banyak granularitas dan kontrol urutan uji coba. Anda menerapkan ITestCaseOrderer antarmuka dan ITestCollectionOrderer untuk mengontrol urutan kasus pengujian untuk kelas, atau koleksi pengujian.

Urutan berdasarkan kasus pengujian menurut abjad

Untuk memesan kasus pengujian dengan nama metodenya, Anda menerapkan ITestCaseOrderer dan menyediakan mekanisme pemesanan.

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);
}

Kemudian di kelas pengujian Anda mengatur urutan kasus pengujian dengan 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);
    }
}

Urutkan menurut koleksi menurut abjad

Untuk memesan koleksi pengujian dengan nama tampilannya, Anda menerapkan ITestCollectionOrderer dan menyediakan mekanisme pemesanan.

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);
}

Karena koleksi pengujian berpotensi berjalan secara paralel, Anda harus secara eksplisit menonaktifkan paralelisasi pengujian koleksi dengan CollectionBehaviorAttribute. Kemudian tentukan implementasi ke 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;
    }
}

Urutan berdasarkan atribut kustom

Untuk memesan pengujian xUnit dengan atribut kustom, Anda terlebih dahulu memerlukan atribut untuk diandalkan. TestPriorityAttribute Tentukan sebagai berikut:

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;
}

Selanjutnya, pertimbangkan implementasi ITestCaseOrderer antarmuka berikutPriorityOrderer.

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());
}

Kemudian di kelas pengujian Anda mengatur urutan kasus pengujian dengan TestCaseOrdererAttribute ke 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);
    }
}

Urutan berdasarkan prioritas

Untuk memesan pengujian secara eksplisit, NUnit menyediakan OrderAttribute. Pengujian dengan atribut ini dimulai sebelum pengujian tanpa. Nilai pesanan digunakan untuk menentukan urutan untuk menjalankan pengujian unit.

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);
    }
}

Langkah berikutnya