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

Endpoints for running and debugging all tests in a class #1089

Merged
merged 16 commits into from
Jan 29, 2018
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/OmniSharp.Abstractions/OmniSharpEndpoints.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,11 @@ public static class V2

public const string GetTestStartInfo = "/v2/getteststartinfo";
public const string RunTest = "/v2/runtest";
public const string RunAllTestsInClass = "/v2/runtestsinclass";
public const string DebugTestGetStartInfo = "/v2/debugtest/getstartinfo";
public const string DebugTestLaunch = "/v2/debugtest/launch";
public const string DebugTestStop = "/v2/debugtest/stop";
public const string DebugTestsInClassGetStartInfo = "/v2/debugtestsinclass/getstartinfo";
}
}
}
5 changes: 4 additions & 1 deletion src/OmniSharp.DotNetTest/DebugSessionManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,13 @@ public void EndSession()
}

public Task<DebugTestGetStartInfoResponse> DebugGetStartInfoAsync(string methodName, string testFrameworkName, string targetFrameworkVersion, CancellationToken cancellationToken)
=> DebugGetStartInfoAsync(new string[] { methodName }, testFrameworkName, targetFrameworkVersion, cancellationToken);

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra blank line

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed that.

public Task<DebugTestGetStartInfoResponse> DebugGetStartInfoAsync(string[] methodNames, string testFrameworkName, string targetFrameworkVersion, CancellationToken cancellationToken)
{
VerifySession(isStarted: true);

return _testManager.DebugGetStartInfoAsync(methodName, testFrameworkName, targetFrameworkVersion, cancellationToken);
return _testManager.DebugGetStartInfoAsync(methodNames, testFrameworkName, targetFrameworkVersion, cancellationToken);
}

public async Task<DebugTestLaunchResponse> DebugLaunchAsync(int targetProcessId)
Expand Down
14 changes: 14 additions & 0 deletions src/OmniSharp.DotNetTest/Models/BaseTestClassRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using OmniSharp.Models;

