Author : HASSAN MD TAREQ

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