Skip to content

Commit d638ad8

Browse files
spottedmahnnohwnd
authored andcommittedDec 17, 2019
Friendly test names (#466)
Add DisplayName parameter to TestMethod to allow friendly test names Add the ability to specify a display name to a test method which can use arbitrary characters. Example ```csharp [TestMethod("Friendly Name 🏆🤩 - It's a brave new world - spaces are ok 🎉")] public void TestMethod1() { } ```
1 parent b715c12 commit d638ad8

File tree

7 files changed

+90
-9
lines changed

7 files changed

+90
-9
lines changed
 

‎src/Adapter/MSTest.CoreAdapter/Discovery/TypeEnumerator.cs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) Microsoft Corporation. All rights reserved.
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

44
namespace Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.Discovery
@@ -204,6 +204,10 @@ internal UnitTestElement GetTestFromMethod(MethodInfo method, bool isDeclaredInT
204204
this.type,
205205
warnings);
206206

207+
// get DisplayName from TestMethodAttribute
208+
var testMethodAttribute = this.reflectHelper.GetCustomAttribute(method, typeof(TestMethodAttribute)) as TestMethodAttribute;
209+
testElement.DisplayName = testMethodAttribute?.DisplayName ?? method.Name;
210+
207211
return testElement;
208212
}
209213
}

‎src/Adapter/MSTest.CoreAdapter/Extensions/TestCaseExtensions.cs

+9-6
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,22 @@ internal static UnitTestElement ToUnitTestElement(this TestCase testCase, string
2424
var testClassName = testCase.GetPropertyValue(Constants.TestClassNameProperty) as string;
2525
var declaringClassName = testCase.GetPropertyValue(Constants.DeclaringClassNameProperty) as string;
2626

27-
TestMethod testMethod = new TestMethod(testCase.DisplayName, testClassName, source, isAsync);
27+
var parts = testCase.FullyQualifiedName.Split('.');
28+
var name = parts[parts.Length - 1];
29+
TestMethod testMethod = new TestMethod(name, testClassName, source, isAsync);
2830

2931
if (declaringClassName != null && declaringClassName != testClassName)
3032
{
3133
testMethod.DeclaringClassFullName = declaringClassName;
3234
}
3335

3436
UnitTestElement testElement = new UnitTestElement(testMethod)
35-
{
36-
IsAsync = isAsync,
37-
TestCategory = testCase.GetPropertyValue(Constants.TestCategoryProperty) as string[],
38-
Priority = testCase.GetPropertyValue(Constants.PriorityProperty) as int?
39-
};
37+
{
38+
IsAsync = isAsync,
39+
TestCategory = testCase.GetPropertyValue(Constants.TestCategoryProperty) as string[],
40+
Priority = testCase.GetPropertyValue(Constants.PriorityProperty) as int?,
41+
DisplayName = testCase.DisplayName
42+
};
4043

4144
return testElement;
4245
}

‎src/Adapter/MSTest.CoreAdapter/ObjectModel/UnitTestElement.cs

+6-1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ public UnitTestElement(TestMethod testMethod)
7272
/// </summary>
7373
public KeyValuePair<string, string>[] DeploymentItems { get; set; }
7474

75+
/// <summary>
76+
/// Gets or sets the DisplayName
77+
/// </summary>
78+
public string DisplayName { get; set; }
79+
7580
/// <summary>
7681
/// Gets or sets the compiler generated type name for async test method.
7782
/// </summary>
@@ -110,7 +115,7 @@ internal TestCase ToTestCase()
110115
this.TestMethod.Name);
111116

112117
TestCase testCase = new TestCase(fullName, TestAdapter.Constants.ExecutorUri, this.TestMethod.AssemblyName);
113-
testCase.DisplayName = this.TestMethod.Name;
118+
testCase.DisplayName = string.IsNullOrEmpty(this.DisplayName) ? this.TestMethod.Name : this.DisplayName;
114119

115120
testCase.SetPropertyValue(TestAdapter.Constants.TestClassNameProperty, this.TestMethod.FullClassName);
116121

‎src/TestFramework/MSTest.Core/Attributes/VSTestAttributes.cs