namespace OmniSharp.DotNetTest.Models
{
public class BaseTestClassRequest : Request
{
public string[] MethodNames { get; set; }
public string TestFrameworkName { get; set; }
/// <summary>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Newline

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where ?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Above the doc comment

/// e.g. .NETCoreApp, Version=2.0
/// </summary>
public string TargetFrameworkVersion { get; set; }
}
}
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.DebugTestsInClassGetStartInfo, typeof(DebugTestClassGetStartInfoRequest), typeof(DebugTestGetStartInfoResponse))]
public class DebugTestClassGetStartInfoRequest : BaseTestClassRequest
{
}
}
10 changes: 10 additions & 0 deletions src/OmniSharp.DotNetTest/Models/RunTestInClassRequest.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.RunAllTestsInClass, typeof(RunTestsInClassRequest), typeof(RunTestResponse))]
public class RunTestsInClassRequest : BaseTestClassRequest
{
}
}
35 changes: 35 additions & 0 deletions src/OmniSharp.DotNetTest/Services/DebugTestClassService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System.Collections.Generic;
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.DebugTestsInClassGetStartInfo, LanguageNames.CSharp)]
class DebugTestClassService : BaseTestService,
IRequestHandler<DebugTestClassGetStartInfoRequest, DebugTestGetStartInfoResponse>
{
private DebugSessionManager _debugSessionManager;

[ImportingConstructor]
public DebugTestClassService(DebugSessionManager debugSessionManager, OmniSharpWorkspace workspace, DotNetCliService dotNetCli, IEventEmitter eventEmitter, ILoggerFactory loggerFactory)
: base(workspace, dotNetCli, eventEmitter, loggerFactory)
{
_debugSessionManager = debugSessionManager;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs a blank line.


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

return await _debugSessionManager.DebugGetStartInfoAsync(request.MethodNames, request.TestFrameworkName, request.TargetFrameworkVersion, CancellationToken.None);
}
}
}
37 changes: 37 additions & 0 deletions src/OmniSharp.DotNetTest/Services/RunTestsInClassService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System.Collections.Generic;
using System.Composition;
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.RunAllTestsInClass, LanguageNames.CSharp)]
internal class RunTestsInClassService : BaseTestService<RunTestsInClassRequest, RunTestResponse>
{
[ImportingConstructor]
public RunTestsInClassService(OmniSharpWorkspace workspace, DotNetCliService dotNetCli, IEventEmitter eventEmitter, ILoggerFactory loggerFactory)
: base(workspace, dotNetCli, eventEmitter, loggerFactory)
{
}

protected override RunTestResponse HandleRequest(RunTestsInClassRequest request, TestManager testManager)
{
if (testManager.IsConnected)
{
return testManager.RunTest(request.MethodNames, request.TestFrameworkName, request.TargetFrameworkVersion);
}

var response = new RunTestResponse
{
Failure = "Failed to connect to 'dotnet test' process",
Pass = false
};

return response;
}
}
}
12 changes: 12 additions & 0 deletions src/OmniSharp.DotNetTest/TestManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,21 @@ public static TestManager Create(Project project, DotNetCliService dotNetCli, IE
protected abstract void VersionCheck();

public abstract RunTestResponse RunTest(string methodName, string testFrameworkName, string targetFrameworkVersion);

public virtual RunTestResponse RunTest(string[] methodNames, string testFrameworkName, string targetFrameworkVersion)
{
throw new NotImplementedException();
}

public abstract GetTestStartInfoResponse GetTestStartInfo(string methodName, string testFrameworkName, string targetFrameworkVersion);

public abstract Task<DebugTestGetStartInfoResponse> DebugGetStartInfoAsync(string methodName, string testFrameworkName, string targetFrameworkVersion, CancellationToken cancellationToken);

public virtual Task<DebugTestGetStartInfoResponse> DebugGetStartInfoAsync(string[] methodNames, string testFrameworkName, string targetFrameworkVersion, CancellationToken cancellationToken)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What other types derive from TestManager? Should they implement this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's just two -- a legacy one for the old 'dotnet test' on project.json projects and the current 'dotnet vstest' version. I would only expect us to make this work for the newer stuff.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have implemented this function only for the VSTestManager and not LegacyTestManager. Is that required ?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the behavior if you open a project with legacy tests? Does the run tests button show up? If it does, and you click it, what happens?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A project with legacy tests == a project.json project. I don't think we should invest effort in that. So long as we don't break the ability to run/debug a single test in a project.json project, I don't think we need to make any changes to LegacyTestManager.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good. I'm happy with our solution of not showing the indicator for legacy projects.

{
throw new NotImplementedException();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing blank line.


public abstract Task DebugLaunchAsync(CancellationToken cancellationToken);

protected virtual bool PrepareToConnect()
Expand Down
21 changes: 14 additions & 7 deletions src/OmniSharp.DotNetTest/VSTestManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public override GetTestStartInfoResponse GetTestStartInfo(string methodName, str
{
VerifyTestFramework(testFrameworkName);

var testCases = DiscoverTests(methodName, targetFrameworkVersion);
var testCases = DiscoverTests(new string[] { methodName }, targetFrameworkVersion);

SendMessage(MessageType.GetTestRunnerProcessStartInfoForRunSelected,
new
Expand All @@ -127,10 +127,13 @@ public override GetTestStartInfoResponse GetTestStartInfo(string methodName, str
}

public override async Task<DebugTestGetStartInfoResponse> DebugGetStartInfoAsync(string methodName, string testFrameworkName, string targetFrameworkVersion, CancellationToken cancellationToken)
=> await DebugGetStartInfoAsync(new string[] { methodName }, testFrameworkName, targetFrameworkVersion, cancellationToken);

public override async Task<DebugTestGetStartInfoResponse> DebugGetStartInfoAsync(string[] methodNames, string testFrameworkName, string targetFrameworkVersion, CancellationToken cancellationToken)
{
VerifyTestFramework(testFrameworkName);

var testCases = await DiscoverTestsAsync(methodName, targetFrameworkVersion, cancellationToken);
var testCases = await DiscoverTestsAsync(methodNames, targetFrameworkVersion, cancellationToken);

SendMessage(MessageType.GetTestRunnerProcessStartInfoForRunSelected,
new
Expand Down Expand Up @@ -184,10 +187,13 @@ public override async Task DebugLaunchAsync(CancellationToken cancellationToken)
}

public override RunTestResponse RunTest(string methodName, string testFrameworkName, string targetFrameworkVersion)
=> RunTest(new string[] { methodName }, testFrameworkName, targetFrameworkVersion);

public override RunTestResponse RunTest(string[] methodNames, string testFrameworkName, string targetFrameworkVersion)
{
VerifyTestFramework(testFrameworkName);

var testCases = DiscoverTests(methodName, targetFrameworkVersion);
var testCases = DiscoverTests(methodNames, targetFrameworkVersion);

var testResults = new List<TestResult>();

Expand Down Expand Up @@ -244,7 +250,7 @@ public override RunTestResponse RunTest(string methodName, string testFrameworkN
};
}

private async Task<TestCase[]> DiscoverTestsAsync(string methodName, string targetFrameworkVersion, CancellationToken cancellationToken)
private async Task<TestCase[]> DiscoverTestsAsync(string[] methodNames, string targetFrameworkVersion, CancellationToken cancellationToken)
{
SendMessage(MessageType.StartDiscovery,
new
Expand All @@ -258,6 +264,7 @@ private async Task<TestCase[]> DiscoverTestsAsync(string methodName, string targ

var testCases = new List<TestCase>();
var done = false;
var hashset = new HashSet<string>(methodNames);

while (!done)
{
Expand Down Expand Up @@ -286,7 +293,7 @@ private async Task<TestCase[]> DiscoverTestsAsync(string methodName, string targ

testName = testName.Trim();

if (testName.Equals(methodName, StringComparison.Ordinal))
if (hashset.Contains(testName, StringComparer.Ordinal))
{
testCases.Add(testCase);
}
Expand All @@ -303,9 +310,9 @@ private async Task<TestCase[]> DiscoverTestsAsync(string methodName, string targ
return testCases.ToArray();
}

private TestCase[] DiscoverTests(string methodName, string targetFrameworkVersion)
private TestCase[] DiscoverTests(string[] methodNames, string targetFrameworkVersion)
{
return DiscoverTestsAsync(methodName, targetFrameworkVersion, CancellationToken.None).Result;
return DiscoverTestsAsync(methodNames, targetFrameworkVersion, CancellationToken.None).Result;
}
}
}