C# 与NUnit类似的xUnit.net中的测试参数化
在xUnit.net框架中是否有类似NUnit的以下功能的方法C# 与NUnit类似的xUnit.net中的测试参数化,c#,.net,unit-testing,nunit,xunit.net,C#,.net,Unit Testing,Nunit,Xunit.net,在xUnit.net框架中是否有类似NUnit的以下功能的方法 [Test, TestCaseSource("CurrencySamples")] public void Format_Currency(decimal value, string expected){} static object[][] CurrencySamples = new object[][] { new object[]{ 0m, "0,00"}, new object[]{ 0.0004m, "0
[Test, TestCaseSource("CurrencySamples")]
public void Format_Currency(decimal value, string expected){}
static object[][] CurrencySamples = new object[][]
{
new object[]{ 0m, "0,00"},
new object[]{ 0.0004m, "0,00"},
new object[]{ 5m, "5,00"},
new object[]{ 5.1m, "5,10"},
new object[]{ 5.12m, "5,12"},
new object[]{ 5.1234m, "5,12"},
new object[]{ 5.1250m, "5,13"}, // round
new object[]{ 5.1299m, "5,13"}, // round
}
这将在NUnit GUI中生成8个单独的测试
[TestCase((string)null, Result = "1")]
[TestCase("", Result = "1")]
[TestCase(" ", Result = "1")]
[TestCase("1", Result = "2")]
[TestCase(" 1 ", Result = "2")]
public string IncrementDocNumber(string lastNum) { return "some"; }
这将生成5个单独的测试并自动比较结果(Assert.Equal()
)
这将生成6个组合测试。无价之宝
几年前,我试过xUnit并喜欢它,但它缺少这些功能。没有他们,我无法生活。有什么变化吗?提供了一种通过数据理论运行参数化测试的方法。这个概念相当于NUnit中的概念,但您从盒子中获得的功能并不完整
下面是一个例子:
[Theory]
[InlineData("Foo")]
[InlineData(9)]
[InlineData(true)]
public void Should_be_assigned_different_values(object value)
{
Assert.NotNull(value);
}
在本例中,每次将指定值作为参数传递时,xUnit将为每个InlineDataAttribute
正确地运行Should\u format\u\u\u货币\u值
测试一次
数据理论是一个扩展点,您可以使用它来创建运行参数化测试的新方法。实现这一点的方法是创建新的属性,这些属性检查测试方法的参数和返回值,并根据这些参数和返回值进行操作
你可以找到一个很好的实例,说明xUnit的数据理论如何在’s和’s理论中得到扩展。让我在这里再举一个例子,以防它能为某人节省一些时间
[Theory]
[InlineData("goodnight moon", "moon", true)]
[InlineData("hello world", "hi", false)]
public void Contains(string input, string sub, bool expected)
{
var actual = input.Contains(sub);
Assert.Equal(expected, actual);
}
根据您的第一个请求,您可以按照找到的示例进行操作 您可以构造一个静态类,其中包含测试集合所需的数据
using System.Collections.Generic;
namespace PropertyDataDrivenTests
{
public static class DemoPropertyDataSource
{
private static readonly List<object[]> _data = new List<object[]>
{
new object[] {1, true},
new object[] {2, false},
new object[] {-1, false},
new object[] {0, false}
};
public static IEnumerable<object[]> TestData
{
get { return _data; }
}
}
}
或者如果您使用的是C#6.0
MemberDataAttribute的第一个参数允许您定义用作数据源的成员,因此您在重用方面有相当大的灵活性。我发现一个库,它可以生成与NUnit的
[Values]
属性等效的功能,名为:
它允许您指定参数级别值:
[Theory, CombinatorialData]
public void CheckValidAge([CombinatorialValues(5, 18, 21, 25)] int age,
bool friendlyOfficer)
{
// This will run with all combinations:
// 5 true
// 18 true
// 21 true
// 25 true
// 5 false
// 18 false
// 21 false
// 25 false
}
或者,您可以隐式地让它计算出覆盖所有可能组合的最小调用数:
[Theory, PairwiseData]
public void CheckValidAge(bool p1, bool p2, bool p3)
{
// Pairwise generates these 4 test cases:
// false false false
// false true true
// true false true
// true true false
}
我在这里收集了所有答案,并另外利用XUnit的
TheoryData
泛型类型为我的测试中的“MemberData”属性提供简单、易于阅读和类型安全的数据定义,如下例所示:
/// must be public & static for MemberDataAttr to use
public static TheoryData<int, bool, string> DataForTest1 = new TheoryData<int, bool, string> {
{ 1, true, "First" },
{ 2, false, "Second" },
{ 3, true, "Third" }
};
[Theory(DisplayName = "My First Test"), MemberData(nameof(DataForTest1))]
public void Test1(int valA, bool valB, string valC)
{
Debug.WriteLine($"Running {nameof(Test1)} with values: {valA}, {valB} & {valC} ");
}
///必须是公共的和静态的,MemberDataAttr才能使用
公共静态TheoryData DataForTest1=新TheoryData{
{1,对,“第一”},
{2,false,“Second”},
{3,对,“第三”}
};
[理论(DisplayName=“我的第一次测试”),成员数据(nameof(DataForTest1))]
公共void Test1(int valA、bool valB、string valC)
{
WriteLine($“正在运行{nameof(Test1)},值为:{valA},{valB}&{valC}”);
}
注意:使用VS2017(15.3.3)、C#7和XUnit 2.2.0 for.NET Core根据XUnit,您有三个“参数化”选项:
[Theory]
[InlineData(1, 2)]
[InlineData(-4, -6)]
[InlineData(2, 4)]
public void FooTest(int value1, int value2)
{
Assert.True(value1 + value2 < 7)
}
public class BarTestData : IEnumerable<object[]>
{
public IEnumerator<object[]> GetEnumerator()
{
yield return new object[] { 1, 2 };
yield return new object[] { -4, -6 };
yield return new object[] { 2, 4 };
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
[Theory]
[ClassData(typeof(BarTestData))]
public void BarTest(int value1, int value2)
{
Assert.True(value1 + value2 < 7)
}
[Theory]
[MemberData(nameof(BazTestData))]
public void BazTest(int value1, int value2)
{
Assert.True(value1 + value2 < 7)
}
public static IEnumerable<object[]> BazTestData => new List<object[]>
{
new object[] { 1, 2 },
new object[] { -4, -6 },
new object[] { 2, 4 },
};
[理论]
[在线数据(1,2)]
[在线数据(-4,-6)]
[在线数据(2,4)]
公共空间英尺(整数值1、整数值2)
{
Assert.True(value1+value2<7)
}
类数据示例
[Theory]
[InlineData(1, 2)]
[InlineData(-4, -6)]
[InlineData(2, 4)]
public void FooTest(int value1, int value2)
{
Assert.True(value1 + value2 < 7)
}
public class BarTestData : IEnumerable<object[]>
{
public IEnumerator<object[]> GetEnumerator()
{
yield return new object[] { 1, 2 };
yield return new object[] { -4, -6 };
yield return new object[] { 2, 4 };
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
[Theory]
[ClassData(typeof(BarTestData))]
public void BarTest(int value1, int value2)
{
Assert.True(value1 + value2 < 7)
}
[Theory]
[MemberData(nameof(BazTestData))]
public void BazTest(int value1, int value2)
{
Assert.True(value1 + value2 < 7)
}
public static IEnumerable<object[]> BazTestData => new List<object[]>
{
new object[] { 1, 2 },
new object[] { -4, -6 },
new object[] { 2, 4 },
};
公共类易货数据:IEnumerable
{
公共IEnumerator GetEnumerator()
{
返回新对象[]{1,2};
返回新对象[]{-4,-6};
产生返回新对象[]{2,4};
}
IEnumerator IEnumerable.GetEnumerator()=>GetEnumerator();
}
[理论]
[ClassData(typeof(BarTestData))]
公共无效易货交易(内部价值1,内部价值2)
{
Assert.True(value1+value2<7)
}
成员数据示例
[Theory]
[InlineData(1, 2)]
[InlineData(-4, -6)]
[InlineData(2, 4)]
public void FooTest(int value1, int value2)
{
Assert.True(value1 + value2 < 7)
}
public class BarTestData : IEnumerable<object[]>
{
public IEnumerator<object[]> GetEnumerator()
{
yield return new object[] { 1, 2 };
yield return new object[] { -4, -6 };
yield return new object[] { 2, 4 };
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
[Theory]
[ClassData(typeof(BarTestData))]
public void BarTest(int value1, int value2)
{
Assert.True(value1 + value2 < 7)
}
[Theory]
[MemberData(nameof(BazTestData))]
public void BazTest(int value1, int value2)
{
Assert.True(value1 + value2 < 7)
}
public static IEnumerable<object[]> BazTestData => new List<object[]>
{
new object[] { 1, 2 },
new object[] { -4, -6 },
new object[] { 2, 4 },
};
[理论]
[成员数据(名称(BazTestData))]
公共测试(int值1、int值2)
{
Assert.True(value1+value2<7)
}
公共静态IEnumerable BazTestData=>新列表
{
新对象[]{1,2},
新对象[]{-4,-6},
新对象[]{2,4},
};
显然,这是使用十进制文字作为属性参数。@rubenbarterlink找不到您的链接。改为转到这里:您将需要xUnit.net:Extensions(NuGet包)或[理论]
属性不可用。如果最推荐的.NET单元测试框架有一些文档就好了。谷歌说你的答案是xUnit文档。这很好。这是一个完整的指南,可以将复杂对象作为参数发送到测试方法