【问题标题】:How to set the test case sequence in xUnit如何在 xUnit 中设置测试用例序列
【发布时间】:2012-02-09 11:45:43
【问题描述】:

我已经用 C# 编写了 xUnit 测试用例。该测试类包含很多方法。我需要按顺序运行整个测试用例。如何在 xUnit 中设置测试用例序列?

【问题讨论】:

  • 为什么要关心测试的执行顺序?测试以任何方式相互依赖通常是一个坏主意——它们应该相互独立。
  • 虽然单元测试确实如此,但集成测试并非如此。
  • 如果有人想知道如何从 2020 年开始执行此操作:您可以使用 github.com/asherber/Xunit.Priority(在 NuGet 上可用)。
  • @Cesar - 感谢您的提示,我会尝试的。在 NUGET 上,我还找到了 Xunit.Extensions.Ordering,但我还没有尝试过(还)——我认为它按字母顺序排列所有内容。
  • 请注意,使用 XUnit.Priority 您可以在类级别定义 [DefaultPriority(x)] 并在方法 (Fact) 级别定义 [Priority(y)]。并且具有相同优先级的测试按字母顺序运行 - 因此在类级别设置默认优先级并按字母顺序命名测试可能就足够了。

标签: c# xunit.net


【解决方案1】:

在 xUnit 2.* 中,这可以使用TestCaseOrderer 属性来指定排序策略来实现,该属性可用于引用在每个测试上注释的属性以表示订单。

例如:

订购策略

[assembly: CollectionBehavior(DisableTestParallelization = true)] 

public class PriorityOrderer : ITestCaseOrderer
{
    public IEnumerable<TTestCase> OrderTestCases<TTestCase>(IEnumerable<TTestCase> testCases) where TTestCase : ITestCase
    {
        var sortedMethods = new SortedDictionary<int, List<TTestCase>>();

        foreach (TTestCase testCase in testCases)
        {
            int priority = 0;

            foreach (IAttributeInfo attr in testCase.TestMethod.Method.GetCustomAttributes((typeof(TestPriorityAttribute).AssemblyQualifiedName)))
                priority = attr.GetNamedArgument<int>("Priority");

            GetOrCreate(sortedMethods, priority).Add(testCase);
        }

        foreach (var list in sortedMethods.Keys.Select(priority => sortedMethods[priority]))
        {
            list.Sort((x, y) => StringComparer.OrdinalIgnoreCase.Compare(x.TestMethod.Method.Name, y.TestMethod.Method.Name));
            foreach (TTestCase testCase in list)
                yield return testCase;
        }
    }

    static TValue GetOrCreate<TKey, TValue>(IDictionary<TKey, TValue> dictionary, TKey key) where TValue : new()
    {
        TValue result;

        if (dictionary.TryGetValue(key, out result)) return result;

        result = new TValue();
        dictionary[key] = result;

        return result;
    }
}

属性

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class TestPriorityAttribute : Attribute
{
    public TestPriorityAttribute(int priority)
    {
        Priority = priority;
    }

    public int Priority { get; private set; }
}

测试用例

[TestCaseOrderer("FullNameOfOrderStrategyHere", "OrderStrategyAssemblyName")]
public class PriorityOrderExamples
{
    [Fact, TestPriority(5)]
    public void Test3()
    {
        // called third
    }

    [Fact, TestPriority(0)]
    public void Test2()
    {
      // called second
    }

    [Fact, TestPriority(-5)]
    public void Test1()
    {
       // called first
    }

}

xUnit 2.* 订购样品here

【讨论】:

  • 这只有在我添加了一个程序集属性后才有效... [程序集:CollectionBehavior(DisableTestParallelization = true)]
  • 谢谢!这可能是必需的,因为我写了那个答案。
  • 可以在here 找到一个“官方”示例。并且没有必要使用属性来实现这一点,也可以使用方法名称的字母顺序等约定。
  • 奇怪,但这些都不适合我。我创建了 4 个 EF 集成测试,尽管按字母顺序排列并应用了优先级,但它并没有考虑正确的顺序。它总是按 4-1-2-3 的顺序运行它们,我将它们命名为 Test_01、Test_02、Test_03 和 Test_04。顺序很重要,因为我将它用于 CRUD 测试(创建、读取、更新、删除)。
