Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add test discovery and NoBuild option to test requests #1719

Merged
merged 12 commits into from
May 19, 2020
1 change: 1 addition & 0 deletions src/OmniSharp.Abstractions/OmniSharpEndpoints.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public static class V2
public const string DebugTestsInContextGetStartInfo = "/v2/debugtestsincontext/getstartinfo";
public const string DebugTestStop = "/v2/debugtest/stop";
public const string DebugTestsInClassGetStartInfo = "/v2/debugtestsinclass/getstartinfo";
public const string DiscoverTests = "/v2/discovertests";
public const string RunTestsInContext = "/v2/runtestsincontext";

public const string BlockStructure = "/v2/blockstructure";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
using OmniSharp.Models;
using OmniSharp.Models;

namespace OmniSharp.DotNetTest.Models
{
public class BaseTestClassRequest : Request
public class BaseTestRequest : Request
{
public string[] MethodNames { get; set; }
public string RunSettings { get; set; }
public string TestFrameworkName { get; set; }

/// <summary>
/// e.g. .NETCoreApp, Version=2.0
/// </summary>
public string TargetFrameworkVersion { get; set; }
public bool NoBuild { get; set; } = false;
}

public class SingleTestRequest : BaseTestRequest
{
public string MethodName { get; set; }
}

public class MultiTestRequest : BaseTestRequest
{
public string[] MethodNames { get; set; }
}
}
2 changes: 2 additions & 0 deletions src/OmniSharp.DotNetTest/Models/BaseTestsInContextRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,7 @@ public abstract class BaseTestsInContextRequest : Request
/// e.g. .NETCoreApp, Version=2.0
/// </summary>
public string? TargetFrameworkVersion { get; set; }

