/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Features/CSharpTest/Testing/CSharpTestMethodFinderTests.cs
499 строк
15 KB
Cyrus Najmabadi
Make tests synchronous
08 июл 2025, 22:11
08 июл 2025, 22:11
542bfda
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Features.Testing; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.CodeAnalysis.Text; using Roslyn.Test.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests; [UseExportProvider] public sealed class CSharpTestMethodFinderTests { #region Xunit [Fact] public Task TestFindsXUnitFactMethod() => TestXunitAsync(""" using Xunit; public class TestClass { [Fact] public void Test$$Method1() { } } """, "TestMethod1"); [Fact] public Task TestMatchesXUnitFactInInnerClassMethod() => TestXunitMatchAsync(""" using Xunit; public class OuterClass { [Fact] public void TestMethod1() { } public class InnerClass { [Fact] public void Test$$Method2() { } } } """, "OuterClass+InnerClass.TestMethod2"); [Fact] public Task TestMatchesXUnitFactInOuterClassMethod() => TestXunitMatchAsync(""" using Xunit; public class OuterClass { [Fact] public void Test$$Method1() { } public class InnerClass { [Fact] public void TestMethod2() { } } } """, "OuterClass.TestMethod1"); [Fact] public Task TestFindsXUnitFactAttributeMethod() => TestXunitAsync(""" using Xunit; public class TestClass { [FactAttribute] public void Test$$Method1() { } } """, "TestMethod1"); [Fact] public Task TestFindsXUnitTheoryMethod() => TestXunitAsync(""" using Xunit; public class TestClass { [Theory] public void Test$$Method1() { } } """, "TestMethod1"); [Fact] public Task TestFindsXUnitTheoryAttributeMethod() => TestXunitAsync(""" using Xunit; public class TestClass { [TheoryAttribute] public void Test$$Method1() { } } """, "TestMethod1"); [Fact] public Task TestFindsXUnitAliasedFactMethod() => TestXunitAsync(""" using Xunit; using test = Xunit.FactAttribute; public class TestClass { [test] public void Test$$Method1() { } } """); [Fact] public Task TestFindsXUnitFactOnlySelectedMethod() => TestXunitAsync(""" using Xunit; public class TestClass { [Fact] public void Test$$Method1() { } [Fact] public void TestMethod2() { } public void NotTestMethod() { } } """, "TestMethod1"); [Fact] public Task TestFindsXunitMethodsInClassMethod() => TestXunitAsync(""" using Xunit; public class Test$$Class { [Fact] public void TestMethod1() { } [Fact] public void TestMethod2() { } [Theory] public void TestMethod3() { } public void NotTestMethod() { } } """, "TestMethod1", "TestMethod2", "TestMethod3"); [Fact] public Task TestXunitNoMethodsInClass() => TestXunitAsync(""" using Xunit; public class Test$$Class { public void NotTestMethod() { } } """); [Fact] public Task TestFindsSelectedXunitMethods() => TestXunitAsync(""" using Xunit; public class TestClass { [Fact] [|public void TestMethod1() { } [Fact] public void TestMethod2()|] { } [Theory] public void TestMethod3() { } public void NotTestMethod() { } } """, "TestMethod1", "TestMethod2"); #endregion #region NUnit [Fact] public Task TestFindsNUnitTestMethod() => TestNUnitAsync(""" using NUnit.Framework; public class TestClass { [Test] public void Test$$Method1() { } } """, "TestMethod1"); [Fact] public Task TestFindsNUnitTestAttributeMethod() => TestNUnitAsync(""" using NUnit.Framework; public class TestClass { [TestAttribute] public void Test$$Method1() { } } """, "TestMethod1"); [Fact] public Task TestFindsNUnitTheoryMethod() => TestNUnitAsync(""" using NUnit.Framework; public class TestClass { [Theory] public void Test$$Method1() { } } """, "TestMethod1"); [Fact] public Task TestFindsNUnitTheoryAttributeMethod() => TestNUnitAsync(""" using NUnit.Framework; public class TestClass { [TheoryAttribute] public void Test$$Method1() { } } """, "TestMethod1"); [Fact] public Task TestFindsNUnitTestCaseMethod() => TestNUnitAsync(""" using NUnit.Framework; public class TestClass { [TestCase] public void Test$$Method1() { } } """, "TestMethod1"); [Fact] public Task TestFindsNUnitTestCaseAttributeMethod() => TestNUnitAsync(""" using NUnit.Framework; public class TestClass { [TestCaseAttribute] public void Test$$Method1() { } } """, "TestMethod1"); [Fact] public Task TestFindsNUnitTestCaseSourceMethod() => TestNUnitAsync(""" using NUnit.Framework; public class TestClass { public static string s_s = ""; [TestCaseSource(nameof(s_s))] public void Test$$Method1() { } } """, "TestMethod1"); [Fact] public Task TestFindsNUnitTestCaseSourceAttributeMethod() => TestNUnitAsync(""" using NUnit.Framework; public class TestClass { public static string s_s = ""; [TestCaseSourceAttribute(nameof(s_s))] public void Test$$Method1() { } } """, "TestMethod1"); [Fact] public Task TestFindsNUnitMethodsInClass() => TestNUnitAsync(""" using NUnit.Framework; public class Test$$Class { [Test] public void TestMethod1() { } [Theory] public void TestMethod2() { } [TestCase] public void TestMethod3() { } public static string s_s = ""; [TestCaseSource(nameof(s_s))] public void TestMethod4() { } public void NotTestMethod() { } } """, "TestMethod1", "TestMethod2", "TestMethod3", "TestMethod4"); #endregion #region MSTest [Fact] public Task TestFindsMSTestTestMethod() => TestMSTestAsync(""" using Microsoft.VisualStudio.TestTools.UnitTesting; public class TestClass { [TestMethod] public void Test$$Method1() { } } """, "TestMethod1"); [Fact] public Task TestFindsMSTestTestMethodAttribute() => TestMSTestAsync(""" using Microsoft.VisualStudio.TestTools.UnitTesting; public class TestClass { [TestMethodAttribute] public void Test$$Method1() { } } """, "TestMethod1"); [Fact] public Task TestFindsMSTestMethodsInClass() => TestMSTestAsync(""" using Microsoft.VisualStudio.TestTools.UnitTesting; public class Test$$Class { [TestMethod] public void TestMethod1() { } [TestMethod] public void TestMethod2() { } public void NotTestMethod() { } } """, "TestMethod1", "TestMethod2"); #endregion [Fact] public Task TestFindsTestMethodInBlockScopedNamespace() => TestXunitAsync(""" namespace BlockScoped { using Xunit; public class TestClass { [Fact] public void Test$$Method1() { } } } """, "TestMethod1"); [Fact] public Task TestFindsTestMethodInFileScopedNamespace() => TestXunitAsync(""" namespace FileScoped; using Xunit; public class TestClass { [Fact] public void Test$$Method1() { } } """, "TestMethod1"); [Fact] public Task TestFindsTestMethodInStruct() => TestXunitAsync(""" using Xunit; public struct TestClass { [Fact] public void Test$$Method1() { } } """, "TestMethod1"); [Fact] public Task TestFindsTestMethodInPartialClass() => TestXunitAsync(""" using Xunit; public partial class PartialClass { [Fact] public void Test$$Method1() { } } public partial class PartialClass { [Fact] public void TestMethod2() { } } """, "TestMethod1"); private static Task TestXunitAsync(string code, params string[] expectedTestNames) { return TestAsync(code, """ using System; namespace Xunit { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public class FactAttribute : Attribute { } [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public class TheoryAttribute : FactAttribute { } } """, expectedTestNames); } private static Task TestXunitMatchAsync(string code, params string[] expectedQualifiedTestNames) { return TestMatchAsync(code, """ using System; namespace Xunit { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public class FactAttribute : Attribute { } [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public class TheoryAttribute : FactAttribute { } } """, expectedQualifiedTestNames); } private static Task TestNUnitAsync(string code, params string[] expectedTestNames) { return TestAsync(code, """ using System; namespace NUnit.Framework { [AttributeUsage(AttributeTargets.Method, AllowMultiple=false, Inherited=true)] public class TestAttribute : Attribute { } [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited=true)] public class TheoryAttribute : Attribute { } [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited=false)] public class TestCaseAttribute : Attribute { } [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = false)] public class TestCaseSourceAttribute : Attribute { public TestCaseSourceAttribute(string sourceName) { } } } """, expectedTestNames); } private static Task TestMSTestAsync(string code, params string[] expectedTestNames) { return TestAsync(code, """ using System; namespace Microsoft.VisualStudio.TestTools.UnitTesting { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public class TestMethodAttribute : Attribute { } } """, expectedTestNames); } private static async Task TestAsync(string code, string testAttributeDefinitionsCode, params string[] expectedTestNames) { var workspace = TestWorkspace.CreateCSharp([code, testAttributeDefinitionsCode]); var testDocument = workspace.Documents.First(); var span = testDocument.CursorPosition != null ? new TextSpan(testDocument.CursorPosition.Value, 0) : testDocument.SelectedSpans.Single(); var testMethodFinder = workspace.CurrentSolution.Projects.Single().GetRequiredLanguageService<ITestMethodFinder>(); var testMethods = await testMethodFinder.GetPotentialTestMethodsAsync(workspace.CurrentSolution.GetRequiredDocument(testDocument.Id), span, CancellationToken.None); var testMethodNames = testMethods.Cast<MethodDeclarationSyntax>().Select(m => m.Identifier.Text).ToArray(); AssertEx.Equal(expectedTestNames, testMethodNames); } private static async Task TestMatchAsync(string code, string testAttributeDefinitionsCode, params string[] expectedTestNames) { var workspace = TestWorkspace.CreateCSharp([code, testAttributeDefinitionsCode]); var testDocument = workspace.Documents.First(); var span = testDocument.CursorPosition != null ? new TextSpan(testDocument.CursorPosition.Value, 0) : testDocument.SelectedSpans.Single(); var testMethodFinder = workspace.CurrentSolution.Projects.Single().GetRequiredLanguageService<ITestMethodFinder>(); var testMethods = await testMethodFinder.GetPotentialTestMethodsAsync(workspace.CurrentSolution.GetRequiredDocument(testDocument.Id), span, CancellationToken.None); var semanticModel = await workspace.CurrentSolution.GetRequiredDocument(testDocument.Id).GetRequiredSemanticModelAsync(CancellationToken.None); List<string> unmatchedTestNames = []; foreach (var expectedTestName in expectedTestNames) { var matchFound = testMethods.Any(m => testMethodFinder.IsMatch(semanticModel, m, expectedTestName, CancellationToken.None)); if (!matchFound) { unmatchedTestNames.Add(expectedTestName); } } Assert.True(unmatchedTestNames.Count == 0, $"Unable to match the following test names: {string.Join(", ", unmatchedTestNames)}"); } }