Added an ITestRunnerResolverFactory that decides on which resolver to use based on the set of parameters received.

This commit is contained in:
Livar Cunha 2016-08-22 21:29:14 -07:00
parent 8e432e567a
commit 0667e84069
10 changed files with 184 additions and 29 deletions

View file

@ -0,0 +1,10 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Microsoft.DotNet.ProjectModel
{
public interface IProjectReader
{
Project ReadProject(string projectPath, ProjectReaderSettings settings = null);
}
}

View file

@ -15,7 +15,7 @@ using NuGet.Versioning;
namespace Microsoft.DotNet.ProjectModel namespace Microsoft.DotNet.ProjectModel
{ {
public class ProjectReader public class ProjectReader : IProjectReader
{ {
public static bool TryGetProject(string path, out Project project, ProjectReaderSettings settings = null) public static bool TryGetProject(string path, out Project project, ProjectReaderSettings settings = null)
{ {
@ -63,6 +63,11 @@ namespace Microsoft.DotNet.ProjectModel
} }
public static Project GetProject(string projectPath, ProjectReaderSettings settings = null) public static Project GetProject(string projectPath, ProjectReaderSettings settings = null)
{
return new ProjectReader().ReadProject(projectPath, settings);
}
public Project ReadProject(string projectPath, ProjectReaderSettings settings)
{ {
projectPath = ProjectPathHelper.NormalizeProjectFilePath(projectPath); projectPath = ProjectPathHelper.NormalizeProjectFilePath(projectPath);
@ -70,7 +75,7 @@ namespace Microsoft.DotNet.ProjectModel
using (var stream = new FileStream(projectPath, FileMode.Open, FileAccess.Read, FileShare.Read)) using (var stream = new FileStream(projectPath, FileMode.Open, FileAccess.Read, FileShare.Read))
{ {
return new ProjectReader().ReadProject(stream, name, projectPath, settings); return ReadProject(stream, name, projectPath, settings);
} }
} }

View file

@ -35,7 +35,7 @@ namespace Microsoft.DotNet.Tools.Test
{ {
$"--configuration", $"--configuration",
dotnetTestParams.Config, dotnetTestParams.Config,
$"{dotnetTestParams.ProjectPath}" $"{dotnetTestParams.ProjectOrAssemblyPath}"
}; };
// Build the test specifically for the target framework \ rid of the ProjectContext. This avoids building the project // Build the test specifically for the target framework \ rid of the ProjectContext. This avoids building the project

View file

@ -23,8 +23,9 @@ namespace Microsoft.DotNet.Tools.Test
private CommandOption _configurationOption; private CommandOption _configurationOption;
private CommandOption _portOption; private CommandOption _portOption;
private CommandOption _parentProcessIdOption; private CommandOption _parentProcessIdOption;
private CommandArgument _projectPath; private CommandArgument _projectOrAssemblyPath;
private CommandOption _noBuildOption; private CommandOption _noBuildOption;
private CommandOption _testRunner;
public int? Port { get; set; } public int? Port { get; set; }
@ -38,7 +39,7 @@ namespace Microsoft.DotNet.Tools.Test
public string Output { get; set; } public string Output { get; set; }
public string ProjectPath { get; set; } public string ProjectOrAssemblyPath { get; set; }
public NuGetFramework Framework { get; set; } public NuGetFramework Framework { get; set; }
@ -50,6 +51,10 @@ namespace Microsoft.DotNet.Tools.Test
public bool Help { get; set; } public bool Help { get; set; }
public string TestRunner { get; set; }
public bool HasTestRunner => !string.IsNullOrWhiteSpace(TestRunner);
public DotnetTestParams() public DotnetTestParams()
{ {
_app = new CommandLineApplication(false) _app = new CommandLineApplication(false)
@ -69,10 +74,10 @@ namespace Microsoft.DotNet.Tools.Test
_app.OnExecute(() => _app.OnExecute(() =>
{ {
// Locate the project and get the name and full path // Locate the project and get the name and full path
ProjectPath = _projectPath.Value; ProjectOrAssemblyPath = _projectOrAssemblyPath.Value;
if (string.IsNullOrEmpty(ProjectPath)) if (string.IsNullOrEmpty(ProjectOrAssemblyPath))
{ {
ProjectPath = Directory.GetCurrentDirectory(); ProjectOrAssemblyPath = Directory.GetCurrentDirectory();
} }
if (_parentProcessIdOption.HasValue()) if (_parentProcessIdOption.HasValue())
@ -156,9 +161,16 @@ namespace Microsoft.DotNet.Tools.Test
CommandOptionType.SingleValue); CommandOptionType.SingleValue);
_noBuildOption = _noBuildOption =
_app.Option("--no-build", "Do not build project before testing", CommandOptionType.NoValue); _app.Option("--no-build", "Do not build project before testing", CommandOptionType.NoValue);
_projectPath = _app.Argument( _testRunner =
"<PROJECT>", _app.Option(
"The project to test, defaults to the current directory. Can be a path to a project.json or a project directory."); "-t|--test-runner <TEST_RUNNER>",
"Test runner to be used to run the test when an assembly to test is specified. If this option " +
"is not provided, we will try to find a suitable runner collocated with the assembly",
CommandOptionType.SingleValue);
_projectOrAssemblyPath = _app.Argument(
"<PROJECT OR ASSEMBLY TO TEST>",
"The project or assembly to test, defaults to the current directory. Can be a path to a " +
"project.json, to a dll or a project directory.");
} }
} }
} }

View file

@ -41,7 +41,7 @@ namespace Microsoft.DotNet.Tools.Test
RegisterForParentProcessExit(dotnetTestParams.ParentProcessId.Value); RegisterForParentProcessExit(dotnetTestParams.ParentProcessId.Value);
} }
var projectPath = GetProjectPath(dotnetTestParams.ProjectPath); var projectPath = GetProjectPath(dotnetTestParams.ProjectOrAssemblyPath);
var runtimeIdentifiers = !string.IsNullOrEmpty(dotnetTestParams.Runtime) ? var runtimeIdentifiers = !string.IsNullOrEmpty(dotnetTestParams.Runtime) ?
new[] { dotnetTestParams.Runtime } : new[] { dotnetTestParams.Runtime } :
RuntimeEnvironmentRidExtensions.GetAllCandidateRuntimeIdentifiers(); RuntimeEnvironmentRidExtensions.GetAllCandidateRuntimeIdentifiers();

