diff --git a/src/OmniSharp.DotNetTest/VSTestManager.cs b/src/OmniSharp.DotNetTest/VSTestManager.cs index 95fd9c8efa..ce36b91896 100644 --- a/src/OmniSharp.DotNetTest/VSTestManager.cs +++ b/src/OmniSharp.DotNetTest/VSTestManager.cs @@ -334,8 +334,32 @@ bool isInRequestedMethods(TestCase testCase) } testName = testName.Trim(); + + // Discovered tests in generic classes come back in the form `Namespace.GenericClass.TestName` + // however requested test names are sent from the IDE in the form of `Namespace.GenericClass`1.TestName` + // to compensate we format each part of the discovered test name to match what the IDE would send. + testName = string.Join(".", testName.Split('.').Select(FormatAsMetadata)); + return hashset.Contains(testName, StringComparer.Ordinal); }; + + static string FormatAsMetadata(string name) + { + if (!name.EndsWith(">")) + { + return name; + } + + var genericParamStart = name.IndexOf('<'); + if (genericParamStart < 0) + { + return name; + } + + var genericParams = name.Substring(genericParamStart, name.Length - genericParamStart - 1); + var paramCount = genericParams.Split(',').Length; + return $"{name.Substring(0, genericParamStart)}`{paramCount}"; + } } private TestCase[] DiscoverTests(string[] methodNames, string runSettings, string targetFrameworkVersion) diff --git a/test-assets/test-projects/NUnitTestProject/TestProgram.cs b/test-assets/test-projects/NUnitTestProject/TestProgram.cs index 493c2471e6..26100a855c 100644 --- a/test-assets/test-projects/NUnitTestProject/TestProgram.cs +++ b/test-assets/test-projects/NUnitTestProject/TestProgram.cs @@ -42,7 +42,7 @@ public void CheckStandardOutput() { int a = 1, b = 1; Console.WriteLine($"a = {a}, b = {b}"); - Assert.AreEqual(a,b); + Assert.AreEqual(a, b); } public void UtilityFunction() @@ -52,4 +52,15 @@ public void UtilityFunction() private static int[] _items = new int[1] { 1 }; } + + [TestFixture(typeof(int))] + [TestFixture(typeof(double))] + public class GenericTest + { + [Test] + public void TypedTest() + { + Assert.NotNull(default(T)); + } + } } diff --git a/tests/OmniSharp.DotNetTest.Tests/RunTestFacts.cs b/tests/OmniSharp.DotNetTest.Tests/RunTestFacts.cs index 868a2780f8..e4a9a707c7 100644 --- a/tests/OmniSharp.DotNetTest.Tests/RunTestFacts.cs +++ b/tests/OmniSharp.DotNetTest.Tests/RunTestFacts.cs @@ -167,6 +167,18 @@ public async Task RunNunitStandardOutputIsReturned() Assert.NotEmpty(response.Results[0].StandardOutput); } + [Fact] + public async Task RunNunitTypedTestRunsTwice() + { + var response = await RunDotNetTestAsync( + NUnitTestProject, + methodName: "Main.Test.GenericTest`1.TypedTest", + testFramework: "nunit", + shouldPass: true); + + Assert.Equal(2, response.Results.Length); + } + [Fact] public async Task RunMSTestTest() { diff --git a/tests/OmniSharp.DotNetTest.Tests/TestDiscoveryFacts.cs b/tests/OmniSharp.DotNetTest.Tests/TestDiscoveryFacts.cs index 5cb59a736e..ed14749a90 100644 --- a/tests/OmniSharp.DotNetTest.Tests/TestDiscoveryFacts.cs +++ b/tests/OmniSharp.DotNetTest.Tests/TestDiscoveryFacts.cs @@ -44,6 +44,7 @@ public TestDiscoveryFacts(ITestOutputHelper output) [InlineData(NUnitTestProject, TestProgram, 28, 20, true, nunit, NUnitTestMethod, "Main.Test.MainTest.SourceDataDrivenTest")] [InlineData(NUnitTestProject, TestProgram, 34, 20, true, nunit, NUnitTestMethod, "Main.Test.MainTest.FailingTest")] [InlineData(NUnitTestProject, TestProgram, 47, 20, false, "", "", "")] + [InlineData(NUnitTestProject, TestProgram, 60, 20, true, nunit, NUnitTestMethod, "Main.Test.GenericTest`1.TypedTest")] public async Task FindTestMethods(string projectName, string fileName, int line, int column, bool expectToFind, string expectedTestFramework, string expectedFeatureName, string expectedMethodName) { using (var testProject = await this._testAssets.GetTestProjectAsync(projectName))