// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. using AwesomeAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting.Resources; using TestFramework.ForTestingMSTest; namespace Microsoft.VisualStudio.TestPlatform.TestFramework.UnitTests.Attributes; public class DynamicDataAttributeTests : TestContainer { private readonly DummyTestClass _dummyTestClass; private readonly MethodInfo _testMethodInfo; private DynamicDataAttribute _dynamicDataAttribute; public DynamicDataAttributeTests() { _dummyTestClass = new DummyTestClass(); _testMethodInfo = _dummyTestClass.GetType().GetTypeInfo().GetDeclaredMethod("TestMethod1")!; _dynamicDataAttribute = new DynamicDataAttribute("ReusableTestDataProperty"); } public void ReflectionArgumentsArePassedInSourceOrderWithoutFlatteningReturnedRows() { var attribute = new DynamicDataAttribute(nameof(ReflectionPartitionSources.Arguments), typeof(ReflectionPartitionSources), 7, "label"); object[][] actual = attribute.GetData(_testMethodInfo).ToArray(); actual.Should().HaveCount(2); actual[0].Should().Equal(7, "label"); actual[1].Should().Equal("label", 8); } public void ReflectionScalarEnumerablesWrapEachElementAndPreserveNullAndEmptyPartitions() { foreach (string member in new[] { nameof(ReflectionPartitionSources.Scalars), nameof(ReflectionPartitionSources.ScalarMethod) }) { object[][] actual = new DynamicDataAttribute(member, typeof(ReflectionPartitionSources)).GetData(_testMethodInfo).ToArray(); actual.Should().HaveCount(3); actual[0].Should().Equal(17); actual[1].Should().HaveCount(1); actual[1][0].Should().BeNull(); actual[2].Should().Equal("text"); } new DynamicDataAttribute(nameof(ReflectionPartitionSources.EmptyScalars), typeof(ReflectionPartitionSources)).GetData(_testMethodInfo).Should().BeEmpty(); } public void ReflectionExplicitMissingMembersAndInvalidKindReportExactSource() { foreach (DynamicDataSourceType kind in new[] { DynamicDataSourceType.Property, DynamicDataSourceType.Method, DynamicDataSourceType.Field }) { var attribute = new DynamicDataAttribute("absent", typeof(ReflectionPartitionSources), kind); Action action = () => attribute.GetData(_testMethodInfo); action.Should().ThrowExactly().Which.ParamName.Should().Be(kind + " absent"); } var invalid = new DynamicDataAttribute("invalid-kind", typeof(ReflectionPartitionSources), (DynamicDataSourceType)999); Action unsupported = () => invalid.GetData(_testMethodInfo); unsupported.Should().ThrowExactly().Which.ParamName.Should().Be( string.Format(CultureInfo.InvariantCulture, FrameworkMessages.DynamicDataValueNull, "invalid-kind", typeof(ReflectionPartitionSources).FullName)); } public void ReflectionMethodsRejectInstanceOpenGenericAndParamsLayoutsBeforeInvocation() { foreach (string member in new[] { nameof(ReflectionPartitionSources.InstanceMethod), nameof(ReflectionPartitionSources.GenericMethod), nameof(ReflectionPartitionSources.ParamsMethod), #if NET9_0_OR_GREATER nameof(ReflectionPartitionSources.ParamsCollection), #endif }) { var attribute = new DynamicDataAttribute(member, typeof(ReflectionPartitionSources), DynamicDataSourceType.Method); Action action = () => attribute.GetData(_testMethodInfo); action.Should().ThrowExactly().Which.Message .Should().Contain(nameof(ReflectionPartitionSources) + "." + member); } } public void ReflectionPropertiesRejectInstanceOrSetterOnlyLayoutsAndPreserveInvokedExceptions() { foreach (string member in new[] { nameof(ReflectionPartitionSources.InstanceProperty), nameof(ReflectionPartitionSources.SetterOnly) }) { var attribute = new DynamicDataAttribute(member, typeof(ReflectionPartitionSources), DynamicDataSourceType.Property); Action action = () => attribute.GetData(_testMethodInfo); action.Should().ThrowExactly().Which.Message.Should().Contain(member); } foreach (string member in new[] { nameof(ReflectionPartitionSources.ThrowingProperty), nameof(ReflectionPartitionSources.ThrowingMethod) }) { var attribute = new DynamicDataAttribute(member, typeof(ReflectionPartitionSources)); Action action = () => attribute.GetData(_testMethodInfo); action.Should().ThrowExactly().Which.InnerException! .Should().BeOfType().Which.Message.Should().Be("source sentinel"); } } public void ReflectionPlainNonEnumerableSourceCannotBeInventedAsOneScalarRow() { var attribute = new DynamicDataAttribute(nameof(ReflectionPartitionSources.NonEnumerable), typeof(ReflectionPartitionSources)); Action action = () => attribute.GetData(_testMethodInfo); ArgumentNullException error = action.Should().ThrowExactly().Which; error.ParamName.Should().Be(string.Format( CultureInfo.InvariantCulture, FrameworkMessages.DynamicDataIEnumerableNull, nameof(ReflectionPartitionSources.NonEnumerable), typeof(ReflectionPartitionSources).FullName)); } private sealed class ReflectionPartitionSources { public static IEnumerable Arguments(int number, string label) => [[number, label], [label, number + 1]]; public static IEnumerable Scalars => new object?[] { 17, null, "text" }; public static IEnumerable ScalarMethod() => new object?[] { 17, null, "text" }; public static IEnumerable EmptyScalars => Array.Empty(); public static object NonEnumerable => new(); public IEnumerable InstanceMethod() => throw new InvalidOperationException("Must be rejected before invocation."); public static IEnumerable GenericMethod() => throw new InvalidOperationException("Must be rejected before invocation."); public static IEnumerable ParamsMethod(params int[] values) => throw new InvalidOperationException("Must be rejected before invocation."); #if NET9_0_OR_GREATER public static IEnumerable ParamsCollection(params IEnumerable values) => throw new InvalidOperationException("Must be rejected before invocation."); #endif public IEnumerable InstanceProperty => throw new InvalidOperationException("Must be rejected before invocation."); public static IEnumerable SetterOnly { set { _ = value; throw new InvalidOperationException("Must be rejected before invocation."); } } public static IEnumerable ThrowingProperty => throw new InvalidOperationException("source sentinel"); public static IEnumerable ThrowingMethod() => throw new InvalidOperationException("source sentinel"); } public void GetDataShouldThrowExceptionIfInvalidPropertyNameIsSpecifiedOrPropertyDoesNotExist() { _dynamicDataAttribute = new DynamicDataAttribute("ABC"); Action action = () => _dynamicDataAttribute.GetData(_testMethodInfo); action.Should().Throw() .WithMessage(string.Format(CultureInfo.InvariantCulture, FrameworkMessages.DynamicDataSourceShouldExistAndBeValid, "ABC", _testMethodInfo.DeclaringType!.FullName)); } public void GetDataShouldReadDataFromProperty() { MethodInfo methodInfo = _dummyTestClass.GetType().GetTypeInfo().GetDeclaredMethod("TestMethod1")!; _dynamicDataAttribute = new DynamicDataAttribute("ReusableTestDataProperty"); IEnumerable data = _dynamicDataAttribute.GetData(methodInfo); data.Should().NotBeNull(); data.ToList().Should().HaveCount(2); } public void GetDataShouldReadDataFromPropertyInDifferentClass() { MethodInfo methodInfo = _dummyTestClass.GetType().GetTypeInfo().GetDeclaredMethod("TestMethod1")!; _dynamicDataAttribute = new DynamicDataAttribute("ReusableTestDataProperty2", typeof(DummyTestClass2)); IEnumerable data = _dynamicDataAttribute.GetData(methodInfo); data.Should().NotBeNull(); data.ToList().Should().HaveCount(2); } public void GetDataShouldReadDataFromMethod() { MethodInfo methodInfo = _dummyTestClass.GetType().GetTypeInfo().GetDeclaredMethod("TestMethod2")!; _dynamicDataAttribute = new DynamicDataAttribute("ReusableTestDataMethod", DynamicDataSourceType.Method); IEnumerable data = _dynamicDataAttribute.GetData(methodInfo); data.Should().NotBeNull(); data.ToList().Should().HaveCount(2); } public void GetDataShouldReadDataFromMethodInDifferentClass() { MethodInfo methodInfo = _dummyTestClass.GetType().GetTypeInfo().GetDeclaredMethod("TestMethod2")!; _dynamicDataAttribute = new DynamicDataAttribute("ReusableTestDataMethod2", typeof(DummyTestClass2), DynamicDataSourceType.Method); IEnumerable data = _dynamicDataAttribute.GetData(methodInfo); data.Should().NotBeNull(); data.ToList().Should().HaveCount(2); } public void GetDataShouldThrowExceptionIfPropertyReturnsNull() { Action action = () => { MethodInfo methodInfo = _dummyTestClass.GetType().GetTypeInfo().GetDeclaredMethod("TestMethod4")!; _dynamicDataAttribute = new DynamicDataAttribute("NullProperty", typeof(DummyTestClass)); _dynamicDataAttribute.GetData(methodInfo); }; action.Should().Throw(); } public void GetDataShouldNotThrowExceptionIfPropertyReturnsEmpty() { MethodInfo methodInfo = _dummyTestClass.GetType().GetTypeInfo().GetDeclaredMethod("TestMethod5")!; _dynamicDataAttribute = new DynamicDataAttribute("EmptyProperty", typeof(DummyTestClass)); IEnumerable data = _dynamicDataAttribute.GetData(methodInfo); // The callers in AssemblyEnumerator and TestMethodRunner are responsible // for throwing an exception if data is empty and ConsiderEmptyDataSourceAsInconclusive is false. data.Should().BeEmpty(); } public void GetDataShouldThrowExceptionIfPropertyDoesNotReturnCorrectType() { Action action = () => { MethodInfo methodInfo = _dummyTestClass.GetType().GetTypeInfo().GetDeclaredMethod("TestMethod3")!; _dynamicDataAttribute = new DynamicDataAttribute("WrongDataTypeProperty", typeof(DummyTestClass)); _dynamicDataAttribute.GetData(methodInfo); }; action.Should().Throw(); } public void GetDisplayNameShouldReturnDisplayName() { object[] data = [1, 2, 3]; string? displayName = _dynamicDataAttribute.GetDisplayName(_testMethodInfo, data); displayName.Should().Be("TestMethod1 (1,2,3)"); } public void GetDisplayNameShouldReturnDisplayNameWithDynamicDataDisplayName() { object[] data = [1, 2, 3]; _dynamicDataAttribute.DynamicDataDisplayName = "GetCustomDynamicDataDisplayName"; string? displayName = _dynamicDataAttribute.GetDisplayName(_testMethodInfo, data); displayName.Should().Be("DynamicDataTestWithDisplayName TestMethod1 with 3 parameters"); } public void GetDisplayNameShouldReturnDisplayNameWithDynamicDataDisplayNameInDifferentClass() { object[] data = [1, 2, 3]; _dynamicDataAttribute.DynamicDataDisplayName = "GetCustomDynamicDataDisplayName2"; _dynamicDataAttribute.DynamicDataDisplayNameDeclaringType = typeof(DummyTestClass2); string? displayName = _dynamicDataAttribute.GetDisplayName(_testMethodInfo, data); displayName.Should().Be("DynamicDataTestWithDisplayName TestMethod1 with 3 parameters"); } public void GetDisplayNameShouldThrowExceptionWithDynamicDataDisplayNameMethodMissingParameters() { Action action = () => { object[] data = [1, 2, 3]; _dynamicDataAttribute.DynamicDataDisplayName = "GetDynamicDataDisplayNameWithMissingParameters"; _dynamicDataAttribute.GetDisplayName(_testMethodInfo, data); }; action.Should().Throw(); } public void GetDisplayNameShouldThrowExceptionWithDynamicDataDisplayNameMethodInvalidReturnType() { Action action = () => { object[] data = [1, 2, 3]; _dynamicDataAttribute.DynamicDataDisplayName = "GetDynamicDataDisplayNameWithInvalidReturnType"; _dynamicDataAttribute.GetDisplayName(_testMethodInfo, data); }; action.Should().Throw(); } public void GetDisplayNameShouldThrowExceptionWithDynamicDataDisplayNameMethodInvalidFirstParameterType() { Action action = () => { object[] data = [1, 2, 3]; _dynamicDataAttribute.DynamicDataDisplayName = "GetDynamicDataDisplayNameWithInvalidFirstParameterType"; _dynamicDataAttribute.GetDisplayName(_testMethodInfo, data); }; action.Should().Throw(); } public void GetDisplayNameShouldThrowExceptionWithDynamicDataDisplayNameMethodInvalidSecondParameterType() { Action action = () => { object[] data = [1, 2, 3]; _dynamicDataAttribute.DynamicDataDisplayName = "GetDynamicDataDisplayNameWithInvalidSecondParameterType"; _dynamicDataAttribute.GetDisplayName(_testMethodInfo, data); }; action.Should().Throw(); } public void GetDisplayNameShouldThrowExceptionWithDynamicDataDisplayNameMethodNonStatic() { Action action = () => { object[] data = [1, 2, 3]; _dynamicDataAttribute.DynamicDataDisplayName = "GetDynamicDataDisplayNameNonStatic"; _dynamicDataAttribute.GetDisplayName(_testMethodInfo, data); }; action.Should().Throw(); } public void GetDisplayNameShouldThrowExceptionWithDynamicDataDisplayNameMethodPrivate() { Action action = () => { object[] data = [1, 2, 3]; _dynamicDataAttribute.DynamicDataDisplayName = "GetDynamicDataDisplayNamePrivate"; _dynamicDataAttribute.GetDisplayName(_testMethodInfo, data); }; action.Should().Throw(); } public void GetDisplayNameShouldThrowExceptionWithMissingDynamicDataDisplayNameMethod() { Action action = () => { object[] data = [1, 2, 3]; _dynamicDataAttribute.DynamicDataDisplayName = "MissingCustomDynamicDataDisplayName"; _dynamicDataAttribute.GetDisplayName(_testMethodInfo, data); }; action.Should().Throw(); } public void GetDisplayNameShouldReturnEmptyStringIfDataIsNull() { string? displayName = _dynamicDataAttribute.GetDisplayName(_testMethodInfo, null); displayName.Should().BeNull(); } public void GetDisplayNameHandlesNullValues() { string?[] data = ["value1", "value2", null]; string?[] data1 = [null, "value1", "value2"]; string?[] data2 = ["value1", null, "value2"]; string? displayName = _dynamicDataAttribute.GetDisplayName(_testMethodInfo, data); displayName.Should().Be("TestMethod1 (\"value1\",\"value2\",null)"); displayName = _dynamicDataAttribute.GetDisplayName(_testMethodInfo, data1); displayName.Should().Be("TestMethod1 (null,\"value1\",\"value2\")"); displayName = _dynamicDataAttribute.GetDisplayName(_testMethodInfo, data2); displayName.Should().Be("TestMethod1 (\"value1\",null,\"value2\")"); } public void GetDisplayNameForArrayOfMultipleItems() { string? displayName = _dynamicDataAttribute.GetDisplayName(_testMethodInfo, [new[] { "a", "b", "c" }]); displayName.Should().Be("TestMethod1 ([\"a\",\"b\",\"c\"])"); } public void GetDisplayNameForMultipleArraysOfOneItem() { string? displayName = _dynamicDataAttribute.GetDisplayName(_testMethodInfo, [new[] { "a" }, new[] { "1" }]); displayName.Should().Be("TestMethod1 ([\"a\"],[\"1\"])"); } public void GetDisplayNameForMultipleArraysOfMultipleItems() { string? displayName = _dynamicDataAttribute.GetDisplayName(_testMethodInfo, [new[] { "a", "b", "c" }, new[] { "1", "2", "3" }]); displayName.Should().Be("TestMethod1 ([\"a\",\"b\",\"c\"],[\"1\",\"2\",\"3\"])"); } public void GetDisplayNameForMultipleArraysOfMultipleItemsValueTypes() { string? displayName = _dynamicDataAttribute.GetDisplayName(_testMethodInfo, [new[] { 1, 2, 3 }, new[] { 4, 5, 6 }]); displayName.Should().Be("TestMethod1 ([1,2,3],[4,5,6])"); } public void GetDisplayNameForMultipleArraysOfArraysOfMultipleItems() { string? displayName = _dynamicDataAttribute.GetDisplayName(_testMethodInfo, [new[] { ["a", "b", "c"], ["d", "e", "f"], new[] { "gh", "ij", "kl" } }, new[] { 'm', 'n', 'o' }, new[] { ["1", "2", "3"], ["4", "5", "6"], new[] { "7", "8", "9" } }]); displayName.Should().Be("TestMethod1 ([[\"a\",\"b\",\"c\"],[\"d\",\"e\",\"f\"],[\"gh\",\"ij\",\"kl\"]],['m','n','o'],[[\"1\",\"2\",\"3\"],[\"4\",\"5\",\"6\"],[\"7\",\"8\",\"9\"]])"); } public void DynamicDataSource_WithTuple_Works() { MethodInfo testMethodInfo = new TestClassTupleData().GetType().GetTypeInfo().GetDeclaredMethod(nameof(TestClassTupleData.DynamicDataTestWithTuple))!; var dynamicDataAttribute = new DynamicDataAttribute(nameof(TestClassTupleData.DataWithTuple), typeof(TestClassTupleData)); dynamicDataAttribute.GetData(testMethodInfo); dynamicDataAttribute = new DynamicDataAttribute(nameof(TestClassTupleData.GetDataWithTuple), typeof(TestClassTupleData), DynamicDataSourceType.Method); dynamicDataAttribute.GetData(testMethodInfo); } public void DynamicDataSource_WithValueTuple_Works() { MethodInfo testMethodInfo = new TestClassTupleData().GetType().GetTypeInfo().GetDeclaredMethod(nameof(TestClassTupleData.DynamicDataTestWithTuple))!; var dynamicDataAttribute = new DynamicDataAttribute(nameof(TestClassTupleData.DataWithValueTuple), typeof(TestClassTupleData)); dynamicDataAttribute.GetData(testMethodInfo); dynamicDataAttribute = new DynamicDataAttribute(nameof(TestClassTupleData.GetDataWithValueTuple), typeof(TestClassTupleData), DynamicDataSourceType.Method); dynamicDataAttribute.GetData(testMethodInfo); } public void DynamicDataSource_WithValueTupleWithTupleSyntax_Works() { MethodInfo testMethodInfo = new TestClassTupleData().GetType().GetTypeInfo().GetDeclaredMethod(nameof(TestClassTupleData.DynamicDataTestWithTuple))!; var dynamicDataAttribute = new DynamicDataAttribute(nameof(TestClassTupleData.DataWithValueTupleWithTupleSyntax), typeof(TestClassTupleData)); dynamicDataAttribute.GetData(testMethodInfo); dynamicDataAttribute = new DynamicDataAttribute(nameof(TestClassTupleData.GetDataWithValueTupleWithTupleSyntax), typeof(TestClassTupleData), DynamicDataSourceType.Method); dynamicDataAttribute.GetData(testMethodInfo); } public void GetDataShouldReadDataFromField() { MethodInfo methodInfo = _dummyTestClass.GetType().GetTypeInfo().GetDeclaredMethod("TestMethod1")!; _dynamicDataAttribute = new DynamicDataAttribute("ReusableTestDataField", DynamicDataSourceType.Field); IEnumerable data = _dynamicDataAttribute.GetData(methodInfo); data.Should().NotBeNull(); data.ToList().Should().HaveCount(2); } public void GetDataShouldReadDataFromFieldInDifferentClass() { MethodInfo methodInfo = _dummyTestClass.GetType().GetTypeInfo().GetDeclaredMethod("TestMethod1")!; _dynamicDataAttribute = new DynamicDataAttribute("ReusableTestDataField2", typeof(DummyTestClass2), DynamicDataSourceType.Field); IEnumerable data = _dynamicDataAttribute.GetData(methodInfo); data.Should().NotBeNull(); data.ToList().Should().HaveCount(2); } public void GetDataShouldReadDataFromFieldInAutoDetectMode() { MethodInfo methodInfo = _dummyTestClass.GetType().GetTypeInfo().GetDeclaredMethod("TestMethod1")!; _dynamicDataAttribute = new DynamicDataAttribute("ReusableTestDataField"); IEnumerable data = _dynamicDataAttribute.GetData(methodInfo); data.Should().NotBeNull(); data.ToList().Should().HaveCount(2); } public void GetDataShouldThrowExceptionIfFieldReturnsNull() { Action action = () => { MethodInfo methodInfo = _dummyTestClass.GetType().GetTypeInfo().GetDeclaredMethod("TestMethod1")!; _dynamicDataAttribute = new DynamicDataAttribute("NullField", typeof(DummyTestClass), DynamicDataSourceType.Field); _dynamicDataAttribute.GetData(methodInfo); }; action.Should().Throw(); } public void GetDataShouldNotThrowExceptionIfFieldReturnsEmpty() { MethodInfo methodInfo = _dummyTestClass.GetType().GetTypeInfo().GetDeclaredMethod("TestMethod1")!; _dynamicDataAttribute = new DynamicDataAttribute("EmptyField", typeof(DummyTestClass), DynamicDataSourceType.Field); IEnumerable data = _dynamicDataAttribute.GetData(methodInfo); // The callers in AssemblyEnumerator and TestMethodRunner are responsible // for throwing an exception if data is empty and ConsiderEmptyDataSourceAsInconclusive is false. data.Should().BeEmpty(); } public void GetDataShouldThrowExceptionIfFieldDoesNotReturnCorrectType() { Action action = () => { MethodInfo methodInfo = _dummyTestClass.GetType().GetTypeInfo().GetDeclaredMethod("TestMethod1")!; _dynamicDataAttribute = new DynamicDataAttribute("WrongDataTypeField", typeof(DummyTestClass), DynamicDataSourceType.Field); _dynamicDataAttribute.GetData(methodInfo); }; action.Should().Throw(); } public void GetDataShouldThrowExceptionIfFieldIsNotStatic() { Action action = () => { MethodInfo methodInfo = _dummyTestClass.GetType().GetTypeInfo().GetDeclaredMethod("TestMethod1")!; _dynamicDataAttribute = new DynamicDataAttribute("NonStaticField", typeof(DummyTestClass), DynamicDataSourceType.Field); _dynamicDataAttribute.GetData(methodInfo); }; action.Should().Throw(); } /// /// The dummy test class. /// [TestClass] [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "Test use case")] internal class DummyTestClass { /// /// Gets the reusable test data property. /// public static IEnumerable ReusableTestDataProperty => [[1, 2, 3], [4, 5, 6]]; /// /// Gets the null test data property. /// public static IEnumerable NullProperty => null!; /// /// Gets the empty test data property. /// public static IEnumerable EmptyProperty => []; /// /// Gets the wrong test data property i.e. Property returning something other than /// expected data type of . /// public static string WrongDataTypeProperty => "Dummy"; /// /// The reusable test data field. /// public static IEnumerable ReusableTestDataField = [[1, 2, 3], [4, 5, 6]]; /// /// The null test data field. /// public static IEnumerable NullField = null!; /// /// The empty test data field. /// public static IEnumerable EmptyField = []; /// /// The wrong test data field i.e. Field returning something other than /// expected data type of . /// public static string WrongDataTypeField = "Dummy"; /// /// Non-static field that should cause an error. /// public IEnumerable NonStaticField = [[1, 2, 3]]; /// /// The reusable test data method. /// /// /// The . /// public static IEnumerable ReusableTestDataMethod() => [[1, 2, 3], [4, 5, 6]]; /// /// The custom display name method. /// /// /// The method info of test method. /// /// /// The test data which is passed to test method. /// /// /// The . /// public static string GetCustomDynamicDataDisplayName(MethodInfo methodInfo, object[] data) => $"DynamicDataTestWithDisplayName {methodInfo.Name} with {data.Length} parameters"; /// /// Custom display name method with missing parameters. /// /// /// The . /// public static string GetDynamicDataDisplayNameWithMissingParameters() => throw new InvalidOperationException(); /// /// Custom display name method with invalid return type. /// public static void GetDynamicDataDisplayNameWithInvalidReturnType() => throw new InvalidOperationException(); /// /// Custom display name method with invalid first parameter type. /// /// /// The method info of test method. /// /// /// The test data which is passed to test method. /// /// /// The . /// public static string GetDynamicDataDisplayNameWithInvalidFirstParameterType(string methodInfo, object[] data) => throw new InvalidOperationException(); /// /// Custom display name method with invalid second parameter. /// /// /// The method info of test method. /// /// /// The test data which is passed to test method. /// /// /// The . /// public static string GetDynamicDataDisplayNameWithInvalidSecondParameterType(MethodInfo methodInfo, string data) => throw new InvalidOperationException(); /// /// Custom display name method that is not static. /// /// /// The method info of test method. /// /// /// The test data which is passed to test method. /// /// /// The . /// public string GetDynamicDataDisplayNameNonStatic(MethodInfo methodInfo, object[] data) => throw new InvalidOperationException(); /// /// The test method 1. /// [TestMethod] [DynamicData("ReusableTestDataProperty")] public void TestMethod1() { } /// /// The test method 2. /// [TestMethod] [DynamicData("ReusableTestDataMethod")] public void TestMethod2() { } /// /// The test method 3. /// [TestMethod] [DynamicData("WrongDataTypeProperty")] public void TestMethod3() { } /// /// The test method 4. /// [TestMethod] [DynamicData("NullProperty")] public void TestMethod4() { } /// /// The test method 5. /// [TestMethod] [DynamicData("EmptyProperty")] public void TestMethod5() { } /// /// DataRow test method 1. /// [DataRow("First", "Second", null)] [DataRow(null, "First", "Second")] [DataRow("First", null, "Second")] [TestMethod] public void DataRowTestMethod() { } /// /// Custom display name method that is private. /// /// /// The method info of test method. /// /// /// The test data which is passed to test method. /// /// /// The . /// #pragma warning disable IDE0051 // Remove unused private members private static string GetDynamicDataDisplayNamePrivate(MethodInfo methodInfo, object[] data) => throw new InvalidOperationException(); } [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "For testing the use case")] [SuppressMessage("Usage", "CA2211:Non-constant fields should not be visible", Justification = "For testing the use case")] public class DummyTestClass2 { /// /// Gets the reusable test data property. /// public static IEnumerable ReusableTestDataProperty2 => [[1, 2, 3], [4, 5, 6]]; /// /// The reusable test data method. /// /// /// The . /// public static IEnumerable ReusableTestDataMethod2() => [[1, 2, 3], [4, 5, 6]]; /// /// The reusable test data field. /// public static IEnumerable ReusableTestDataField2 = [[1, 2, 3], [4, 5, 6]]; /// /// The custom display name method. /// /// /// The method info of test method. /// /// /// The test data which is passed to test method. /// /// /// The . /// public static string GetCustomDynamicDataDisplayName2(MethodInfo methodInfo, object[] data) => $"DynamicDataTestWithDisplayName {methodInfo.Name} with {data.Length} parameters"; } [TestClass] internal class TestClassTupleData { public static IEnumerable> GetDataWithTuple() { yield return new(0, "0"); yield return new(1, "1"); } public static IEnumerable> DataWithTuple { get { yield return new(0, "0"); yield return new(1, "1"); } } [SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1141:Use tuple syntax", Justification = "We want to explicitly test this syntax")] public static IEnumerable> GetDataWithValueTuple() { yield return new(0, "0"); yield return new(1, "1"); } [SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1141:Use tuple syntax", Justification = "We want to explicitly test this syntax")] public static IEnumerable> DataWithValueTuple { get { yield return new(0, "0"); yield return new(1, "1"); } } public static IEnumerable<(int Integer, string AsString)> GetDataWithValueTupleWithTupleSyntax() { yield return (0, "0"); yield return (1, "1"); } public static IEnumerable<(int Integer, string AsString)> DataWithValueTupleWithTupleSyntax { get { yield return (0, "0"); yield return (1, "1"); } } [DataTestMethod] public void DynamicDataTestWithTuple(int value, string integerAsString) { } } }