View file

@ -9,24 +9,24 @@ namespace Microsoft.DotNet.Tools.Test
{ {
public class AssemblyTestRunnerResolver : ITestRunnerResolver public class AssemblyTestRunnerResolver : ITestRunnerResolver
{ {
private readonly string _assemblyUnderTestPath; private readonly string _directoryOfAssemblyUnderTest;
private readonly IDirectory _directory; private readonly IDirectory _directory;
public AssemblyTestRunnerResolver(string assemblyUnderTestPath) : public AssemblyTestRunnerResolver(string directoryOfAssemblyUnderTest) :
this(assemblyUnderTestPath, FileSystemWrapper.Default.Directory) this(directoryOfAssemblyUnderTest, FileSystemWrapper.Default.Directory)
{ {
} }
internal AssemblyTestRunnerResolver(string assemblyUnderTestPath, IDirectory directory) internal AssemblyTestRunnerResolver(string directoryOfAssemblyUnderTest, IDirectory directory)
{ {
_assemblyUnderTestPath = assemblyUnderTestPath; _directoryOfAssemblyUnderTest = Path.GetDirectoryName(directoryOfAssemblyUnderTest);
_directory = directory; _directory = directory;
} }
public string ResolveTestRunner() public string ResolveTestRunner()
{ {
var testRunnerPath = _directory.GetFiles(_assemblyUnderTestPath, "dotnet-test-*").FirstOrDefault(); var testRunnerPath = _directory.GetFiles(_directoryOfAssemblyUnderTest, "dotnet-test-*").FirstOrDefault();
return Path.GetFileNameWithoutExtension(testRunnerPath); return Path.GetFileNameWithoutExtension(testRunnerPath);
} }

View file

@ -0,0 +1,47 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using Microsoft.DotNet.ProjectModel;
namespace Microsoft.DotNet.Tools.Test
{
public class DotnetTestRunnerResolverFactory
{
private readonly IProjectReader _projectReader;
public DotnetTestRunnerResolverFactory(IProjectReader projectReader)
{
_projectReader = projectReader;
}
public ITestRunnerResolver Create(DotnetTestParams dotnetTestParams)
{
var testRunnerResolver = dotnetTestParams.ProjectOrAssemblyPath.EndsWith(".dll") ?
GetAssemblyTestRunnerResolver(dotnetTestParams) :
GetProjectJsonTestRunnerResolver(dotnetTestParams);
return testRunnerResolver;
}
private ITestRunnerResolver GetAssemblyTestRunnerResolver(DotnetTestParams dotnetTestParams)
{
ITestRunnerResolver testRunnerResolver = null;
if (dotnetTestParams.HasTestRunner)
{
testRunnerResolver = new ParameterTestRunnerResolver(dotnetTestParams.TestRunner);
}
else
{
testRunnerResolver = new AssemblyTestRunnerResolver(dotnetTestParams.ProjectOrAssemblyPath);
}
return testRunnerResolver;
}
private ITestRunnerResolver GetProjectJsonTestRunnerResolver(DotnetTestParams dotnetTestParams)
{
var project = _projectReader.ReadProject(dotnetTestParams.ProjectOrAssemblyPath);
return new ProjectJsonTestRunnerResolver(project);
}
}
}

View file

@ -0,0 +1,79 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.IO;
using FluentAssertions;
using Microsoft.DotNet.ProjectModel;
using Microsoft.DotNet.Tools.Test;
using Moq;
using Xunit;
namespace Microsoft.Dotnet.Tools.Test.Tests
{
public class GivenATestRunnerResolverFactoryAndADotnetTestParams
{
private const string PathToAFolder = "c:/some/path";
private const string PathToAnAssembly = "c:/some/path/to/assembly.dll";
private const string SomeTestRunner = "some test runner";
private readonly string _pathToAProjectJson = Path.Combine(PathToAFolder, "project.json");
[Fact]
public void It_returns_a_ProjectJsonTestRunnerResolver_when_the_path_parameter_points_to_a_project_json()
{
var dotnetTestParams = new DotnetTestParams
{
ProjectOrAssemblyPath = _pathToAProjectJson
};
var projectReaderMock = new Mock<IProjectReader>();
projectReaderMock
.Setup(p => p.ReadProject(dotnetTestParams.ProjectOrAssemblyPath, null))
.Returns(new Project());
var dotnetTestRunnerResolverFactory = new DotnetTestRunnerResolverFactory(projectReaderMock.Object);
var testRunnerResolver = dotnetTestRunnerResolverFactory.Create(dotnetTestParams);
testRunnerResolver.Should().BeOfType<ProjectJsonTestRunnerResolver>();
}
[Fact]
public void It_returns_a_ProjectJsonTestRunnerResolver_when_the_path_parameter_points_to_a_folder()
{
var dotnetTestParams = new DotnetTestParams
{
ProjectOrAssemblyPath = PathToAFolder
};
var projectReaderMock = new Mock<IProjectReader>();
projectReaderMock
.Setup(p => p.ReadProject(dotnetTestParams.ProjectOrAssemblyPath, null))
.Returns(new Project());
var dotnetTestRunnerResolverFactory = new DotnetTestRunnerResolverFactory(projectReaderMock.Object);
var testRunnerResolver = dotnetTestRunnerResolverFactory.Create(dotnetTestParams);
testRunnerResolver.Should().BeOfType<ProjectJsonTestRunnerResolver>();
}
[Fact]
public void It_returns_a_ParameterTestRunnerResolver_when_an_assembly_and_a_test_runner_are_passed()
{
var dotnetTestParams = new DotnetTestParams
{
ProjectOrAssemblyPath = PathToAnAssembly,
TestRunner = SomeTestRunner
};
var projectReaderMock = new Mock<IProjectReader>();
var dotnetTestRunnerResolverFactory = new DotnetTestRunnerResolverFactory(projectReaderMock.Object);
var testRunnerResolver = dotnetTestRunnerResolverFactory.Create(dotnetTestParams);
testRunnerResolver.Should().BeOfType<ParameterTestRunnerResolver>();
}
}
}

View file

@ -2,6 +2,7 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using FluentAssertions; using FluentAssertions;
@ -14,20 +15,21 @@ namespace Microsoft.Dotnet.Tools.Test.Tests
{ {
public class GivenAnAssemblyTestRunnerResolver public class GivenAnAssemblyTestRunnerResolver
{ {
private const string PathToAssemblyUnderTest = "path to some assembly under test"; private const string DirectoryOfAssemblyUnderTest = "c:/some/path";
private const string TestRunnerName = "dotnet-test-someRunner"; private const string TestRunnerName = "dotnet-test-someRunner";
private static readonly string TestRunnerFileName = $"{TestRunnerName}.dll"; private static readonly string TestRunnerFileName = $"{TestRunnerName}.dll";
[Fact] [Fact]
public void It_finds_the_runner_in_the_same_folder_as_the_assembly() public void It_finds_the_runner_in_the_same_folder_as_the_assembly_when_the_path_passed_is_to_the_assembly()
{ {
var directoryMock = new DirectoryMock(); var directoryMock = new DirectoryMock();
directoryMock.AddFile(PathToAssemblyUnderTest, TestRunnerFileName); directoryMock.AddFile(DirectoryOfAssemblyUnderTest, TestRunnerFileName);
var assemblyTestRunnerResolver = new AssemblyTestRunnerResolver(PathToAssemblyUnderTest, directoryMock); var pathToAssemblyUnderTest = Path.Combine(DirectoryOfAssemblyUnderTest, TestRunnerFileName);
var assemblyTestRunnerResolver = new AssemblyTestRunnerResolver(pathToAssemblyUnderTest, directoryMock);
var testRunner = assemblyTestRunnerResolver.ResolveTestRunner(); var testRunner = assemblyTestRunnerResolver.ResolveTestRunner();
@ -39,11 +41,11 @@ namespace Microsoft.Dotnet.Tools.Test.Tests
{ {
var directoryMock = new DirectoryMock(); var directoryMock = new DirectoryMock();
directoryMock.AddFile(PathToAssemblyUnderTest, TestRunnerFileName); directoryMock.AddFile(DirectoryOfAssemblyUnderTest, TestRunnerFileName);
directoryMock.AddFile(PathToAssemblyUnderTest, "dotnet-test-someOtherTestRunner.dll"); directoryMock.AddFile(DirectoryOfAssemblyUnderTest, "dotnet-test-someOtherTestRunner.dll");
directoryMock.AddFile(PathToAssemblyUnderTest, "dotnet-test-AndYetAnotherTestRunner.dll"); directoryMock.AddFile(DirectoryOfAssemblyUnderTest, "dotnet-test-AndYetAnotherTestRunner.dll");
var assemblyTestRunnerResolver = new AssemblyTestRunnerResolver(PathToAssemblyUnderTest, directoryMock); var assemblyTestRunnerResolver = new AssemblyTestRunnerResolver(DirectoryOfAssemblyUnderTest, directoryMock);
var bestEffortTestRunner = assemblyTestRunnerResolver.ResolveTestRunner(); var bestEffortTestRunner = assemblyTestRunnerResolver.ResolveTestRunner();
@ -55,7 +57,7 @@ namespace Microsoft.Dotnet.Tools.Test.Tests
{ {
var directoryMock = new DirectoryMock(); var directoryMock = new DirectoryMock();
var assemblyTestRunnerResolver = new AssemblyTestRunnerResolver(PathToAssemblyUnderTest, directoryMock); var assemblyTestRunnerResolver = new AssemblyTestRunnerResolver(DirectoryOfAssemblyUnderTest, directoryMock);
var testRunner = assemblyTestRunnerResolver.ResolveTestRunner(); var testRunner = assemblyTestRunnerResolver.ResolveTestRunner();

View file

@ -48,13 +48,13 @@ namespace Microsoft.Dotnet.Tools.Test.Tests
[Fact] [Fact]
public void It_sets_the_project_path_current_folder_if_one_is_not_passed_in() public void It_sets_the_project_path_current_folder_if_one_is_not_passed_in()
{ {
_emptyDotnetTestParams.ProjectPath.Should().Be(Directory.GetCurrentDirectory()); _emptyDotnetTestParams.ProjectOrAssemblyPath.Should().Be(Directory.GetCurrentDirectory());
} }
[Fact] [Fact]
public void It_sets_the_project_path_to_the_passed_value() public void It_sets_the_project_path_to_the_passed_value()
{ {
_dotnetTestFullParams.ProjectPath.Should().Be(ProjectJson); _dotnetTestFullParams.ProjectOrAssemblyPath.Should().Be(ProjectJson);
} }
[Fact] [Fact]