public bool NoBuild { get; set; } = false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
namespace OmniSharp.DotNetTest.Models
{
[OmniSharpEndpoint(OmniSharpEndpoints.V2.DebugTestsInClassGetStartInfo, typeof(DebugTestClassGetStartInfoRequest), typeof(DebugTestGetStartInfoResponse))]
public class DebugTestClassGetStartInfoRequest : BaseTestClassRequest
public class DebugTestClassGetStartInfoRequest : MultiTestRequest
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,7 @@
namespace OmniSharp.DotNetTest.Models
{
[OmniSharpEndpoint(OmniSharpEndpoints.V2.DebugTestGetStartInfo, typeof(DebugTestGetStartInfoRequest), typeof(DebugTestGetStartInfoResponse))]
public class DebugTestGetStartInfoRequest : Request
public class DebugTestGetStartInfoRequest : SingleTestRequest
{
public string MethodName { get; set; }
public string RunSettings { get; set; }
public string TestFrameworkName { get; set; }
/// <summary>
/// e.g. .NETCoreApp, Version=2.0
/// </summary>
public string TargetFrameworkVersion { get; set; }
}
}
10 changes: 10 additions & 0 deletions src/OmniSharp.DotNetTest/Models/DiscoverTestsRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using OmniSharp.Mef;
using OmniSharp.Models;

namespace OmniSharp.DotNetTest.Models
{
[OmniSharpEndpoint(OmniSharpEndpoints.V2.DiscoverTests, typeof(DiscoverTestsRequest), typeof(DiscoverTestsResponse))]
public class DiscoverTestsRequest : BaseTestRequest
{
}
}
20 changes: 20 additions & 0 deletions src/OmniSharp.DotNetTest/Models/DiscoverTestsResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace OmniSharp.DotNetTest.Models
{
public class Test
{
public string FullyQualifiedName { get; set; }

public string DisplayName { get; set; }

public string Source { get; set; }

public string CodeFilePath { get; set; }

public int LineNumber { get; set; }
}

public class DiscoverTestsResponse
{
public Test[] Tests { get; set; }
}
}
9 changes: 1 addition & 8 deletions src/OmniSharp.DotNetTest/Models/GetTestStartInfoRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,7 @@
namespace OmniSharp.DotNetTest.Models
{
[OmniSharpEndpoint(OmniSharpEndpoints.V2.GetTestStartInfo, typeof(GetTestStartInfoRequest), typeof(GetTestStartInfoResponse))]
public class GetTestStartInfoRequest : Request
public class GetTestStartInfoRequest : SingleTestRequest
{
public string MethodName { get; set; }
public string RunSettings { get; set; }
public string TestFrameworkName { get; set; }
/// <summary>
/// e.g. .NETCoreApp, Version=2.0
/// </summary>
public string TargetFrameworkVersion { get; set; }
}
}
2 changes: 1 addition & 1 deletion src/OmniSharp.DotNetTest/Models/RunTestInClassRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
namespace OmniSharp.DotNetTest.Models
{
[OmniSharpEndpoint(OmniSharpEndpoints.V2.RunAllTestsInClass, typeof(RunTestsInClassRequest), typeof(RunTestResponse))]
public class RunTestsInClassRequest : BaseTestClassRequest
public class RunTestsInClassRequest : MultiTestRequest
{
}
}
9 changes: 1 addition & 8 deletions src/OmniSharp.DotNetTest/Models/RunTestRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,7 @@
namespace OmniSharp.DotNetTest.Models
{
[OmniSharpEndpoint(OmniSharpEndpoints.V2.RunTest, typeof(RunTestRequest), typeof(RunTestResponse))]
public class RunTestRequest : Request
public class RunTestRequest : SingleTestRequest
{
public string MethodName { get; set; }
public string RunSettings { get; set; }
public string TestFrameworkName { get; set; }
/// <summary>
/// e.g. .NETCoreApp, Version=2.0
/// </summary>
public string TargetFrameworkVersion { get; set; }
}
}
4 changes: 2 additions & 2 deletions src/OmniSharp.DotNetTest/Services/BaseTestService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ protected BaseTestService(OmniSharpWorkspace workspace, IDotNetCliService dotNet
LoggerFactory = loggerFactory;
}

protected TestManager CreateTestManager(string fileName)
protected TestManager CreateTestManager(string fileName, bool noBuild)
{
var document = Workspace.GetDocument(fileName);

return TestManager.Start(document.Project, DotNetCli, EventEmitter, LoggerFactory);
return TestManager.Start(document.Project, DotNetCli, EventEmitter, LoggerFactory, noBuild);
}
}
}
9 changes: 6 additions & 3 deletions src/OmniSharp.DotNetTest/Services/BaseTestService`2.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.Extensions.Logging;
using OmniSharp.DotNetTest.Models;
using OmniSharp.Eventing;
using OmniSharp.Mef;
using OmniSharp.Models;
Expand All @@ -10,7 +11,7 @@ namespace OmniSharp.DotNetTest.Services
{
[OmniSharpHandler(OmniSharpEndpoints.V2.GetTestStartInfo, LanguageNames.CSharp)]
internal abstract class BaseTestService<TRequest, TResponse> : BaseTestService, IRequestHandler<TRequest, TResponse>
where TRequest: Request
where TRequest: BaseTestRequest
{
protected BaseTestService(OmniSharpWorkspace workspace, IDotNetCliService dotNetCli, IEventEmitter eventEmitter, ILoggerFactory loggerFactory)
: base(workspace, dotNetCli, eventEmitter, loggerFactory)
Expand All @@ -21,8 +22,10 @@ protected BaseTestService(OmniSharpWorkspace workspace, IDotNetCliService dotNet

public async Task<TResponse> Handle(TRequest request)
{
using var testManager = CreateTestManager(request.FileName);
return await HandleRequest(request, testManager);
using (var testManager = CreateTestManager(request.FileName, request.NoBuild))
{
return await HandleRequest(request, testManager);
}
}
}
}
2 changes: 1 addition & 1 deletion src/OmniSharp.DotNetTest/Services/DebugTestClassService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public DebugTestClassService(DebugSessionManager debugSessionManager, OmniSharpW

public async Task<DebugTestGetStartInfoResponse> Handle(DebugTestClassGetStartInfoRequest request)
{
var testManager = CreateTestManager(request.FileName);
var testManager = CreateTestManager(request.FileName, request.NoBuild);
_debugSessionManager.StartSession(testManager);

return await _debugSessionManager.DebugGetStartInfoAsync(request.MethodNames, request.RunSettings, request.TestFrameworkName, request.TargetFrameworkVersion, CancellationToken.None);
Expand Down
2 changes: 1 addition & 1 deletion src/OmniSharp.DotNetTest/Services/DebugTestService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public DebugTestService(DebugSessionManager debugSessionManager, OmniSharpWorksp

public Task<DebugTestGetStartInfoResponse> Handle(DebugTestGetStartInfoRequest request)
{
var testManager = CreateTestManager(request.FileName);
var testManager = CreateTestManager(request.FileName, request.NoBuild);
if (testManager.IsConnected)
{
//only if the test manager connected successfully, shall we proceed with the request
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public async Task<DebugTestGetStartInfoResponse> Handle(DebugTestsInContextGetSt
};
}

testManager.Connect();
testManager.Connect(request.NoBuild);

if (testManager.IsConnected)
{
Expand Down
33 changes: 33 additions & 0 deletions src/OmniSharp.DotNetTest/Services/DiscoverTestsService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System;
using System.Composition;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.Extensions.Logging;
using OmniSharp.DotNetTest.Models;
using OmniSharp.Eventing;
using OmniSharp.Mef;
using OmniSharp.Services;

namespace OmniSharp.DotNetTest.Services
{
[OmniSharpHandler(OmniSharpEndpoints.V2.DiscoverTests, LanguageNames.CSharp)]
internal class DiscoverTestsService : BaseTestService<DiscoverTestsRequest, DiscoverTestsResponse>
{
[ImportingConstructor]
public DiscoverTestsService(OmniSharpWorkspace workspace, IDotNetCliService dotNetCli, IEventEmitter eventEmitter, ILoggerFactory loggerFactory)
: base(workspace, dotNetCli, eventEmitter, loggerFactory)
{
}

protected override async Task<DiscoverTestsResponse> HandleRequest(DiscoverTestsRequest request, TestManager testManager)
{
if (testManager.IsConnected)
{
return await testManager.DiscoverTestsAsync(request.RunSettings, request.TestFrameworkName, request.TargetFrameworkVersion, default(CancellationToken));
}

throw new InvalidOperationException("The debugger could not be started");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public async Task<RunTestResponse> Handle(RunTestsInContextRequest request)
};
}

testManager.Connect();
testManager.Connect(request.NoBuild);

if (testManager.IsConnected)
{
Expand Down
12 changes: 7 additions & 5 deletions src/OmniSharp.DotNetTest/TestManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ protected TestManager(Project project, string workingDirectory, IDotNetCliServic
Logger = logger ?? throw new ArgumentNullException(nameof(logger));
}

public static TestManager Start(Project project, IDotNetCliService dotNetCli, IEventEmitter eventEmitter, ILoggerFactory loggerFactory)
public static TestManager Start(Project project, IDotNetCliService dotNetCli, IEventEmitter eventEmitter, ILoggerFactory loggerFactory, bool noBuild)
{
var manager = Create(project, dotNetCli, eventEmitter, loggerFactory);
manager.Connect();
manager.Connect(noBuild);
return manager;
}

Expand Down Expand Up @@ -82,6 +82,8 @@ public static TestManager Create(Project project, IDotNetCliService dotNetCli, I

public abstract Task<RunTestResponse> RunTestAsync(string[] methodNames, string runSettings, string testFrameworkName, string targetFrameworkVersion, CancellationToken cancellationToken);

public abstract Task<DiscoverTestsResponse> DiscoverTestsAsync(string runSettings, string testFrameworkName, string targetFrameworkVersion, CancellationToken cancellationToken);

public abstract Task<GetTestStartInfoResponse> GetTestStartInfoAsync(string methodName, string runSettings, string testFrameworkName, string targetFrameworkVersion, CancellationToken cancellationToken);

public abstract Task<DebugTestGetStartInfoResponse> DebugGetStartInfoAsync(string methodName, string runSettings, string testFrameworkName, string targetFrameworkVersion, CancellationToken cancellationToken);
Expand All @@ -90,20 +92,20 @@ public static TestManager Create(Project project, IDotNetCliService dotNetCli, I

public abstract Task DebugLaunchAsync(CancellationToken cancellationToken);

protected virtual bool PrepareToConnect()
protected virtual bool PrepareToConnect(bool noBuild)
{
// Descendents can override.
return true;
}

internal void Connect()
internal void Connect(bool noBuild)
{
if (_isConnected)
{
throw new InvalidOperationException("Already connected.");
}

if (!PrepareToConnect())
if (!PrepareToConnect(noBuild))
{
return;
}
Expand Down
33 changes: 29 additions & 4 deletions src/OmniSharp.DotNetTest/VSTestManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,13 @@ protected override void VersionCheck()
}
}

protected override bool PrepareToConnect()
protected override bool PrepareToConnect(bool noBuild)
{
if (noBuild)
{
return true;
}

// The project must be built before we can test.
var arguments = "build";

Expand Down Expand Up @@ -122,6 +127,22 @@ private static void VerifyTestFramework(string testFrameworkName)
}
}

public override async Task<DiscoverTestsResponse> DiscoverTestsAsync(string runSettings, string testFrameworkName, string targetFrameworkVersion, CancellationToken cancellationToken)
{
var testCases = await DiscoverTestsAsync(null, runSettings, targetFrameworkVersion, cancellationToken);
return new DiscoverTestsResponse
{
Tests = testCases.Select(o => new Test
{
FullyQualifiedName = o.FullyQualifiedName,
DisplayName = o.DisplayName,
Source = o.Source,
CodeFilePath = o.CodeFilePath,
LineNumber = o.LineNumber
}).ToArray()
};
}

public override async Task<GetTestStartInfoResponse> GetTestStartInfoAsync(string methodName, string runSettings, string testFrameworkName, string targetFrameworkVersion, CancellationToken cancellationToken)
{
VerifyTestFramework(testFrameworkName);
Expand Down Expand Up @@ -411,7 +432,11 @@ private async Task<TestCase[]> DiscoverTestsAsync(string[] methodNames, string r

var testCases = new List<TestCase>();
var done = false;
var hashset = new HashSet<string>(methodNames);
HashSet<string> hashset = null;
if (methodNames != null)
{
hashset = new HashSet<string>(methodNames);
}

while (!done)
{
Expand All @@ -429,14 +454,14 @@ private async Task<TestCase[]> DiscoverTestsAsync(string[] methodNames, string r

case MessageType.TestCasesFound:
var foundTestCases = message.DeserializePayload<TestCase[]>();
testCases.AddRange(foundTestCases.Where(isInRequestedMethods));
testCases.AddRange(methodNames != null ? foundTestCases.Where(isInRequestedMethods) : foundTestCases);
break;

case MessageType.DiscoveryComplete:
var lastDiscoveredTests = message.DeserializePayload<DiscoveryCompletePayload>().LastDiscoveredTests;
if (lastDiscoveredTests != null)
{
testCases.AddRange(lastDiscoveredTests.Where(isInRequestedMethods));
testCases.AddRange(methodNames != null ? lastDiscoveredTests.Where(isInRequestedMethods) : lastDiscoveredTests);
}

done = true;
Expand Down
Loading