+24
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,30 @@ public virtual TestMethodAttribute GetTestMethodAttribute(TestMethodAttribute te
6767
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
6868
public class TestMethodAttribute : Attribute
6969
{
70+
/// <summary>
71+
/// Initializes a new instance of the <see cref="TestMethodAttribute"/> class.
72+
/// </summary>
73+
public TestMethodAttribute()
74+
: this(null)
75+
{
76+
}
77+
78+
/// <summary>
79+
/// Initializes a new instance of the <see cref="TestMethodAttribute"/> class.
80+
/// </summary>
81+
/// <param name="displayName">
82+
/// Message specifies reason for ignoring.
83+
/// </param>
84+
public TestMethodAttribute(string displayName)
85+
{
86+
this.DisplayName = displayName;
87+
}
88+
89+
/// <summary>
90+
/// Gets display Name for the Test Window
91+
/// </summary>
92+
public string DisplayName { get; private set; }
93+
7094
/// <summary>
7195
/// Executes a test method.
7296
/// </summary>

‎test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Discovery/TypeEnumeratorTests.cs

+35
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ namespace Microsoft.VisualStudio.TestPlatform.MSTestAdapter.UnitTests.Discovery
2525
using TestCleanup = FrameworkV1::Microsoft.VisualStudio.TestTools.UnitTesting.TestCleanupAttribute;
2626
using TestInitialize = FrameworkV1::Microsoft.VisualStudio.TestTools.UnitTesting.TestInitializeAttribute;
2727
using TestMethod = FrameworkV1::Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute;
28+
using TestMethodV2 = FrameworkV2::Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute;
2829
using UTF = FrameworkV2::Microsoft.VisualStudio.TestTools.UnitTesting;
2930

3031
[TestClass]
@@ -529,6 +530,40 @@ public void GetTestFromMethodShouldSetDeclaringAssemblyName()
529530
Assert.AreEqual(otherAssemblyName, testElement.TestMethod.DeclaringAssemblyName);
530531
}
531532

533+
[TestMethod]
534+
public void GetTestFromMethodShouldSetDisplayNameToTestMethodNameIfDisplayNameIsNotPresent()
535+
{
536+
this.SetupTestClassAndTestMethods(isValidTestClass: true, isValidTestMethod: true, isMethodFromSameAssembly: true);
537+
TypeEnumerator typeEnumerator = this.GetTypeEnumeratorInstance(typeof(DummyTestClass), "DummyAssemblyName");
538+
var methodInfo = typeof(DummyTestClass).GetMethod(nameof(DummyTestClass.MethodWithVoidReturnType));
539+
540+
// Setup mocks to behave like we have [TestMethod] attribute on the method
541+
this.mockReflectHelper.Setup(
542+
rh => rh.GetCustomAttribute(It.IsAny<MemberInfo>(), It.IsAny<Type>())).Returns(new TestMethodV2());
543+
544+
var testElement = typeEnumerator.GetTestFromMethod(methodInfo, true, this.warnings);
545+
546+
Assert.IsNotNull(testElement);
547+
Assert.AreEqual("MethodWithVoidReturnType", testElement.DisplayName);
548+
}
549+
550+
[TestMethod]
551+
public void GetTestFromMethodShouldSetDisplayNameFromAttribute()
552+
{
553+
this.SetupTestClassAndTestMethods(isValidTestClass: true, isValidTestMethod: true, isMethodFromSameAssembly: true);
554+
TypeEnumerator typeEnumerator = this.GetTypeEnumeratorInstance(typeof(DummyTestClass), "DummyAssemblyName");
555+
var methodInfo = typeof(DummyTestClass).GetMethod(nameof(DummyTestClass.MethodWithVoidReturnType));
556+
557+
// Setup mocks to behave like we have [TestMethod("Test method display name.")] attribute on the method
558+
this.mockReflectHelper.Setup(
559+
rh => rh.GetCustomAttribute(methodInfo, typeof(TestMethodV2))).Returns(new TestMethodV2("Test method display name."));
560+
561+
var testElement = typeEnumerator.GetTestFromMethod(methodInfo, true, this.warnings);
562+
563+
Assert.IsNotNull(testElement);
564+
Assert.AreEqual("Test method display name.", testElement.DisplayName);
565+
}
566+
532567
#endregion
533568

534569
#region private methods

‎test/UnitTests/MSTest.CoreAdapter.Unit.Tests/Extensions/TestCaseExtensionsTests.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ public void ToUnitTestElementShouldReturnUnitTestElementWithFieldsSet()
3434
Assert.AreEqual(true, resultUnitTestElement.IsAsync);
3535
Assert.AreEqual(2, resultUnitTestElement.Priority);
3636
Assert.AreEqual(testCategories, resultUnitTestElement.TestCategory);
37-
Assert.AreEqual("DummyDisplayName", resultUnitTestElement.TestMethod.Name);
37+
Assert.AreEqual("DummyDisplayName", resultUnitTestElement.DisplayName);
38+
Assert.AreEqual("DummyMethod", resultUnitTestElement.TestMethod.Name);
3839
Assert.AreEqual("DummyClassName", resultUnitTestElement.TestMethod.FullClassName);
3940
Assert.AreEqual(true, resultUnitTestElement.TestMethod.IsAsync);
4041
Assert.IsNull(resultUnitTestElement.TestMethod.DeclaringClassFullName);

‎test/UnitTests/MSTest.CoreAdapter.Unit.Tests/ObjectModel/UnitTestElementTests.cs

+9
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,15 @@ public void ToTestCaseShouldSetDisplayName()
7676
Assert.AreEqual("M", testCase.DisplayName);
7777
}
7878

79+
[TestMethodV1]
80+
public void ToTestCaseShouldSetDisplayNameIfPresent()
81+
{
82+
this.unitTestElement.DisplayName = "Display Name";
83+
var testCase = this.unitTestElement.ToTestCase();
84+
85+
Assert.AreEqual("Display Name", testCase.DisplayName);
86+
}
87+
7988
[TestMethodV1]
8089
public void ToTestCaseShouldSetTestClassNameProperty()
8190
{

0 commit comments

Comments
 (0)