默认情况下,nunit测试按字母顺序运行。有人知道任何设置执行顺序的方法吗?是否存在属性?
默认情况下,nunit测试按字母顺序运行。有人知道任何设置执行顺序的方法吗?是否存在属性?
Answers:
您的单元测试应该能够独立运行并且独立运行。如果它们满足此条件,则顺序无关紧要。
但是,在某些情况下,您将需要首先运行某些测试。一个典型的例子是在持续集成情况下,某些测试的运行时间比其他测试更长。我们使用category属性,以便我们可以在使用数据库的测试之前运行使用模拟的测试。
即把它放在您的快速测试的开始
[Category("QuickTests")]
在具有依赖于某些环境条件的测试的情况下,请考虑TestFixtureSetUp和TestFixtureTearDown属性,这些属性允许您标记要在测试之前和之后执行的方法。
我只想指出,尽管大多数响应者都认为这些是单元测试,但问题并没有指明它们是单元测试。
nUnit是一个很棒的工具,可以用于各种测试情况。我可以看到想要控制测试订单的适当原因。
在这种情况下,我不得不求助于将运行顺序合并到测试名称中。能够使用属性指定运行顺序会很棒。
001_first_test
002_second_test
等等?
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() { ... }
}
我正在一个相当复杂的网站上使用Selenium进行测试,并且整个测试套件可以运行超过半小时,而我还不能涵盖整个应用程序。如果必须确保为每个测试正确填写所有先前的表格,那么这将为整个测试增加大量时间,而不仅仅是少量时间。如果运行测试有太多开销,那么人们将不会经常运行它们。
因此,我将它们整理好并依靠以前的测试来完成文本框等。当前提条件无效时,我将使用Assert.Ignore(),但需要按顺序运行它们。
我真的很喜欢上一个答案。
我做了一些更改,以便能够使用属性来设置订单范围:
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);
}
}
}
}
}
}
OrderedTest
在NUnit的3不再支持
我知道这是一个相对较旧的帖子,但是这是保持测试顺序的另一种方法,而不会使测试名称尴尬。通过使用TestCaseSource属性,并使传递的对象具有委托(动作),您不仅可以完全控制顺序,还可以将测试的名称命名为。
之所以可行,是因为根据文档,从测试源返回的集合中的项目将始终按照列出的顺序执行。
这是我明天要进行的演示的演示:
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");
}
}
}
}
TestCaseSource
的方式来运行有序的测试是神来之笔。做得好。我将这种方法与下面的方法一起使用,并添加了一些其他修改以使其更易于使用。请参阅我的答案中的链接以获取更多信息,但是基本的想法来自于这个好答案!
TestCaseSource
必须是静态的,从而无法使用模式。笨蛋
TestCaseSource
必须是静态的方法-NUnit 3中的源(变量或属性)必须是静态对象,否则测试将不会执行。而且您不能在静态对象内创建动态对象。这就是为什么它在第3节中不起作用的原因
我正在使用C#编写的Selenium WebDriver端到端UI测试用例,这些用NUnit框架运行。(不是单位案例)
这些UI测试当然取决于执行顺序,因为其他测试需要添加一些数据作为前提条件。(在每个测试中执行步骤都是不可行的)
现在,在添加第10个测试用例之后,我看到NUnit要按以下顺序运行:Test_1 Test_10 Test_2 Test_3 ..
所以我想我现在也必须按字母顺序排列测试用例的名称,但是将控制执行顺序的这个小功能添加到NUnit会很好。
通常,单元测试应该是独立的,但是如果必须,则可以按字母顺序命名方法,例如:
[Test]
public void Add_Users(){}
[Test]
public void Add_UsersB(){}
[Test]
public void Process_Users(){}
或者你可以做..
private void Add_Users(){}
private void Add_UsersB(){}
[Test]
public void Process_Users()
{
Add_Users();
Add_UsersB();
// more code
}
a_
b_
t1_
,t2_
而不是依靠容易错过的结尾字符开始测试,则容易
有充分的理由使用测试订购机制。我自己的大多数测试都使用良好的惯例,例如设置/拆卸。其他一些则需要大量的数据设置,然后可以将其用于测试一系列功能。到目前为止,我已经使用大型测试来处理这些(Selenium Webdriver)集成测试。但是,我认为上面建议的https://github.com/nunit/docs/wiki/Order-Attribute上的帖子 有很多优点。这是为什么订购非常有价值的示例:
这10分钟的等待时间会使测试套件变慢。当您在多个测试中乘以相似的缓存延迟时,会消耗大量时间。排序测试可以允许在测试套件开始时就将数据设置作为“测试”来完成,而测试依赖于缓存来在测试运行结束时执行。
这个问题现在真的很老了,但是对于那些可能通过搜索找到答案的人来说,我从user3275462和PvtVandals / Rico中获得了很好的答案,并将它们以及一些我自己的更新添加到GitHub存储库中。我还创建了一个关联的博客文章,其中包含一些其他信息,您可以查看更多信息。
希望这对大家有帮助。另外,我经常喜欢使用Category属性将我的集成测试或其他端到端测试与实际的单元测试区分开。其他人指出,单元测试不应具有顺序依赖性,但是其他测试类型通常具有顺序依赖性,因此这提供了一种很好的方式,使其仅运行所需的测试类别并对这些端到端测试进行排序。
我很惊讶NUnit社区没有提出任何建议,所以我自己创建了这样的东西。
我目前正在开发一个开源库,该允许您使用NUnit订购测试。您可以订购测试夹具,也可以订购“订购的测试规格”。
该库提供以下功能:
该库实际上是受到MSTest如何测试.orderedtest
文件排序的启发。请看下面的例子。
[OrderedTestFixture]
public sealed class MyOrderedTestFixture : TestOrderingSpecification {
protected override void DefineTestOrdering() {
TestFixture<Fixture1>();
OrderedTestSpecification<MyOtherOrderedTestFixture>();
TestFixture<Fixture2>();
TestFixture<Fixture3>();
}
protected override bool ContinueOnError => false; // Or true, if you want to continue even if a child test fails
}
如果使用[TestCase]
,则参数TestName
为测试提供名称。
如果未指定,则根据方法名称和提供的参数生成名称。
您可以控制测试执行的顺序,如下所示:
[Test]
[TestCase("value1", TestName = "ExpressionTest_1")]
[TestCase("value2", TestName = "ExpressionTest_2")]
[TestCase("value3", TestName = "ExpressionTest_3")]
public void ExpressionTest(string v)
{
//do your stuff
}
在这里,我使用了"ExpressionTest"
带数字的方法名称后缀。
您可以使用按字母顺序排列的任何名称,请参见TestCase属性
您不应该依赖于测试框架选择执行测试的顺序。测试应该是独立且独立的。因为它们不应该依赖于其他测试来设置它们的工作台或清理它们。无论测试的执行顺序如何(对于SUT的给定快照),它们也应产生相同的结果。
我做了一些谷歌搜索。像往常一样,有些人采取了偷偷摸摸的手段(而不是解决潜在的可测试性/设计问题)
另请参见:良好测试的特征
如果使用TestCaseSource
键是to override string ToString
方法,那么它如何工作:
假设您有TestCase类
public class TestCase
{
public string Name { get; set; }
public int Input { get; set; }
public int Expected { get; set; }
}
以及TestCases的列表:
private static IEnumerable<TestCase> TestSource()
{
return new List<TestCase>
{
new TestCase()
{
Name = "Test 1",
Input = 2,
Expected = 4
},
new TestCase()
{
Name = "Test 2",
Input = 4,
Expected = 16
},
new TestCase()
{
Name = "Test 3",
Input = 10,
Expected = 100
}
};
}
现在,将其与Test方法一起使用,看看会发生什么:
[TestCaseSource(nameof(TestSource))]
public void MethodXTest(TestCase testCase)
{
var x = Power(testCase.Input);
x.ShouldBe(testCase.Expected);
}
这不会按顺序进行测试,并且输出将如下所示:
因此,如果我们override string ToString
像这样添加到类中:
public class TestCase
{
public string Name { get; set; }
public int Input { get; set; }
public int Expected { get; set; }
public override string ToString()
{
return Name;
}
}
结果将改变,我们得到测试的顺序和名称,例如:
注意: