在我的情况下,我想从 CSV 文件加载数据,但我无法将文件名传递给“数据源”。
经过一番挣扎,我找到了这个两分钱的解决方案。
一开始我继承了TestCaseSourceAttirbute
/// <summary>
/// FactoryAttribute indicates the source to be used to provide test cases for a test method.
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class TestCaseCsvAttribute : TestCaseSourceAttribute
{
public TestCaseCsvAttribute(Type mapped, Type config) : base(typeof(TestCsvReader<,>).MakeGenericType(mapped, config), "Data")
{ }
}
然后我创建了数据层,在我的例子中是一个 CSV 阅读器。
/// <summary>
/// Test data provider
/// </summary>
/// <typeparam name="T">Type to return in enumerable</typeparam>
/// <typeparam name="C">Configuration type that provide Filenames</typeparam>
public sealed class TestCsvReader<T, C>
{
/// <summary>
/// Initializes a new instance of the <see cref="TestCsvReader{T, C}"/> class.
/// </summary>
public TestCsvReader()
{
this.Config = (C)Activator.CreateInstance<C>();
}
/// <summary>
/// Gets or sets the configuration.
/// </summary>
/// <value>
/// The configuration.
/// </value>
private C Config { get; set; }
/// <summary>
/// Gets the filename.
/// </summary>
/// <value>
/// The filename.
/// </value>
/// <exception cref="System.Exception">
/// </exception>
private string Filename
{
get
{
try
{
string result = Convert.ToString(typeof(C).GetProperty(string.Format("{0}Filename", typeof(T).Name)).GetValue(this.Config));
if (!File.Exists(result))
throw new Exception(string.Format("Unable to find file '{0}' specified in property '{1}Filename' in class '{1}'", result, typeof(C).Name));
return result;
}
catch
{
throw new Exception(string.Format("Unable to find property '{0}Filename' in class '{1}'", typeof(T).Name, typeof(C).Name));
}
}
}
/// <summary>
/// Yields values from source
/// </summary>
/// <returns></returns>
public IEnumerable Data()
{
string file = this.Filename;
T[] result = null;
using (StreamReader reader = File.OpenText(file))
{
//TODO: do it here your magic
}
yield return new TestCaseData(result);
}
}
然后我创建了一个类,其唯一作用域是包含文件路径的属性。该属性有一个命名约定,即 ClassTypeName + "Filename"。
public class Configurations
{
public string ConflictDataFilename
{
get
{
return @"C:\test.csv";
}
}
}
此时只需对测试进行相应的装饰,使用要映射到数据的类的类型和包含文件路径的类。
[Test(Description="Try this one")]
[TestCaseCsv(typeof(ClassMappedToData), typeof(Configurations))]
public void Infinite(ClassMappedToData[] data)
{
}
希望这能有所帮助。