Skip to content

Commit d68079e

Browse files
authored
fix: run test for sln target (#13)
* fix: typo in WorkspaceBuildTargetsHandler.cs * test: add new test-project `mstest-sln-tests` * refactor: use ProjectGraph in BuildTargetTestHandler * fix: use new ProjectGraph for each build step * test: add test case for `mstest-sln-tests`
1 parent c630200 commit d68079e

File tree

14 files changed

+177
-39
lines changed

14 files changed

+177
-39
lines changed

src/bsp-server/BuildHelper.cs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,38 +3,38 @@
33
using dotnet_bsp.Logging;
44
using Microsoft.Build.Construction;
55
using Microsoft.Build.Evaluation;
6+
using Microsoft.Build.Execution;
67
using Microsoft.Build.Graph;
78

89
namespace dotnet_bsp;
910

1011
internal static class BuildHelper
1112
{
12-
internal static IEnumerable<BuildTargetIdentifier> FilterProjectsOutIfPartOfAnSolutionTarget(BuildTargetIdentifier[] targets)
13+
internal static IEnumerable<string> ExtractProjectsFromSolutions(BuildTargetIdentifier[] targets)
1314
{
14-
var filteredTargets = targets.ToList();
15-
var slnList = targets
16-
.Where(x => Path.GetExtension(x.ToString()) == ".sln");
1715
var projList = targets
1816
.Where(x => Path.GetExtension(x.ToString()) == ".csproj")
1917
.Select(x => x.Uri.AbsolutePath)
2018
.ToList();
19+
var slnList = targets
20+
.Where(x => Path.GetExtension(x.ToString()) == ".sln");
2121
foreach (var target in slnList)
2222
{
2323
var slnFile = SolutionFile.Parse(target.ToString());
2424
if (slnFile is not null)
2525
{
2626
var projectFilesInSln = slnFile.ProjectsInOrder
27+
.Where(x =>
28+
x.ProjectType is
29+
SolutionProjectType.KnownToBeMSBuildFormat or
30+
SolutionProjectType.WebProject)
2731
.Select(x => x.AbsolutePath);
28-
29-
var includedProj = projectFilesInSln
30-
.Intersect(projList);
31-
32-
filteredTargets
33-
.RemoveAll(x => includedProj.Contains(x.Uri.AbsolutePath));
32+
projList.AddRange(projectFilesInSln);
3433
}
3534
}
3635

37-
return filteredTargets;
36+
return projList
37+
.Distinct();
3838
}
3939

4040
internal static bool RestoreTestTargets(

src/bsp-server/Handlers/BuildTargetTestCaseDiscoveryHandler.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@ public Task<TestCaseDiscoveryResult> HandleRequestAsync(TestCaseDiscoveryParams
3636
var buildResult = true;
3737
var testCaseDiscoveryResult = true;
3838

39-
var targetFiles = BuildHelper.FilterProjectsOutIfPartOfAnSolutionTarget(testCaseDiscoveryParams.Targets)
40-
.Select(x => x.ToString());
39+
var targetFiles = BuildHelper.ExtractProjectsFromSolutions(testCaseDiscoveryParams.Targets);
4140
var initParams = _initializeManager.GetInitializeParams();
4241
if (initParams.RootUri.IsFile)
4342
{

src/bsp-server/Handlers/BuildTargetTestHandler.cs

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
using BaseProtocol;
22
using bsp4csharp.Protocol;
3-
using Microsoft.Build.Construction;
43
using Microsoft.Build.Evaluation;
54
using dotnet_bsp.Logging;
65
using Microsoft.TestPlatform.VsTestConsole.TranslationLayer;
76
using Microsoft.TestPlatform.VsTestConsole.TranslationLayer.Interfaces;
87
using TestResult = bsp4csharp.Protocol.TestResult;
9-
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client;
108
using Newtonsoft.Json.Linq;
119
using dotnet_bsp.EventHandlers;
1210
using System.Text.RegularExpressions;
11+
using Microsoft.Build.Graph;
12+
using Microsoft.Build.Execution;
1313

1414
namespace dotnet_bsp.Handlers;
1515

@@ -39,20 +39,13 @@ public Task<TestResult> HandleRequestAsync(TestParams testParams, RequestContext
3939

4040
if (initParams.RootUri.IsFile)
4141
{
42-
var projectTargets = new Dictionary<string, JObject?>();
43-
44-
var testTargetFiles = BuildHelper
45-
.FilterProjectsOutIfPartOfAnSolutionTarget(testParams.Targets)
46-
.Select(x => x.ToString());
42+
var workspacePath = initParams.RootUri.LocalPath;
43+
context.Logger.LogInformation("Get loaded test projects from {}", workspacePath);
4744

45+
var testTargetFiles = BuildHelper.ExtractProjectsFromSolutions(testParams.Targets);
4846
var projects = new ProjectCollection();
49-
foreach (var target in testTargetFiles)
50-
{
51-
HandleProject(testParams, projects, target, projectTargets);
52-
}
5347

54-
var workspacePath = initParams.RootUri.LocalPath;
55-
context.Logger.LogInformation("Get loaded test projects from {}", workspacePath);
48+
context.Logger.LogInformation("Projects in use {}", string.Join(",", testTargetFiles));
5649

5750
_baseProtocolClientManager.SendClearDiagnosticsMessage();
5851

@@ -75,16 +68,26 @@ public Task<TestResult> HandleRequestAsync(TestParams testParams, RequestContext
7568

7669
if (testResult)
7770
{
78-
foreach (var projectTarget in projectTargets)
71+
JObject? testParamsData = null;
72+
if (testParams.DataKind == TestParamsDataKinds.DotnetTest &&
73+
testParams.Data is JObject data)
74+
{
75+
testParamsData = data;
76+
}
77+
78+
var graph = new ProjectGraph(testTargetFiles, projects);
79+
var testProjects = graph.ProjectNodesTopologicallySorted
80+
.Where(x => x.ProjectInstance.IsTestProject());
81+
foreach (var testProject in testProjects)
7982
{
80-
var proj = projects.LoadProject(projectTarget.Key);
8183
msBuildLogger = new MSBuildLogger(_baseProtocolClientManager, testParams.OriginId, workspacePath);
8284

85+
var proj = testProject.ProjectInstance;
8386
context.Logger.LogInformation("Start test target: {}", proj.ProjectFileLocation);
8487
var targetPath = proj.Properties.First(x => x.Name == "TargetPath").EvaluatedValue;
8588
context.Logger.LogInformation("targetPath: {}", targetPath);
8689

87-
var dotnetTestParamsData = projectTarget.Value?.ToObject<DotnetTestParamsData>();
90+
var dotnetTestParamsData = testParamsData?.ToObject<DotnetTestParamsData>();
8891
if (dotnetTestParamsData is not null)
8992
{
9093
RunAllTests(proj, [targetPath], testParams.OriginId, dotnetTestParamsData.RunSettings, dotnetTestParamsData.Filter, context, msBuildLogger);
@@ -104,10 +107,9 @@ public Task<TestResult> HandleRequestAsync(TestParams testParams, RequestContext
104107
});
105108
}
106109

107-
private void HandleProject(TestParams testParams, ProjectCollection projects, string projectFile, Dictionary<string, JObject?> projectTargets)
110+
private void HandleTestProject(TestParams testParams, ProjectInstance project, Dictionary<string, JObject?> projectTargets)
108111
{
109-
var proj = projects.LoadProject(projectFile);
110-
if (!projectTargets.ContainsKey(proj.FullPath))
112+
if (project.IsTestProject() && !projectTargets.ContainsKey(project.FullPath))
111113
{
112114
JObject? testData = null;
113115
if (testParams.DataKind == TestParamsDataKinds.DotnetTest &&
@@ -116,11 +118,11 @@ private void HandleProject(TestParams testParams, ProjectCollection projects, st
116118
testData = data;
117119
}
118120

119-
projectTargets[proj.FullPath] = testData;
121+
projectTargets[project.FullPath] = testData;
120122
}
121123
}
122124

123-
private void RunAllTests(Project proj, IEnumerable<string> targets, string? originId, string? testRunSettings, string testCaseFilter, RequestContext context, MSBuildLogger msBuildLogger)
125+
private void RunAllTests(ProjectInstance proj, IEnumerable<string> targets, string? originId, string? testRunSettings, string testCaseFilter, RequestContext context, MSBuildLogger msBuildLogger)
124126
{
125127
var outputPath = proj.Properties.First(x => x.Name == "OutputPath").EvaluatedValue;
126128
context.Logger.LogInformation("outputPath: {}", outputPath);

src/bsp-server/Handlers/WorkspaceBuildTargetsHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public Task<WorkspaceBuildTargetsResult> HandleRequestAsync(RequestContext conte
3939
private IReadOnlyList<BuildTarget> GetBuildTargetsInWorkspace(string workspacePath, IBpLogger logger)
4040
{
4141
var list = new List<BuildTarget>();
42-
logger.LogInformation("Search solutin files in: {}", workspacePath);
42+
logger.LogInformation("Search solution files in: {}", workspacePath);
4343
//TODO: think about the implications to search for all sln files in workspace
4444
var slnFilePath = Directory
4545
.GetFiles(workspacePath, "*.sln")

src/bsp-server/TestRunner.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.Text.RegularExpressions;
22
using Microsoft.Build.Evaluation;
33
using BaseProtocol;
4+
using Microsoft.Build.Execution;
45

56
namespace dotnet_bsp;
67

@@ -69,6 +70,12 @@ public record SdkVersion(int Major, int Minor, int Patch, string DirPath);
6970
return FindTestAdapter(targetPath, context);
7071
}
7172

73+
public static string? FindTestAdapter(ProjectInstance proj, RequestContext context)
74+
{
75+
var targetPath = proj.Properties.First(x => x.Name == "TargetPath").EvaluatedValue;
76+
return FindTestAdapter(targetPath, context);
77+
}
78+
7279
public static string? FindTestAdapter(string targetPath, RequestContext context)
7380
{
7481
var targetDirectory = Path.GetDirectoryName(targetPath);
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.0.31903.59
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{0C88DD14-F956-CE84-757C-A364CCF449FC}"
7+
EndProject
8+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test1", "test\Test1\Test1.csproj", "{7425CFFD-664C-4C4A-AC46-F96240C07AAB}"
9+
EndProject
10+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{827E0CD3-B72D-47B6-A68D-7590B98EB39B}"
11+
EndProject
12+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FooApp", "src\FooApp\FooApp.csproj", "{C080B90C-CCE4-4116-8235-90E0185FB8B8}"
13+
EndProject
14+
Global
15+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
16+
Debug|Any CPU = Debug|Any CPU
17+
Debug|x64 = Debug|x64
18+
Debug|x86 = Debug|x86
19+
Release|Any CPU = Release|Any CPU
20+
Release|x64 = Release|x64
21+
Release|x86 = Release|x86
22+
EndGlobalSection
23+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
24+
{7425CFFD-664C-4C4A-AC46-F96240C07AAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
25+
{7425CFFD-664C-4C4A-AC46-F96240C07AAB}.Debug|Any CPU.Build.0 = Debug|Any CPU
26+
{7425CFFD-664C-4C4A-AC46-F96240C07AAB}.Debug|x64.ActiveCfg = Debug|Any CPU
27+
{7425CFFD-664C-4C4A-AC46-F96240C07AAB}.Debug|x64.Build.0 = Debug|Any CPU
28+
{7425CFFD-664C-4C4A-AC46-F96240C07AAB}.Debug|x86.ActiveCfg = Debug|Any CPU
29+
{7425CFFD-664C-4C4A-AC46-F96240C07AAB}.Debug|x86.Build.0 = Debug|Any CPU
30+
{7425CFFD-664C-4C4A-AC46-F96240C07AAB}.Release|Any CPU.ActiveCfg = Release|Any CPU
31+
{7425CFFD-664C-4C4A-AC46-F96240C07AAB}.Release|Any CPU.Build.0 = Release|Any CPU
32+
{7425CFFD-664C-4C4A-AC46-F96240C07AAB}.Release|x64.ActiveCfg = Release|Any CPU
33+
{7425CFFD-664C-4C4A-AC46-F96240C07AAB}.Release|x64.Build.0 = Release|Any CPU
34+
{7425CFFD-664C-4C4A-AC46-F96240C07AAB}.Release|x86.ActiveCfg = Release|Any CPU
35+
{7425CFFD-664C-4C4A-AC46-F96240C07AAB}.Release|x86.Build.0 = Release|Any CPU
36+
{C080B90C-CCE4-4116-8235-90E0185FB8B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
37+
{C080B90C-CCE4-4116-8235-90E0185FB8B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
38+
{C080B90C-CCE4-4116-8235-90E0185FB8B8}.Debug|x64.ActiveCfg = Debug|Any CPU
39+
{C080B90C-CCE4-4116-8235-90E0185FB8B8}.Debug|x64.Build.0 = Debug|Any CPU
40+
{C080B90C-CCE4-4116-8235-90E0185FB8B8}.Debug|x86.ActiveCfg = Debug|Any CPU
41+
{C080B90C-CCE4-4116-8235-90E0185FB8B8}.Debug|x86.Build.0 = Debug|Any CPU
42+
{C080B90C-CCE4-4116-8235-90E0185FB8B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
43+
{C080B90C-CCE4-4116-8235-90E0185FB8B8}.Release|Any CPU.Build.0 = Release|Any CPU
44+
{C080B90C-CCE4-4116-8235-90E0185FB8B8}.Release|x64.ActiveCfg = Release|Any CPU
45+
{C080B90C-CCE4-4116-8235-90E0185FB8B8}.Release|x64.Build.0 = Release|Any CPU
46+
{C080B90C-CCE4-4116-8235-90E0185FB8B8}.Release|x86.ActiveCfg = Release|Any CPU
47+
{C080B90C-CCE4-4116-8235-90E0185FB8B8}.Release|x86.Build.0 = Release|Any CPU
48+
EndGlobalSection
49+
GlobalSection(SolutionProperties) = preSolution
50+
HideSolutionNode = FALSE
51+
EndGlobalSection
52+
GlobalSection(NestedProjects) = preSolution
53+
{7425CFFD-664C-4C4A-AC46-F96240C07AAB} = {0C88DD14-F956-CE84-757C-A364CCF449FC}
54+
{C080B90C-CCE4-4116-8235-90E0185FB8B8} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
55+
EndGlobalSection
56+
EndGlobal
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net9.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
</PropertyGroup>
9+
10+
</Project>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// See https://aka.ms/new-console-template for more information
2+
Console.WriteLine("Hello, World!");
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[assembly: Parallelize(Scope = ExecutionScope.MethodLevel)]
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
namespace mstest_tests;
2+
3+
[TestClass]
4+
public sealed class Test1
5+
{
6+
[TestMethod]
7+
[DataRow("a")]
8+
[DataRow("b")]
9+
public void Test1_Success(string expectedValue)
10+
{
11+
Assert.AreEqual("a", expectedValue);
12+
}
13+
14+
[TestMethod]
15+
public void TestMethod2()
16+
{
17+
}
18+
}

0 commit comments

Comments
 (0)