【解决方案2】:

Testpriority:this 页面底部。

[PrioritizedFixture]
public class MyTests
{
    [Fact, TestPriority(1)]
    public void FirstTest()
    {
        // Test code here is always run first
    }
    [Fact, TestPriority(2)]
    public void SeccondTest()
    {
        // Test code here is run second
    }
}

顺便说一句,我现在也有同样的问题。是的,这不是干净的艺术..但是 QA 想要手动测试..所以具有特定顺序的自动化测试对他们来说已经是一个很大的飞跃..(咳嗽)是的,这不是真正的单元测试..

【讨论】:

  • TestPriority 仅适用于每个模块/类。所以不同的类仍然以随机顺序执行。 (C# 编译器以不可预测的顺序将类嵌入到程序集中。)为了使测试序列(测试人员有测试协议)更容易和可重复,我添加了字母排序。所以我创建了一个 xunit 1.9 的修改版本,它按字母顺序执行测试类。看看andreas-reiff.de/2012/06/…
  • @bricelam,该链接似乎已损坏,它进入了一些重定向循环。
【解决方案3】:

如果您确实需要优先考虑您的测试(可能不是您的单元测试),您可以使用Xunit.Priority。 我已将它用于一些集成测试,并且工作得非常好且简单,无需为简单的案例场景编写优先级类的开销

【讨论】:

    【解决方案4】:

    由于某种原因,XUnit.Priority 对我不起作用。在我的测试用例中,它没有按照指定的优先顺序运行测试。

    所以我尝试了XUnitPriorityOrderer,它与使用类似但正在工作(要快速测试它,请将以下代码保存在文本编辑器中作为 OrderedXUnitTests.linq,然后使用LinqPad 6 打开并执行它。或者,您也可以将TestClass复制到Visual Studio并添加XUnit、XUnit.Runner.VisualStudio和XUnitPriorityOrderer):

    <Query Kind="Program">
      <NuGetReference>XUnitPriorityOrderer</NuGetReference>
      <Namespace>Xunit</Namespace>
      <Namespace>XUnitPriorityOrderer</Namespace>
    </Query>
    
    
    #load "xunit"
    
    // using XUnitPriorityOrderer
    // see: https://github.com/frederic-prusse/XUnitPriorityOrderer
    void Main()
    {
        RunTests();  // Call RunTests() or press Alt+Shift+T to initiate testing.
    }
    
    
    #region private::Tests
    
    [TestCaseOrderer(CasePriorityOrderer.TypeName, CasePriorityOrderer.AssembyName)]
    public class TestClass
    {
        static List<string> Order { get; set; }
        
        public TestClass()
        {
            Order = Order ?? new List<string>();
        }
    
        [Fact, Order(2)]
        void Test_Xunit_AnotherTest()
        {
            Order.Add("Test_Xunit_AnotherTest");
            Assert.True(3 + 1 == 4);
        }
    
        [Fact, Order(1)]
        void Test_Xunit()
        {
            Order.Add("Test_XUnit");
            Assert.True(1 + 1 == 2);
        }
    
        [Fact, Order(99)]
        void Print_Order()
        {
            Order.Add("Print_Order");
            var strOrder = string.Join(", ", Order.ToArray());
            strOrder.Dump("Execution Order");
            Assert.True(true);
        }
    }
    #endregion
    

    这将按照给定的顺序(Order(1)、Order(2) 和 Order(99))运行测试,并最终转储执行的测试(测试方法 Print_Order())。

    【讨论】:

      【解决方案5】:

      按照设计,你不能。这是故意随机的,以防止任何人出于愿望或意外获得其中之一。

      随机性仅适用于给定的 Test 类,因此您可以通过包装您想要控制嵌套类内部顺序的项目来实现您的目标 - 但在这种情况下,您仍然会以 random 结束只要你在一个类中有两个以上的测试方法,就可以排序。

      如果您尝试管理固定装置或上下文的构建,内置的IUseFixture&lt;T&gt; 机制可能是合适的。有关示例,请参见 xUnit Cheat Sheet

      但你真的需要告诉我们更多关于你想要做什么的信息,否则我们只能投机取巧。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-10-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多