<PackageReference Include="NUnit" Version="4.3.1" />

TestCaseSourceAttribute

Indicates the source to be used to provide test fixture instances for a test class. The name parameter is a String representing the name of the source used to provide test cases. It has the following characteristics:It must be a static field, property, or method in the same class as the test case.It must return an IEnumerable or a type that implements IEnumerable, such as an array, a List, or your own iterator.Each item returned by the enumerator must be compatible with the signature of the method on which the attribute appears.
using NUnit.Framework.Interfaces; using NUnit.Framework.Internal; using NUnit.Framework.Internal.Builders; using NUnit.Framework.Internal.Extensions; using System; using System.Collections; using System.Collections.Generic; using System.Reflection; using System.Runtime.CompilerServices; namespace NUnit.Framework { [System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = false)] public class TestCaseSourceAttribute : NUnitAttribute, ITestBuilder, IImplyFixture { private readonly NUnitTestCaseBuilder _builder = new NUnitTestCaseBuilder(); private const string SourceMustBeStatic = "The sourceName specified on a TestCaseSourceAttribute must refer to a static field, property or method."; private const string ParamGivenToField = "You have specified a data source field but also given a set of parameters. Fields cannot take parameters, please revise the 3rd parameter passed to the TestCaseSourceAttribute and either remove it or specify a method."; private const string ParamGivenToProperty = "You have specified a data source property but also given a set of parameters. Properties cannot take parameters, please revise the 3rd parameter passed to the TestCaseSource attribute and either remove it or specify a method."; private const string NumberOfArgsDoesNotMatch = "You have given the wrong number of arguments to the method in the TestCaseSourceAttribute, please check the number of parameters passed in the object is correct in the 3rd parameter for the TestCaseSourceAttribute and this matches the number of parameters in the target method and try again."; [System.Runtime.CompilerServices.Nullable(2)] [field: System.Runtime.CompilerServices.Nullable(2)] public object[] MethodParams { [System.Runtime.CompilerServices.NullableContext(2)] get; } [System.Runtime.CompilerServices.Nullable(2)] [field: System.Runtime.CompilerServices.Nullable(2)] public string SourceName { [System.Runtime.CompilerServices.NullableContext(2)] get; } [System.Runtime.CompilerServices.Nullable(2)] [field: System.Runtime.CompilerServices.Nullable(2)] public Type SourceType { [System.Runtime.CompilerServices.NullableContext(2)] get; } [System.Runtime.CompilerServices.Nullable(2)] [field: System.Runtime.CompilerServices.Nullable(2)] public string Category { [System.Runtime.CompilerServices.NullableContext(2)] get; [System.Runtime.CompilerServices.NullableContext(2)] set; } public TestCaseSourceAttribute(string sourceName) { SourceName = sourceName; } public TestCaseSourceAttribute(Type sourceType, string sourceName, [System.Runtime.CompilerServices.Nullable(2)] object[] methodParams) { MethodParams = methodParams; SourceType = sourceType; SourceName = sourceName; } public TestCaseSourceAttribute(Type sourceType, string sourceName) { SourceType = sourceType; SourceName = sourceName; } public TestCaseSourceAttribute(string sourceName, [System.Runtime.CompilerServices.Nullable(2)] object[] methodParams) { MethodParams = methodParams; SourceName = sourceName; } public TestCaseSourceAttribute(Type sourceType) { SourceType = sourceType; } public IEnumerable<TestMethod> BuildFrom(IMethodInfo method, [System.Runtime.CompilerServices.Nullable(2)] Test suite) { int count = 0; foreach (TestCaseParameters item in GetTestCasesFor(method)) { count++; yield return _builder.BuildTestMethod(method, suite, item); } if (count == 0 && method.GetParameters().Length == 0) { TestCaseParameters testCaseParameters = new TestCaseParameters(); testCaseParameters.RunState = RunState.NotRunnable; testCaseParameters.Properties.Set("_SKIPREASON", "TestCaseSourceAttribute may not be used on a method without parameters"); yield return _builder.BuildTestMethod(method, suite, testCaseParameters); } } private IEnumerable<ITestCaseData> GetTestCasesFor(IMethodInfo method) { List<ITestCaseData> list = new List<ITestCaseData>(); try { IEnumerable enumerable = ContextUtils.DoIsolated(() => GetTestCaseSource(method)); if (enumerable != null) { foreach (object item in enumerable) { object obj; if (item != null) obj = (item as ITestCaseData); else { ITestCaseData testCaseData = new TestCaseParameters(new object[1]); obj = testCaseData; } ITestCaseData testCaseData2 = (ITestCaseData)obj; if (testCaseData2 == null) { object[] array = null; Array array2 = item as Array; if (array2 != null) { IParameterInfo[] parameters = method.GetParameters(); int num = parameters.Length; if (num > 0 && num == array2.Length && parameters[0].ParameterType != array2.GetType()) { array = new object[array2.Length]; for (int i = 0; i < array2.Length; i++) { array[i] = array2.GetValue(i); } } } if (array == null) array = new object[1] { item }; testCaseData2 = new TestCaseParameters(array); } if (Category != null) { foreach (string item2 in Category.Tokenize(',', false)) { testCaseData2.Properties.Add("Category", item2); } } list.Add(testCaseData2); } return list; } list.Clear(); list.Add(new TestCaseParameters(new Exception("The test case source could not be found."))); return list; } catch (Exception exception) { list.Clear(); list.Add(new TestCaseParameters(exception)); return list; } } [return: System.Runtime.CompilerServices.Nullable(2)] private IEnumerable GetTestCaseSource(IMethodInfo method) { Type type = SourceType ?? method.TypeInfo.Type; if (SourceName == null) return Reflect.Construct(type, null) as IEnumerable; MemberInfo[] memberIncludingFromBase = type.GetMemberIncludingFromBase(SourceName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (memberIncludingFromBase.Length == 1) { MemberInfo memberInfo = memberIncludingFromBase[0]; FieldInfo fieldInfo = memberInfo as FieldInfo; if ((object)fieldInfo != null) { if (!fieldInfo.IsStatic) return ReturnErrorAsParameter("The sourceName specified on a TestCaseSourceAttribute must refer to a static field, property or method."); if (MethodParams != null) return ReturnErrorAsParameter("You have specified a data source field but also given a set of parameters. Fields cannot take parameters, please revise the 3rd parameter passed to the TestCaseSourceAttribute and either remove it or specify a method."); return (IEnumerable)fieldInfo.GetValue(null); } PropertyInfo propertyInfo = memberInfo as PropertyInfo; if ((object)propertyInfo != null) { if ((!(propertyInfo.GetGetMethod(true)?.IsStatic)) ?? true) return ReturnErrorAsParameter("The sourceName specified on a TestCaseSourceAttribute must refer to a static field, property or method."); if (MethodParams != null) return ReturnErrorAsParameter("You have specified a data source property but also given a set of parameters. Properties cannot take parameters, please revise the 3rd parameter passed to the TestCaseSource attribute and either remove it or specify a method."); return (IEnumerable)propertyInfo.GetValue(null, null); } MethodInfo methodInfo = memberInfo as MethodInfo; if ((object)methodInfo != null) { if (!methodInfo.IsStatic) return ReturnErrorAsParameter("The sourceName specified on a TestCaseSourceAttribute must refer to a static field, property or method."); if (MethodParams != null && methodInfo.GetParameters().Length != MethodParams.Length) return ReturnErrorAsParameter("You have given the wrong number of arguments to the method in the TestCaseSourceAttribute, please check the number of parameters passed in the object is correct in the 3rd parameter for the TestCaseSourceAttribute and this matches the number of parameters in the target method and try again."); return AsyncEnumerableAdapter.CoalesceToEnumerable(methodInfo.InvokeMaybeAwait<object>(MethodParams)); } } return null; } private static IEnumerable ReturnErrorAsParameter(string errorMessage) { TestCaseParameters testCaseParameters = new TestCaseParameters(); testCaseParameters.RunState = RunState.NotRunnable; testCaseParameters.Properties.Set("_SKIPREASON", errorMessage); return new TestCaseParameters[1] { testCaseParameters }; } } }