Author : MD TAREQ HASSAN
Data attribute base class
public abstract class DataAttribute : Attribute
{
public virtual string Skip { get; set; }
public abstract IEnumerable<object[]> GetData(MethodInfo testMethod);
}
To implement a custom method, you just need to derive from this class, and implement GetData()
. You can then use your new attribute to pass data to a theory test method.
CsvFile data attribute
public class CsvTestDataAttribute : DataAttribute
{
private readonly string _csvFileName;
public CsvTestDataAttribute(string csvFileName)
{
_csvFileName = csvFileName;
}
public override IEnumerable<object[]> GetData(MethodInfo testMethod)
{
string[] csvLines = File.ReadAllLines(_csvFileName);
var testCases = new List<object[]>();
foreach (var csvLine in csvLines)
{
IEnumerable<int> values = csvLine.Split(',').Select(int.Parse);
object[] testCase = values.Cast<object>().ToArray();
testCases.Add(testCase);
}
return testCases;
}
}
Using CsvTestDataAttribute
public class MemoryCalculatorTests
{
[Theory]
[CsvTestData("foo.csv")]
public void ShouldSubtractTwoNumbers(int firstNumber, int secondNumber, int expectedResult)
{
var sut = new MemoryCalculator();
sut.Subtract(firstNumber);
sut.Subtract(secondNumber);
Assert.Equal(expectedResult, sut.CurrentValue);
}
}
JsonFile data attribute
[Courtesy: andrewlock.net]
public class JsonFileDataAttribute : DataAttribute
{
private readonly string _filePath;
private readonly string _propertyName;
public JsonFileDataAttribute(string filePath) : this(filePath, null)
{
}
public JsonFileDataAttribute(string filePath, string propertyName)
{
_filePath = filePath;
_propertyName = propertyName;
}
public override IEnumerable<object[]> GetData(MethodInfo testMethod)
{
if (testMethod == null) { throw new ArgumentNullException(nameof(testMethod)); }
// Get the absolute path to the JSON file
var path = Path.IsPathRooted(_filePath) ? _filePath : Path.GetRelativePath(Directory.GetCurrentDirectory(), _filePath);
if (!File.Exists(path))
{
throw new ArgumentException($"Could not find file at path: {path}");
}
// Load the file
var fileData = File.ReadAllText(_filePath);
if (string.IsNullOrEmpty(_propertyName))
{
//whole file is the data
return JsonConvert.DeserializeObject<List<object[]>>(fileData);
}
// Only use the specified property as the data
var allData = JObject.Parse(fileData);
var data = allData[_propertyName];
return data.ToObject<List<object[]>>();
}
}
Using JsonFileDataAttribute
[Theory]
[JsonFileData("data.json", "AddData")]
public void CanAdd(int value1, int value2, int expected)
{
var calculator = new Calculator();
var result = calculator.Add(value1, value2);
Assert.Equal(expected, result);
}
For test data json file in the project
foo.json
file > Right click > Properties- Properties window > Copy To Output Directory : Copy if newer
Excel data attribute
https://github.com/xamarin/xunit/blob/master/samples/ExcelDataExample/ExcelDataAttribute.cs