NUnit测试运行顺序

Ria*_*ney 108 .net tdd attributes nunit

默认情况下,nunit测试按字母顺序运行.有谁知道设置执行顺序的方法?这个属性是否存在?

Les*_*Les 168

我只是想指出,虽然大多数响应者都认为这些是单元测试,但问题没有说明它们是.

nUnit是一个很棒的工具,可用于各种测试情况.我可以看到想要控制测试订单的合适原因.

在那些情况下,我不得不求助于将运行顺序合并到测试名称中.能够使用属性指定运行顺序会很棒.

  • 谢谢你这里唯一明智的答案.这是一个具体的问题,但某些模糊的迂腐答案正在被投票.是的,我们都知道单元测试应该是什么,但这不是问题. (78认同)
  • 指定顺序的另一个好理由是在继续使用其余测试套件之前先捕获某些问题.换句话说,如果我创建用户的测试失败,那么在找到此结果之前我不需要运行其他所有内容.在我的另一个测试中,我可能会嘲笑用户,但对我来说这是第一个失败的测试很重要 - 特别是当测试套件很大时. (2认同)

Răz*_*nda 111

NUnit 3.2.0添加了一个OrderAttribute,参见:

https://github.com/nunit/docs/wiki/Order-Attribute

例:

public class MyFixture
{
    [Test, Order(1)]
    public void TestA() { ... }


    [Test, Order(2)]
    public void TestB() { ... }

    [Test]
    public void TestC() { ... }
}
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案,但要注意,文档状态测试不等待先前的测试完成. (7认同)
  • Thanx,正确的我正在寻找的 - 没有讨论,为什么它的好或坏:) (4认同)
  • 然后他们将其设为整数而不是小数,因此如果必须插入测试,则所有测试都必须重新编号。 (2认同)

Nee*_*ack 49

您的单元测试应该能够独立运行并且独立运行.如果他们满足这个标准,则顺序无关紧要.

但有时你会想要先运行某些测试.一个典型的例子是持续集成情况,其中一些测试比其他测试运行更长.我们使用category属性,以便我们可以在使用数据库的测试之前运行使用模拟的测试.

即把它放在快速测试的开始

[Category("QuickTests")]
Run Code Online (Sandbox Code Playgroud)

如果您有依赖于某些环境条件的测试,请考虑TestFixtureSetUpTestFixtureTearDown属性,这些属性允许您标记在测试之前和之后要执行的方法.

  • 订单相关测试的另一个例子是当你想使用你的nunit框架来运行集成测试时...... (27认同)
  • @Chris,我倾向于不使用这些属性,这是一篇有趣的博客文章 - http://jamesnewkirk.typepad.com/posts/2007/09/why-you-should-.html.关于类别测试的好点但是. (2认同)
  • 如果您不以随机顺序运行测试,您如何验证它们在无序运行时是否确实有效?您所说的类似于“如果您的软件没有错误,则无需测试”。 (2认同)

小智 21

希望测试以特定的顺序运行并不意味着测试依赖于彼此 - 我现在正在开发一个TDD项目,而且我是一个很好的TDDer我嘲笑/存根一切,但它会使如果我可以指定显示测试结果的顺序 - 主题而不是按字母顺序排列,则更具可读性.到目前为止,我唯一能想到的是将a_ b_ c_添加到类,命名空间和方法的类中.(不太好)我认为[TestOrderAttribute]属性会很好 - 不是严格遵循框架,而是一个提示,所以我们可以实现这一点


小智 10

无论测试是否依赖于顺序......我们中的一些人只是想以有序的方式控制一切.

单元测试通常按复杂程度创建.那么,为什么它们也不应该按照复杂性或它们的创建顺序运行?

就个人而言,我喜欢看到测试按照我创建它们的顺序运行.在TDD中,每个连续的测试自然会变得更复杂,并且需要更多的时间来运行.我宁愿首先看到更简单的测试失败,因为它将成为失败原因的更好指标.

但是,我也可以看到以随机顺序运行它们的好处,特别是如果你想测试你的测试对其他测试没有任何依赖性.如何添加一个选项来测试跑步者"随机运行测试直到停止"?


小智 9

我正在一个相当复杂的网站上测试Selenium,整套测试可以运行半个多小时,而且我还没有完成覆盖整个应用程序.如果我必须确保每次测试都正确填写所有以前的表格,这会给整个测试增加大量时间,而不仅仅是少量时间.如果运行测试的开销太大,人们就不会经常运行它们.

所以,我把它们按顺序排列,并依赖于以前的测试,以便有文本框等完成.当前置条件无效时我使用Assert.Ignore(),但我需要让它们按顺序运行.


小智 9

我真的很喜欢以前的答案.

我稍微更改了一下,以便能够使用属性来设置顺序范围:

