diff --git a/src/Adapter/MSTest.CoreAdapter/Constants.cs b/src/Adapter/MSTest.CoreAdapter/Constants.cs index 45ee087101..80f4f4637b 100644 --- a/src/Adapter/MSTest.CoreAdapter/Constants.cs +++ b/src/Adapter/MSTest.CoreAdapter/Constants.cs @@ -40,6 +40,8 @@ internal static class Constants internal static readonly TestProperty TestClassNameProperty = TestProperty.Register("MSTestDiscoverer.TestClassName", TestClassNameLabel, typeof(string), TestPropertyAttributes.Hidden, typeof(TestCase)); + internal static readonly TestProperty DeclaringClassNameProperty = TestProperty.Register("MSTestDiscoverer.DeclaringClassName", DeclaringClassNameLabel, typeof(string), TestPropertyAttributes.Hidden, typeof(TestCase)); + internal static readonly TestProperty AsyncTestProperty = TestProperty.Register("MSTestDiscoverer.IsAsync", IsAsyncLabel, typeof(bool), TestPropertyAttributes.Hidden, typeof(TestCase)); #pragma warning disable CS0618 // Type or member is obsolete @@ -98,6 +100,7 @@ internal static class Constants /// These Property names should not be localized. /// private const string TestClassNameLabel = "ClassName"; + private const string DeclaringClassNameLabel = "DeclaringClassName"; private const string IsAsyncLabel = "IsAsync"; private const string TestCategoryLabel = "TestCategory"; private const string PriorityLabel = "Priority"; diff --git a/src/Adapter/MSTest.CoreAdapter/Discovery/TypeEnumerator.cs b/src/Adapter/MSTest.CoreAdapter/Discovery/TypeEnumerator.cs index 5177dda6ee..ea861d1d36 100644 --- a/src/Adapter/MSTest.CoreAdapter/Discovery/TypeEnumerator.cs +++ b/src/Adapter/MSTest.CoreAdapter/Discovery/TypeEnumerator.cs @@ -70,6 +70,8 @@ internal virtual ICollection Enumerate(out ICollection /// List of Valid Tests. internal Collection GetTests(ICollection warnings) { + bool foundDuplicateTests = false; + var foundTests = new HashSet(); var tests = new Collection(); // Test class is already valid. Verify methods. @@ -85,11 +87,35 @@ internal Collection GetTests(ICollection warnings) if (this.testMethodValidator.IsValidTestMethod(method, this.type, warnings)) { + foundDuplicateTests = foundDuplicateTests || !foundTests.Add(method.Name); tests.Add(this.GetTestFromMethod(method, isMethodDeclaredInTestTypeAssembly, warnings)); } } - return tests; + if (!foundDuplicateTests) + { + return tests; + } + + // Remove duplicate test methods by taking the first one of each name + // that is declared closest to the test class in the hierarchy. + var inheritanceDepths = new Dictionary(); + var currentType = this.type; + int currentDepth = 0; + + while (currentType != null) + { + inheritanceDepths[currentType.FullName] = currentDepth; + ++currentDepth; + currentType = currentType.GetTypeInfo().BaseType; + } + + return new Collection( + tests.GroupBy( + t => t.TestMethod.Name, + (_, elements) => + elements.OrderBy(t => inheritanceDepths[t.TestMethod.DeclaringClassFullName ?? t.TestMethod.FullClassName]).First()) + .ToList()); } /// @@ -126,9 +152,9 @@ internal UnitTestElement GetTestFromMethod(MethodInfo method, bool isDeclaredInT var asyncTypeName = method.GetAsyncTypeName(); testElement.AsyncTypeName = asyncTypeName; - testElement.TestCategory = this.reflectHelper.GetCategories(method); + testElement.TestCategory = this.reflectHelper.GetCategories(method, this.type); - testElement.DoNotParallelize = this.reflectHelper.IsDoNotParallelizeSet(method); + testElement.DoNotParallelize = this.reflectHelper.IsDoNotParallelizeSet(method, this.type); var traits = this.reflectHelper.GetTestPropertiesAsTraits(method); diff --git a/src/Adapter/MSTest.CoreAdapter/Execution/TypeCache.cs b/src/Adapter/MSTest.CoreAdapter/Execution/TypeCache.cs index cf9f0d105a..251a20e433 100644 --- a/src/Adapter/MSTest.CoreAdapter/Execution/TypeCache.cs +++ b/src/Adapter/MSTest.CoreAdapter/Execution/TypeCache.cs @@ -606,10 +606,26 @@ private TestMethodAttribute GetTestMethodAttribute(MethodInfo methodInfo, TestCl private MethodInfo GetMethodInfoForTestMethod(TestMethod testMethod, TestClassInfo testClassInfo) { var methodsInClass = testClassInfo.ClassType.GetRuntimeMethods().ToArray(); + MethodInfo testMethodInfo; - var testMethodInfo = - methodsInClass.Where(method => method.Name.Equals(testMethod.Name)) - .FirstOrDefault(method => method.HasCorrectTestMethodSignature(true)); + if (testMethod.DeclaringClassFullName != null) + { + // Only find methods that match the given declaring name. + testMethodInfo = + methodsInClass.Where(method => method.Name.Equals(testMethod.Name) + && method.DeclaringType.FullName.Equals(testMethod.DeclaringClassFullName) + && method.HasCorrectTestMethodSignature(true)).FirstOrDefault(); + } + else + { + // Either the declaring class is the same as the test class, or + // the declaring class information wasn't passed in the test case. + // Prioritize the former while maintaining previous behavior for the latter. + var className = testClassInfo.ClassType.FullName; + testMethodInfo = + methodsInClass.Where(method => method.Name.Equals(testMethod.Name) && method.HasCorrectTestMethodSignature(true)) + .OrderByDescending(method => method.DeclaringType.FullName.Equals(className)).FirstOrDefault(); + } // if correct method is not found, throw appropriate // exception about what is wrong. diff --git a/src/Adapter/MSTest.CoreAdapter/Extensions/TestCaseExtensions.cs b/src/Adapter/MSTest.CoreAdapter/Extensions/TestCaseExtensions.cs index 45a17a14d7..4b36457406 100644 --- a/src/Adapter/MSTest.CoreAdapter/Extensions/TestCaseExtensions.cs +++ b/src/Adapter/MSTest.CoreAdapter/Extensions/TestCaseExtensions.cs @@ -22,9 +22,15 @@ internal static UnitTestElement ToUnitTestElement(this TestCase testCase, string { var isAsync = (testCase.GetPropertyValue(Constants.AsyncTestProperty) as bool?) ?? false; var testClassName = testCase.GetPropertyValue(Constants.TestClassNameProperty) as string; + var declaringClassName = testCase.GetPropertyValue(Constants.DeclaringClassNameProperty) as string; TestMethod testMethod = new TestMethod(testCase.DisplayName, testClassName, source, isAsync); + if (declaringClassName != null && declaringClassName != testClassName) + { + testMethod.DeclaringClassFullName = declaringClassName; + } + UnitTestElement testElement = new UnitTestElement(testMethod) { IsAsync = isAsync, diff --git a/src/Adapter/MSTest.CoreAdapter/Helpers/ReflectHelper.cs b/src/Adapter/MSTest.CoreAdapter/Helpers/ReflectHelper.cs index 6fd7617021..feeeddd7b5 100644 --- a/src/Adapter/MSTest.CoreAdapter/Helpers/ReflectHelper.cs +++ b/src/Adapter/MSTest.CoreAdapter/Helpers/ReflectHelper.cs @@ -315,10 +315,11 @@ internal virtual bool IsMethodDeclaredInSameAssemblyAsType(MethodInfo method, Ty /// Get categories applied to the test method /// /// The member to inspect. + /// The reflected type that owns . /// Categories defined. - internal virtual string[] GetCategories(MemberInfo categoryAttributeProvider) + internal virtual string[] GetCategories(MemberInfo categoryAttributeProvider, Type owningType) { - var categories = this.GetCustomAttributesRecursively(categoryAttributeProvider, typeof(TestCategoryBaseAttribute)); + var categories = this.GetCustomAttributesRecursively(categoryAttributeProvider, owningType, typeof(TestCategoryBaseAttribute)); List testCategories = new List(); if (categories != null) @@ -346,11 +347,12 @@ internal ParallelizeAttribute GetParallelizeAttribute(Assembly assembly) /// Get the parallelization behavior for a test method. /// /// Test method. + /// The type that owns . /// True if test method should not run in parallel. - internal bool IsDoNotParallelizeSet(MemberInfo testMethod) + internal bool IsDoNotParallelizeSet(MemberInfo testMethod, Type owningType) { return this.GetCustomAttributes(testMethod, typeof(DoNotParallelizeAttribute)).Any() - || this.GetCustomAttributes(testMethod.DeclaringType.GetTypeInfo(), typeof(DoNotParallelizeAttribute)).Any(); + || this.GetCustomAttributes(owningType.GetTypeInfo(), typeof(DoNotParallelizeAttribute)).Any(); } /// @@ -367,19 +369,20 @@ internal bool IsDoNotParallelizeSet(Assembly assembly) /// Gets custom attributes at the class and assembly for a method. /// /// Method Info or Member Info or a Type + /// The type that owns . /// What type of CustomAttribute you need. For instance: TestCategory, Owner etc., /// The categories of the specified type on the method. - internal IEnumerable GetCustomAttributesRecursively(MemberInfo attributeProvider, Type type) + internal IEnumerable GetCustomAttributesRecursively(MemberInfo attributeProvider, Type owningType, Type type) { var categories = this.GetCustomAttributes(attributeProvider, typeof(TestCategoryBaseAttribute)); if (categories != null) { - categories = categories.Concat(this.GetCustomAttributes(attributeProvider.DeclaringType.GetTypeInfo(), typeof(TestCategoryBaseAttribute))).ToArray(); + categories = categories.Concat(this.GetCustomAttributes(owningType.GetTypeInfo(), typeof(TestCategoryBaseAttribute))).ToArray(); } if (categories != null) { - categories = categories.Concat(this.GetCustomAttributeForAssembly(attributeProvider, typeof(TestCategoryBaseAttribute))).ToArray(); + categories = categories.Concat(this.GetCustomAttributeForAssembly(owningType.GetTypeInfo(), typeof(TestCategoryBaseAttribute))).ToArray(); } if (categories != null) @@ -401,8 +404,7 @@ internal virtual Attribute[] GetCustomAttributeForAssembly(MemberInfo memberInfo { return PlatformServiceProvider.Instance.ReflectionOperations.GetCustomAttributes( - memberInfo.DeclaringType.GetTypeInfo().Assembly, - type).OfType().ToArray(); + memberInfo.Module.Assembly, type).OfType().ToArray(); } /// diff --git a/src/Adapter/MSTest.CoreAdapter/ObjectModel/TestMethod.cs b/src/Adapter/MSTest.CoreAdapter/ObjectModel/TestMethod.cs index 8692bd0b39..708e9b621f 100644 --- a/src/Adapter/MSTest.CoreAdapter/ObjectModel/TestMethod.cs +++ b/src/Adapter/MSTest.CoreAdapter/ObjectModel/TestMethod.cs @@ -74,7 +74,8 @@ public string DeclaringAssemblyName } /// - /// Gets or sets the declaring class full name. This will be used while getting navigation data. + /// Gets or sets the declaring class full name. + /// This will be used to resolve overloads and while getting navigation data. /// This will be null if FullClassName is same as DeclaringClassFullName. /// Reason to set to null in the above case is to minimise the transfer of data across appdomains and not have a perf hit. /// diff --git a/src/Adapter/MSTest.CoreAdapter/ObjectModel/UnitTestElement.cs b/src/Adapter/MSTest.CoreAdapter/ObjectModel/UnitTestElement.cs index 00215788db..744e224101 100644 --- a/src/Adapter/MSTest.CoreAdapter/ObjectModel/UnitTestElement.cs +++ b/src/Adapter/MSTest.CoreAdapter/ObjectModel/UnitTestElement.cs @@ -114,6 +114,12 @@ internal TestCase ToTestCase() testCase.SetPropertyValue(TestAdapter.Constants.TestClassNameProperty, this.TestMethod.FullClassName); + // Set declaring type if present so the correct method info can be retrieved + if (this.TestMethod.DeclaringClassFullName != null) + { + testCase.SetPropertyValue(TestAdapter.Constants.DeclaringClassNameProperty, this.TestMethod.DeclaringClassFullName); + } + // Many of the tests will not be async, so there is no point in sending extra data if (this.IsAsync) { diff --git a/src/Adapter/PlatformServices.Interface/ObjectModel/ITestMethod.cs b/src/Adapter/PlatformServices.Interface/ObjectModel/ITestMethod.cs index fd3abb6496..5d3abe84dd 100644 --- a/src/Adapter/PlatformServices.Interface/ObjectModel/ITestMethod.cs +++ b/src/Adapter/PlatformServices.Interface/ObjectModel/ITestMethod.cs @@ -19,7 +19,8 @@ public interface ITestMethod string FullClassName { get; } /// - /// Gets the declaring class full name. This will be used while getting navigation data. + /// Gets the declaring class full name. + /// This will be used for resolving overloads and while getting navigation data. /// string DeclaringClassFullName { get; } diff --git a/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Discovery/TypeEnumeratorTests.cs b/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Discovery/TypeEnumeratorTests.cs index 94639f1a05..d68e2655dc 100644 --- a/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Discovery/TypeEnumeratorTests.cs +++ b/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Discovery/TypeEnumeratorTests.cs @@ -183,6 +183,82 @@ public void GetTestsShouldNotReturnBaseTestMethodsFromAnotherAssemblyByConfigura "DummyDerivedFromRemoteTestClass inherits DummyRemoteBaseTestClass from different assembly. BestTestMethod from DummyRemoteBaseTestClass should not be discovered when RunSettings MSTestV2 specifies EnableBaseClassTestMethodsFromOtherAssemblies = false."); } + [TestMethod] + public void GetTestsShouldNotReturnHiddenTestMethods() + { + this.SetupTestClassAndTestMethods(isValidTestClass: true, isValidTestMethod: true, isMethodFromSameAssembly: true); + TypeEnumerator typeEnumerator = this.GetTypeEnumeratorInstance(typeof(DummyHidingTestClass), Assembly.GetExecutingAssembly().FullName); + + var tests = typeEnumerator.Enumerate(out this.warnings); + + Assert.IsNotNull(tests); + Assert.AreEqual( + 1, + tests.Count(t => t.TestMethod.Name == "BaseTestMethod"), + "DummyHidingTestClass declares BaseTestMethod directly so it should always be discovered."); + Assert.AreEqual( + 1, + tests.Count(t => t.TestMethod.Name == "DerivedTestMethod"), + "DummyHidingTestClass declares BaseTestMethod directly so it should always be discovered."); + Assert.IsFalse( + tests.Any(t => t.TestMethod.DeclaringClassFullName == typeof(DummyBaseTestClass).FullName), + "DummyHidingTestClass hides BaseTestMethod so declaring class should not be the base class"); + } + + [TestMethod] + public void GetTestsShouldReturnOverriddenTestMethods() + { + this.SetupTestClassAndTestMethods(isValidTestClass: true, isValidTestMethod: true, isMethodFromSameAssembly: true); + TypeEnumerator typeEnumerator = this.GetTypeEnumeratorInstance(typeof(DummyOverridingTestClass), Assembly.GetExecutingAssembly().FullName); + + var tests = typeEnumerator.Enumerate(out this.warnings); + + Assert.IsNotNull(tests); + Assert.AreEqual( + 1, + tests.Count(t => t.TestMethod.Name == "BaseTestMethod"), + "DummyOverridingTestClass inherits BaseTestMethod so it should be discovered."); + Assert.AreEqual( + 1, + tests.Count(t => t.TestMethod.Name == "DerivedTestMethod"), + "DummyOverridingTestClass overrides DerivedTestMethod directly so it should always be discovered."); + Assert.AreEqual( + typeof(DummyHidingTestClass).FullName, + tests.Single(t => t.TestMethod.Name == "BaseTestMethod").TestMethod.DeclaringClassFullName, + "DummyOverridingTestClass inherits BaseTestMethod from DummyHidingTestClass specifically."); + Assert.IsNull( + tests.Single(t => t.TestMethod.Name == "DerivedTestMethod").TestMethod.DeclaringClassFullName, + "DummyOverridingTestClass overrides DerivedTestMethod so is the declaring class."); + } + + [TestMethod] + public void GetTestsShouldNotReturnHiddenTestMethodsFromAnyLevel() + { + this.SetupTestClassAndTestMethods(isValidTestClass: true, isValidTestMethod: true, isMethodFromSameAssembly: true); + TypeEnumerator typeEnumerator = this.GetTypeEnumeratorInstance(typeof(DummySecondHidingTestClass), Assembly.GetExecutingAssembly().FullName); + + var tests = typeEnumerator.Enumerate(out this.warnings); + + Assert.IsNotNull(tests); + Assert.AreEqual( + 1, + tests.Count(t => t.TestMethod.Name == "BaseTestMethod"), + "DummySecondHidingTestClass hides BaseTestMethod so it should be discovered."); + Assert.AreEqual( + 1, + tests.Count(t => t.TestMethod.Name == "DerivedTestMethod"), + "DummySecondHidingTestClass hides DerivedTestMethod so it should be discovered."); + Assert.IsFalse( + tests.Any(t => t.TestMethod.DeclaringClassFullName == typeof(DummyBaseTestClass).FullName), + "DummySecondHidingTestClass hides all base test methods so declaring class should not be any base class"); + Assert.IsFalse( + tests.Any(t => t.TestMethod.DeclaringClassFullName == typeof(DummyHidingTestClass).FullName), + "DummySecondHidingTestClass hides all base test methods so declaring class should not be any base class"); + Assert.IsFalse( + tests.Any(t => t.TestMethod.DeclaringClassFullName == typeof(DummyOverridingTestClass).FullName), + "DummySecondHidingTestClass hides all base test methods so declaring class should not be any base class"); + } + #endregion #region GetTestFromMethod tests @@ -247,7 +323,7 @@ public void GetTestFromMethodShouldSetTestCategory() var testCategories = new string[] { "foo", "bar" }; // Setup mocks - this.mockReflectHelper.Setup(rh => rh.GetCategories(methodInfo)).Returns(testCategories); + this.mockReflectHelper.Setup(rh => rh.GetCategories(methodInfo, typeof(DummyTestClass))).Returns(testCategories); var testElement = typeEnumerator.GetTestFromMethod(methodInfo, true, this.warnings); @@ -496,5 +572,34 @@ public void DerivedTestMethod() } } + public class DummyHidingTestClass : DummyBaseTestClass + { + public new virtual void BaseTestMethod() + { + } + + public virtual void DerivedTestMethod() + { + } + } + + public class DummyOverridingTestClass : DummyHidingTestClass + { + public override void DerivedTestMethod() + { + } + } + + public class DummySecondHidingTestClass : DummyOverridingTestClass + { + public new void BaseTestMethod() + { + } + + public new void DerivedTestMethod() + { + } + } + #endregion } diff --git a/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Execution/TypeCacheTests.cs b/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Execution/TypeCacheTests.cs index 8e2e4c8806..7883de6c59 100644 --- a/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Execution/TypeCacheTests.cs +++ b/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Execution/TypeCacheTests.cs @@ -1031,6 +1031,48 @@ public void GetTestMethodInfoShouldReturnTestMethodInfoForDerivedTestClasses() Assert.IsNotNull(testMethodInfo.TestMethodOptions.Executor); } + [TestMethodV1] + public void GetTestMethodInfoShouldReturnTestMethodInfoForDerivedClassMethodOverloadByDefault() + { + var type = typeof(DerivedTestClass); + var methodInfo = type.GetRuntimeMethod("OverloadedTestMethod", new Type[] { }); + var testMethod = new TestMethod(methodInfo.Name, type.FullName, "A", isAsync: false); + + var testMethodInfo = this.typeCache.GetTestMethodInfo( + testMethod, + new TestContextImplementation(testMethod, null, new Dictionary()), + false); + + Assert.AreEqual(methodInfo, testMethodInfo.TestMethod); + Assert.AreEqual(0, testMethodInfo.TestMethodOptions.Timeout); + Assert.AreEqual(this.typeCache.ClassInfoCache.ToArray()[0], testMethodInfo.Parent); + Assert.IsNotNull(testMethodInfo.TestMethodOptions.Executor); + } + + [TestMethodV1] + public void GetTestMethodInfoShouldReturnTestMethodInfoForDeclaringTypeMethodOverload() + { + var baseType = typeof(BaseTestClass); + var type = typeof(DerivedTestClass); + var methodInfo = baseType.GetRuntimeMethod("OverloadedTestMethod", new Type[] { }); + var testMethod = new TestMethod(methodInfo.Name, type.FullName, "A", isAsync: false) + { + DeclaringClassFullName = baseType.FullName + }; + + var testMethodInfo = this.typeCache.GetTestMethodInfo( + testMethod, + new TestContextImplementation(testMethod, null, new Dictionary()), + false); + + // The two MethodInfo instances will have different ReflectedType properties, + // so cannot be compared directly. Use MethodHandle to verify it's the same. + Assert.AreEqual(methodInfo.MethodHandle, testMethodInfo.TestMethod.MethodHandle); + Assert.AreEqual(0, testMethodInfo.TestMethodOptions.Timeout); + Assert.AreEqual(this.typeCache.ClassInfoCache.ToArray()[0], testMethodInfo.Parent); + Assert.IsNotNull(testMethodInfo.TestMethodOptions.Executor); + } + #endregion #endregion @@ -1311,6 +1353,10 @@ public void TestMethodWithMultipleExpectedException() [DummyTestClass] internal class DerivedTestClass : BaseTestClass { + [UTF.TestMethod] + public new void OverloadedTestMethod() + { + } } internal class BaseTestClass @@ -1319,6 +1365,11 @@ internal class BaseTestClass public void DummyTestMethod() { } + + [UTF.TestMethod] + public void OverloadedTestMethod() + { + } } private class DummyTestClassWithNoDefaultConstructor diff --git a/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Extensions/TestCaseExtensionsTests.cs b/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Extensions/TestCaseExtensionsTests.cs index e827d03569..8c6ef2c73f 100644 --- a/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Extensions/TestCaseExtensionsTests.cs +++ b/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Extensions/TestCaseExtensionsTests.cs @@ -37,6 +37,7 @@ public void ToUnitTestElementShouldReturnUnitTestElementWithFieldsSet() Assert.AreEqual("DummyDisplayName", resultUnitTestElement.TestMethod.Name); Assert.AreEqual("DummyClassName", resultUnitTestElement.TestMethod.FullClassName); Assert.AreEqual(true, resultUnitTestElement.TestMethod.IsAsync); + Assert.IsNull(resultUnitTestElement.TestMethod.DeclaringClassFullName); } [TestMethod] @@ -52,5 +53,18 @@ public void ToUnitTestElementForTestCaseWithNoPropertiesShouldReturnUnitTestElem Assert.AreEqual(0, resultUnitTestElement.Priority); Assert.AreEqual(null, resultUnitTestElement.TestCategory); } + + [TestMethod] + public void ToUnitTestElementShouldAddDeclaringClassNameToTestElementWhenAvailable() + { + TestCase testCase = new TestCase("DummyClass.DummyMethod", new Uri("DummyUri", UriKind.Relative), Assembly.GetCallingAssembly().FullName); + testCase.SetPropertyValue(Constants.TestClassNameProperty, "DummyClassName"); + testCase.SetPropertyValue(Constants.DeclaringClassNameProperty, "DummyDeclaringClassName"); + + var resultUnitTestElement = testCase.ToUnitTestElement(testCase.Source); + + Assert.AreEqual("DummyClassName", resultUnitTestElement.TestMethod.FullClassName); + Assert.AreEqual("DummyDeclaringClassName", resultUnitTestElement.TestMethod.DeclaringClassFullName); + } } } diff --git a/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Helpers/ReflectHelperTests.cs b/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Helpers/ReflectHelperTests.cs index c37d2d432a..49bb940e5f 100644 --- a/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Helpers/ReflectHelperTests.cs +++ b/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Helpers/ReflectHelperTests.cs @@ -36,7 +36,6 @@ public void IntializeTests() this.reflectHelper = new TestableReflectHelper(); this.method = new Mock(); this.method.Setup(x => x.MemberType).Returns(MemberTypes.Method); - this.method.Setup(x => x.DeclaringType).Returns(typeof(ReflectHelperTests)); this.testablePlatformServiceProvider = new TestablePlatformServiceProvider(); this.testablePlatformServiceProvider.SetupMockReflectionOperations(); @@ -58,13 +57,13 @@ public void GetTestCategoryAttributeShouldIncludeTestCategoriesAtClassLevel() this.reflectHelper.SetCustomAttribute(typeof(UTF.TestCategoryBaseAttribute), new[] { new UTF.TestCategoryAttribute("ClassLevel") }, MemberTypes.TypeInfo); string[] expected = new[] { "ClassLevel" }; - var actual = this.reflectHelper.GetCategories(this.method.Object).ToArray(); + var actual = this.reflectHelper.GetCategories(this.method.Object, typeof(ReflectHelperTests)).ToArray(); CollectionAssert.AreEqual(expected, actual); } /// - /// Testing test category attributes adorned at calss, assembly and method level are getting collected. + /// Testing test category attributes adorned at class, assembly and method level are getting collected. /// [TestMethod] public void GetTestCategoryAttributeShouldIncludeTestCategoriesAtAllLevels() @@ -74,14 +73,14 @@ public void GetTestCategoryAttributeShouldIncludeTestCategoriesAtAllLevels() this.reflectHelper.SetCustomAttribute(typeof(UTF.TestCategoryBaseAttribute), new[] { new UTF.TestCategoryAttribute("ClassLevel") }, MemberTypes.TypeInfo); this.reflectHelper.SetCustomAttribute(typeof(UTF.TestCategoryBaseAttribute), new[] { new UTF.TestCategoryAttribute("MethodLevel") }, MemberTypes.Method); - var actual = this.reflectHelper.GetCategories(this.method.Object).ToArray(); + var actual = this.reflectHelper.GetCategories(this.method.Object, typeof(ReflectHelperTests)).ToArray(); string[] expected = new[] { "MethodLevel", "ClassLevel", "AsmLevel1", "AsmLevel2", "AsmLevel3" }; CollectionAssert.AreEqual(expected, actual); } /// - /// Testing test category attributes adorned at calss, assembly and method level are getting collected. + /// Testing test category attributes adorned at class, assembly and method level are getting collected. /// [TestMethod] public void GetTestCategoryAttributeShouldConcatCustomAttributeOfSameType() @@ -93,7 +92,7 @@ public void GetTestCategoryAttributeShouldConcatCustomAttributeOfSameType() this.reflectHelper.SetCustomAttribute(typeof(UTF.TestCategoryBaseAttribute), new[] { new UTF.TestCategoryAttribute("MethodLevel1") }, MemberTypes.Method); this.reflectHelper.SetCustomAttribute(typeof(UTF.TestCategoryBaseAttribute), new[] { new UTF.TestCategoryAttribute("MethodLevel2") }, MemberTypes.Method); - var actual = this.reflectHelper.GetCategories(this.method.Object).ToArray(); + var actual = this.reflectHelper.GetCategories(this.method.Object, typeof(ReflectHelperTests)).ToArray(); string[] expected = new[] { "MethodLevel1", "MethodLevel2", "ClassLevel1", "ClassLevel2", "AsmLevel1", "AsmLevel2" }; CollectionAssert.AreEqual(expected, actual); @@ -109,7 +108,7 @@ public void GetTestCategoryAttributeShouldIncludeTestCategoriesAtAssemblyLevel() string[] expected = new[] { "AsmLevel" }; - var actual = this.reflectHelper.GetCategories(this.method.Object).ToArray(); + var actual = this.reflectHelper.GetCategories(this.method.Object, typeof(ReflectHelperTests)).ToArray(); CollectionAssert.AreEqual(expected, actual); } @@ -123,7 +122,7 @@ public void GetTestCategoryAttributeShouldIncludeMultipleTestCategoriesAtClassLe this.reflectHelper.SetCustomAttribute(typeof(UTF.TestCategoryBaseAttribute), new[] { new UTF.TestCategoryAttribute("ClassLevel"), new UTF.TestCategoryAttribute("ClassLevel1") }, MemberTypes.TypeInfo); string[] expected = new[] { "ClassLevel", "ClassLevel1" }; - var actual = this.reflectHelper.GetCategories(this.method.Object).ToArray(); + var actual = this.reflectHelper.GetCategories(this.method.Object, typeof(ReflectHelperTests)).ToArray(); CollectionAssert.AreEqual(expected, actual); } @@ -137,7 +136,7 @@ public void GetTestCategoryAttributeShouldIncludeMultipleTestCategoriesAtAssembl this.reflectHelper.SetCustomAttribute(typeof(UTF.TestCategoryBaseAttribute), new[] { new UTF.TestCategoryAttribute("AsmLevel"), new UTF.TestCategoryAttribute("AsmLevel1") }, MemberTypes.All); string[] expected = new[] { "AsmLevel", "AsmLevel1" }; - var actual = this.reflectHelper.GetCategories(this.method.Object).ToArray(); + var actual = this.reflectHelper.GetCategories(this.method.Object, typeof(ReflectHelperTests)).ToArray(); CollectionAssert.AreEqual(expected, actual); } @@ -150,7 +149,7 @@ public void GetTestCategoryAttributeShouldIncludeTestCategoriesAtMethodLevel() this.reflectHelper.SetCustomAttribute(typeof(UTF.TestCategoryBaseAttribute), new[] { new UTF.TestCategoryAttribute("MethodLevel") }, MemberTypes.Method); string[] expected = new[] { "MethodLevel" }; - var actual = this.reflectHelper.GetCategories(this.method.Object).ToArray(); + var actual = this.reflectHelper.GetCategories(this.method.Object, typeof(ReflectHelperTests)).ToArray(); CollectionAssert.AreEqual(expected, actual); } diff --git a/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/ObjectModel/UnitTestElementTests.cs b/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/ObjectModel/UnitTestElementTests.cs index bb96dd1476..1143ae8967 100644 --- a/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/ObjectModel/UnitTestElementTests.cs +++ b/test/UnitTests/MSTest.CoreAdapter.Unit.Tests/ObjectModel/UnitTestElementTests.cs @@ -84,6 +84,20 @@ public void ToTestCaseShouldSetTestClassNameProperty() Assert.AreEqual("C", testCase.GetPropertyValue(Constants.TestClassNameProperty)); } + [TestMethodV1] + public void ToTestCaseShouldSetDeclaringClassNameIfPresent() + { + this.testMethod.DeclaringClassFullName = null; + var testCase = this.unitTestElement.ToTestCase(); + + Assert.IsNull(testCase.GetPropertyValue(Constants.DeclaringClassNameProperty)); + + this.testMethod.DeclaringClassFullName = "DC"; + testCase = this.unitTestElement.ToTestCase(); + + Assert.AreEqual("DC", testCase.GetPropertyValue(Constants.DeclaringClassNameProperty)); + } + [TestMethodV1] public void ToTestCaseShouldSetIsAsyncProperty() {