xUnit.net extensions support data-driven tests called Theories. Such tests are similar to regular xUnit.net tests but instead of being decorated with [Fact]
they are decorated with [Theory]
.
Below is a data-driven test with the data coming a Microsoft Excel (.xls) spreadsheet.
[Theory]
[ExcelData("UnitTestData.xls", "SELECT x, y FROM Data")]
public void Foo(object x, object y)
{
// 'x' and 'y' are values from the .xls spreadsheet.
}
Also, a data-driven test with the data coming from a type implementing the IEnumerable<object[]>.
[Theory]
[ClassData(typeof(CollectionOfSpecifiedString))]
public void Bar(object x, object y)
{
// 'x' and 'y' are values from the IEnumerable<object[]> type.
}
internal class CollectionOfSpecifiedString : IEnumerable<object[]>
{
public IEnumerator<object[]> GetEnumerator()
{
yield return new object[]
{
"foo", "zoo"
};
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
In the above samples, [ExcelData]
and [ClassData]
are attributes representing a data source for a data-driven test.
Below is a data-driven test with the data coming from a type implementing the IEnumerable<object[]> combined with the data coming from an .xls spreadsheet.
[Theory]
[ClassExcelData(
typeof(CollectionOfSpecifiedString),
"UnitTestData.xls", "SELECT x, y FROM Data")]
public void Zoo(object x, object y)
{
// 'x' is coming from the IEnumerable<object[]> type.
// 'y' is coming from the .xls spreadsheet.
}
internal class CollectionOfSpecifiedString : IEnumerable<object[]>
{
public IEnumerator<object[]> GetEnumerator()
{
yield return new object[]
{
"foo"
};
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
The [ClassExcelData]
from the previous example is a composite of two xUnit.net’s data attributes [ClassData]
and [ExcelData]
.
All we have to do is create a type deriving from CompositeDataAttribute
, passing in its base constructor an array of the data attributes we would like to compose.
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
internal class ClassExcelDataAttribute : CompositeDataAttribute
{
internal ClassExcelDataAttribute(Type type, string filename, string selectStatement)
: base(new DataAttribute[] {
new ClassDataAttribute(type),
new ExcelDataAttribute(filename, selectStatement) })
{
}
}
The description for the CompositeDataAttribute
algorithm can be found here.
CompositeDataAttribute is currently bundled with AutoFixture extension for xUnit.net. You can use it by installing the AutoFixture.Xunit NuGet package.