namespace SmiMobile.Web.Selenium.Tests
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;
    using NUnit.Framework;

    public class OrderedTestAttribute : Attribute
    {
        public int Order { get; set; }


        public OrderedTestAttribute(int order)
        {
            Order = order;
        }
    }

    public class TestStructure
    {
        public Action Test;
    }

    class Int
    {
        public int I;
    }

    [TestFixture]
    public class ControllingTestOrder
    {
        private static readonly Int MyInt = new Int();

        [TestFixtureSetUp]
        public void SetUp()
        {
            MyInt.I = 0;
        }

        [OrderedTest(0)]
        public void Test0()
        {
            Console.WriteLine("This is test zero");
            Assert.That(MyInt.I, Is.EqualTo(0));
        }

        [OrderedTest(2)]
        public void ATest0()
        {
            Console.WriteLine("This is test two");
            MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(2));
        }


        [OrderedTest(1)]
        public void BTest0()
        {
            Console.WriteLine("This is test one");
            MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(1));
        }

        [OrderedTest(3)]
        public void AAA()
        {
            Console.WriteLine("This is test three");
            MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(3));
        }


        [TestCaseSource(sourceName: "TestSource")]
        public void MyTest(TestStructure test)
        {
            test.Test();
        }

        public IEnumerable<TestCaseData> TestSource
        {
            get
            {
                var assembly =Assembly.GetExecutingAssembly();
                Dictionary<int, List<MethodInfo>> methods = assembly
                    .GetTypes()
                    .SelectMany(x => x.GetMethods())
                    .Where(y => y.GetCustomAttributes().OfType<OrderedTestAttribute>().Any())
                    .GroupBy(z => z.GetCustomAttribute<OrderedTestAttribute>().Order)
                    .ToDictionary(gdc => gdc.Key, gdc => gdc.ToList());

                foreach (var order in methods.Keys.OrderBy(x => x))
                {
                    foreach (var methodInfo in methods[order])
                    {
                        MethodInfo info = methodInfo;
                        yield return new TestCaseData(
                            new TestStructure
                                {
                                    Test = () =>
                                        {
                                            object classInstance = Activator.CreateInstance(info.DeclaringType, null);
                                            info.Invoke(classInstance, null);
                                        }
                                }).SetName(methodInfo.Name);
                    }
                }

            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 7

我知道这是一个相对较旧的帖子,但这是另一种方法来保持测试顺序,而不会让测试名称变得尴尬.通过使用TestCaseSource属性并让您传入的对象具有委托(Action),您不仅可以完全控制顺序,还可以将测试命名为它.

这是有效的,因为根据文档,从测试源返回的集合中的项将始终按列出的顺序执行.

这是我明天给出的一个演示的演示:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;

namespace NUnitTest
{
    public class TestStructure
    {
        public Action Test;
    }

    class Int
    {
        public int I;
    }

    [TestFixture]
    public class ControllingTestOrder
    {
        private static readonly Int MyInt= new Int();

        [TestFixtureSetUp]
        public void SetUp()
        {
            MyInt.I = 0;
        }

        [TestCaseSource(sourceName: "TestSource")]
        public void MyTest(TestStructure test)
        {
            test.Test();
        }

        public IEnumerable<TestCaseData> TestSource
        {
            get
            {
                yield return new TestCaseData(
                    new TestStructure
                    {
                        Test = () =>
                        {
                            Console.WriteLine("This is test one");
                            MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(1));
                        }
                    }).SetName(@"Test One");
                yield return new TestCaseData(
                    new TestStructure
                    {
                        Test = () =>
                        {
                            Console.WriteLine("This is test two");
                            MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(2));
                        }
                    }).SetName(@"Test Two");
                yield return new TestCaseData(
                    new TestStructure
                    {
                        Test = () =>
                        {
                            Console.WriteLine("This is test three");
                            MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(3));
                        }
                    }).SetName(@"Test Three");
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 5

我正在使用C#编写的Selenium WebDriver端到端UI测试用例,它们使用NUnit框架运行.(不是单位情况)

这些UI测试当然取决于执行顺序,因为其他测试需要添加一些数据作为前提条件.(在每个测试中执行这些步骤是不可行的)

现在,在添加第10个测试用例之后,我看到NUnit想要按以下顺序运行:Test_1 Test_10 Test_2 Test_3 ..

所以我想我现在必须对测试用例名称进行字母表化,但是将控制执行顺序的这个小功能添加到NUnit会更好.

  • 不同意Arran:UI测试本质上是小步骤的序列.每一步都应该是一个测试(原因 - 如果失败,我需要知道哪一步).序列可以是独立的,但在序列中,顺序很重要并且在失败时停止是必要的. (9认同)

小智 5

使用测试排序机制有充分的理由。我自己的大多数测试都使用良好的实践,例如设置/拆卸。其他则需要大量数据设置,然后可用于测试一系列功能。到目前为止,我已经使用大型测试来处理这些(Selenium Webdriver)集成测试。但是,我认为上面建议的https://github.com/nunit/docs/wiki/Order-Attribute帖子 有很多优点。以下是为什么订购非常有价值的示例:

  • 使用 Selenium Webdriver 运行测试以下载报告
  • 报告的状态(无论是否可下载)缓存10 分钟
  • 这意味着,在每次测试之前,我需要重置报告状态,然后等待最多10 分钟,然后确认状态已更改,然后验证报告下载是否正确。
  • 由于报告的复杂性,无法通过模拟或测试框架内的任何其他机制以实际/及时的方式生成报告。

这 10 分钟的等待时间会减慢测试套件的速度。当您在多个测试中乘以类似的缓存延迟时,会消耗大量时间。排序测试可以允许在测试套件开始时将数据设置作为“测试”完成,而依赖于缓存的测试将在测试运行结束时执行。