C#NUnit TestCaseSource传递参数
我有以下方法生成一组测试用例!
public IEnumerable PrepareTestCases(param1) { foreach (string entry in entries) { yield return callMyMethod(param1); } }
如何将作为参数类型的param作为参数传递给PrepareTestCases()
方法?
有没有办法做到以下几点:
[Test, Category("Integration"), TestCaseSource("PrepareTestCases", param1)] public void TestRun(ResultsOfCallMyMethod testData) { // do something! }
如果查看TestCaseSourceAttribute文档,您将看到没有任何方法可以将参数传递给返回测试用例的方法。
生成测试用例的方法应该是无参数的 。
因此,假设您要避免代码重复,并且需要重用相同的方法来生成一些测试用例列表,我建议您执行以下操作:
-
编写实际生成测试用例集的参数化方法:
(PrepareTestCases()
已经这样做了)public IEnumerable
PrepareTestCases(string param) { foreach (string entry in entries) { yield return CallMyMethod(param); } } -
编写无参数包装器,调用测试用例生成器并在那里传递所需的参数:
public IEnumerable
PrepareTestCases_Param1() { return PrepareTestCases("param1"); } public IEnumerable PrepareTestCases_Param2() { return PrepareTestCases("param2"); } -
编写测试方法并将paremeterless包装器作为测试用例源传递:
[TestCaseSource("PrepareTestCases_Param1")] public void TestRun1(ResultsOfCallMyMethod data) { } [TestCaseSource("PrepareTestCases_Param2")] public void TestRun2(ResultsOfCallMyMethod data) { }
我已经在即将发布的最新版nunit中对此进行了更改(3.2)。
https://github.com/nunit/nunit/blob/4f54fd7e86f659682e7a538dfe5abee0c33aa8b4/CHANGES.txt
- TestCaseSourceAttribute现在可选地获取可以传递给source方法的参数数组
现在可以做这样的事情
[Test, Category("Integration"), TestCaseSource(typeof(MyDataSources),"PrepareTestCases", new object[] {param1})] public void TestRun(ResultsOfCallMyMethod testData) { // do something! } private class MyDataSources { public IEnumerable PrepareTestCases(param1) { foreach (string entry in entries) { yield return callMyMethod(param1); } } }
在我的情况下,我想从CSV文件加载数据,但我无法将文件名传递给“数据源”。 经过一番挣扎后,我来到这个两分钱的解决方案。
起初我inheritance了TestCaseSourceAttirbute
/// /// FactoryAttribute indicates the source to be used to provide test cases for a test method. /// [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阅读器。
/// /// Test data provider /// /// Type to return in enumerable /// Configuration type that provide Filenames public sealed class TestCsvReader { /// /// Initializes a new instance of the class. /// public TestCsvReader() { this.Config = (C)Activator.CreateInstance(); } /// /// Gets or sets the configuration. /// /// /// The configuration. /// private C Config { get; set; } /// /// Gets the filename. /// /// /// The filename. /// /// /// 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)); } } } /// /// Yields values from source /// /// 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) { }
希望这可以帮助一点。