Is there a way to run a data driven XUnit
test using a CSV
file as the data source? I've tried Cavity.Data.XUnit
, but it's no longer compatible with the newest version of XUnit
. So far, I've only been able to achieve this using Excel files, but I need to change them to CSV
instead.
An example:
[Theory]
[ExcelData(@"Settings\TestFileParam.xls", "Select url, username, password, from TestData")]
//^Replace with a CSV file instead
public void Tester_Method(string url, string username, string password)
{
//Code reading the data from CSV
Assert.True(something);
}
You'll need to create a custom xUnit.Sdk.DataAttribute. This is an example which will read in data in this form.
MyCsv.csv
sep=,
csvRowOne,csvRowTwo,csvRowThree
15,"Just A Test","Apples are Red"
Then you would call it like this:
[Theory]
[CsvData(@"C:\MyCsv.csv")]
public void TestWithCSVData(int csvRowOne, string csvRowTwo, string csvRowThree)
It just parses strings and ints, but you can extend the ConvertParameter method to do more.
CsvDataAttribute.cs
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class CsvDataAttribute : DataAttribute
{
private readonly string _fileName;
public CsvDataAttribute(string fileName)
{
_fileName = fileName;
}
public override IEnumerable<object[]> GetData(MethodInfo testMethod)
{
var pars = testMethod.GetParameters();
var parameterTypes = pars.Select(par => par.ParameterType).ToArray();
using (var csvFile = new StreamReader(_fileName))
{
csvFile.ReadLine();// Delimiter Row: "sep=,". Comment out if not used
csvFile.ReadLine(); // Headings Row. Comment out if not used
string line;
while ((line = csvFile.ReadLine()) != null)
{
var row = line.Split(',');
yield return ConvertParameters((object[])row, parameterTypes);
}
}
}
private static object[] ConvertParameters(IReadOnlyList<object> values, IReadOnlyList<Type> parameterTypes)
{
var result = new object[parameterTypes.Count];
for (var idx = 0; idx < parameterTypes.Count; idx++)
{
result[idx] = ConvertParameter(values[idx], parameterTypes[idx]);
}
return result;
}
private static object ConvertParameter(object parameter, Type parameterType)
{
return parameterType == typeof(int) ? Convert.ToInt32(parameter) : parameter;
}
}
xUnit does not have this exact capability built in, it does however have extension points for type of use case. Much of xUnit can be replaced and customized, new test case data sources are one of the more common ones.
The Xunit.Sdk.DataAttribute
is the extension point the ExcelDataAttribute
uses.
A typical implementation would look something like this
public class CsvDataAttribute : DataAttribute
{
readonly string fileName;
public CsvDataAttribute(string fileName)
{
this.fileName = fileName;
}
public override IEnumerable<object[]> GetData(MethodInfo testMethod)
{
//Parse CSV and return an object[] for each test case
}
}
The implementation of ExcelDataAttribute
is found here. https://github.com/xunit/samples.xunit/blob/885edfc2e84ec4934cd137a985c3b06dda043ab5/ExcelDataExample/ExcelDataAttribute.cs
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With