diff --git a/.gitignore b/.gitignore index f1732c2e0..9af9fe15f 100644 --- a/.gitignore +++ b/.gitignore @@ -151,6 +151,7 @@ _ReSharper*/ *.DotSettings.user .idea/ *.iml +*.DotSettings # JustCode is a .NET coding add-in .JustCode diff --git a/src/dotnet-test-console/AssemblyTestRunner.cs b/src/dotnet-test-console/AssemblyTestRunner.cs new file mode 100644 index 000000000..62c0fdb57 --- /dev/null +++ b/src/dotnet-test-console/AssemblyTestRunner.cs @@ -0,0 +1,28 @@ +// 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; +using Microsoft.DotNet.Cli.Utils; + +namespace Microsoft.DotNet.Tools.Test +{ + public class AssemblyTestRunner : IDotnetTestRunner + { + private readonly Func _nextRunner; + + public AssemblyTestRunner(Func nextRunner) + { + _nextRunner = nextRunner; + } + + public int RunTests(DotnetTestParams dotnetTestParams) + { + var commandFactory = + new CommandFactory(); + + var assemblyUnderTest = dotnetTestParams.ProjectOrAssemblyPath; + + return _nextRunner(commandFactory, assemblyUnderTest).RunTests(dotnetTestParams); + } + } +} \ No newline at end of file diff --git a/src/dotnet-test-console/ConsoleTestRunner.cs b/src/dotnet-test-console/ConsoleTestRunner.cs index 9277afe18..5dfb9ad9a 100644 --- a/src/dotnet-test-console/ConsoleTestRunner.cs +++ b/src/dotnet-test-console/ConsoleTestRunner.cs @@ -3,46 +3,53 @@ using System.Collections.Generic; using Microsoft.DotNet.Cli.Utils; -using Microsoft.DotNet.ProjectModel; +using NuGet.Frameworks; namespace Microsoft.DotNet.Tools.Test { - public class ConsoleTestRunner : BaseDotnetTestRunner + public class ConsoleTestRunner : IDotnetTestRunner { - internal override int DoRunTests(ProjectContext projectContext, DotnetTestParams dotnetTestParams) - { - var commandFactory = - new ProjectDependenciesCommandFactory( - projectContext.TargetFramework, - dotnetTestParams.Config, - dotnetTestParams.Output, - dotnetTestParams.BuildBasePath, - projectContext.ProjectDirectory); + private readonly ITestRunnerResolver _testRunnerResolver; - return commandFactory.Create( - GetCommandName(projectContext.ProjectFile.TestRunner), - GetCommandArgs(projectContext, dotnetTestParams), - projectContext.TargetFramework, + private readonly ICommandFactory _commandFactory; + + private readonly string _assemblyUnderTest; + + private readonly NuGetFramework _framework; + + public ConsoleTestRunner( + ITestRunnerResolver testRunnerResolver, + ICommandFactory commandFactory, + string assemblyUnderTest, + NuGetFramework framework = null) + { + _testRunnerResolver = testRunnerResolver; + _commandFactory = commandFactory; + _assemblyUnderTest = assemblyUnderTest; + _framework = framework; + } + + public int RunTests(DotnetTestParams dotnetTestParams) + { + return _commandFactory.Create( + _testRunnerResolver.ResolveTestRunner(), + GetCommandArgs(dotnetTestParams), + _framework, dotnetTestParams.Config) .Execute() .ExitCode; } - private IEnumerable GetCommandArgs(ProjectContext projectContext, DotnetTestParams dotnetTestParams) + private IEnumerable GetCommandArgs(DotnetTestParams dotnetTestParams) { var commandArgs = new List { - new AssemblyUnderTest(projectContext, dotnetTestParams).Path + _assemblyUnderTest }; commandArgs.AddRange(dotnetTestParams.RemainingArguments); return commandArgs; } - - private static string GetCommandName(string testRunner) - { - return $"dotnet-test-{testRunner}"; - } } } diff --git a/src/dotnet-test-console/DesignTimeRunner.cs b/src/dotnet-test-console/DesignTimeRunner.cs index 66753a6b1..646cd89eb 100644 --- a/src/dotnet-test-console/DesignTimeRunner.cs +++ b/src/dotnet-test-console/DesignTimeRunner.cs @@ -3,44 +3,49 @@ using System; using Microsoft.DotNet.Cli.Utils; -using Microsoft.DotNet.ProjectModel; namespace Microsoft.DotNet.Tools.Test { - public class DesignTimeRunner : BaseDotnetTestRunner + public class DesignTimeRunner : IDotnetTestRunner { - internal override int DoRunTests(ProjectContext projectContext, DotnetTestParams dotnetTestParams) + private readonly ITestRunnerResolver _testRunnerResolver; + + private readonly ICommandFactory _commandFactory; + + private readonly string _assemblyUnderTest; + + public DesignTimeRunner( + ITestRunnerResolver testRunnerResolver, + ICommandFactory commandFactory, + string assemblyUnderTest) + { + _testRunnerResolver = testRunnerResolver; + _commandFactory = commandFactory; + _assemblyUnderTest = assemblyUnderTest; + } + + public int RunTests(DotnetTestParams dotnetTestParams) { Console.WriteLine("Listening on port {0}", dotnetTestParams.Port.Value); - HandleDesignTimeMessages(projectContext, dotnetTestParams); + HandleDesignTimeMessages(dotnetTestParams); return 0; } - private static void HandleDesignTimeMessages( - ProjectContext projectContext, - DotnetTestParams dotnetTestParams) + private void HandleDesignTimeMessages(DotnetTestParams dotnetTestParams) { var reportingChannelFactory = new ReportingChannelFactory(); var adapterChannel = reportingChannelFactory.CreateAdapterChannel(dotnetTestParams.Port.Value); try { - var pathToAssemblyUnderTest = new AssemblyUnderTest(projectContext, dotnetTestParams).Path; + var pathToAssemblyUnderTest = _assemblyUnderTest; var messages = new TestMessagesCollection(); using (var dotnetTest = new DotnetTest(messages, pathToAssemblyUnderTest)) { - var commandFactory = - new ProjectDependenciesCommandFactory( - projectContext.TargetFramework, - dotnetTestParams.Config, - dotnetTestParams.Output, - dotnetTestParams.BuildBasePath, - projectContext.ProjectDirectory); - var testRunnerFactory = - new TestRunnerFactory(GetCommandName(projectContext.ProjectFile.TestRunner), commandFactory); + new TestRunnerFactory(_testRunnerResolver.ResolveTestRunner(), _commandFactory); dotnetTest .AddNonSpecificMessageHandlers(messages, adapterChannel) @@ -60,10 +65,5 @@ namespace Microsoft.DotNet.Tools.Test adapterChannel.SendError(ex); } } - - private static string GetCommandName(string testRunner) - { - return $"dotnet-test-{testRunner}"; - } } } diff --git a/src/dotnet-test-console/DotnetTestParams.cs b/src/dotnet-test-console/DotnetTestParams.cs index 177a31c98..9bfdadff1 100644 --- a/src/dotnet-test-console/DotnetTestParams.cs +++ b/src/dotnet-test-console/DotnetTestParams.cs @@ -56,6 +56,8 @@ namespace Microsoft.DotNet.Tools.Test public bool HasTestRunner => !string.IsNullOrWhiteSpace(TestRunner); + public bool IsTestingAssembly => ProjectOrAssemblyPath.EndsWith(".dll"); + public DotnetTestParams() { _app = new CommandLineApplication(false) @@ -108,7 +110,7 @@ namespace Microsoft.DotNet.Tools.Test if (_testRunner.HasValue()) { - if (!IsAssembly(ProjectOrAssemblyPath)) + if (!IsTestingAssembly) { throw new InvalidOperationException("You can only specify a test runner with a dll."); } @@ -138,11 +140,6 @@ namespace Microsoft.DotNet.Tools.Test _app.Execute(args); } - private bool IsAssembly(string projectOrAssemblyPath) - { - return projectOrAssemblyPath.EndsWith(".dll"); - } - private void AddDotnetTestParameters() { _app.HelpOption("-?|-h|--help"); diff --git a/src/dotnet-test-console/DotnetTestRunnerFactory.cs b/src/dotnet-test-console/DotnetTestRunnerFactory.cs index 32ef694ec..49e374991 100644 --- a/src/dotnet-test-console/DotnetTestRunnerFactory.cs +++ b/src/dotnet-test-console/DotnetTestRunnerFactory.cs @@ -1,19 +1,56 @@ // 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; +using Microsoft.DotNet.Cli.Utils; +using NuGet.Frameworks; + namespace Microsoft.DotNet.Tools.Test { public class DotnetTestRunnerFactory : IDotnetTestRunnerFactory { - public IDotnetTestRunner Create(int? port) - { - IDotnetTestRunner dotnetTestRunner = new ConsoleTestRunner(); - if (port.HasValue) - { - dotnetTestRunner = new DesignTimeRunner(); - } + private readonly DotnetTestRunnerResolverFactory _dotnetTestRunnerResolverFactory; - return dotnetTestRunner; + public DotnetTestRunnerFactory(DotnetTestRunnerResolverFactory dotnetTestRunnerResolverFactory) + { + _dotnetTestRunnerResolverFactory = dotnetTestRunnerResolverFactory; + } + + public IDotnetTestRunner Create(DotnetTestParams dotnetTestParams) + { + Func nextTestRunner = + (commandFactory, assemblyUnderTest, framework) => + { + var dotnetTestRunnerResolver = _dotnetTestRunnerResolverFactory.Create(dotnetTestParams); + + IDotnetTestRunner testRunner = + new ConsoleTestRunner(dotnetTestRunnerResolver, commandFactory, assemblyUnderTest, framework); + if (dotnetTestParams.Port.HasValue) + { + testRunner = new DesignTimeRunner(dotnetTestRunnerResolver, commandFactory, assemblyUnderTest); + } + + return testRunner; + }; + + return dotnetTestParams.IsTestingAssembly + ? CreateTestRunnerForAssembly(nextTestRunner) + : CreateTestRunnerForProjectJson(nextTestRunner); + } + + private static IDotnetTestRunner CreateTestRunnerForAssembly( + Func nextTestRunner) + { + Func nextAssemblyTestRunner = + (commandFactory, assemblyUnderTest) => nextTestRunner(commandFactory, assemblyUnderTest, null); + + return new AssemblyTestRunner(nextAssemblyTestRunner); + } + + private static IDotnetTestRunner CreateTestRunnerForProjectJson( + Func nextTestRunner) + { + return new ProjectJsonTestRunner(nextTestRunner); } } } diff --git a/src/dotnet-test-console/IDotnetTestRunner.cs b/src/dotnet-test-console/IDotnetTestRunner.cs index 1466eb32d..2e40e335c 100644 --- a/src/dotnet-test-console/IDotnetTestRunner.cs +++ b/src/dotnet-test-console/IDotnetTestRunner.cs @@ -1,13 +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. -using Microsoft.DotNet.ProjectModel; -using Microsoft.DotNet.Cli.Utils; - namespace Microsoft.DotNet.Tools.Test { public interface IDotnetTestRunner { - int RunTests(ProjectContext projectContext, DotnetTestParams dotnetTestParams, BuildWorkspace workspace); + int RunTests(DotnetTestParams dotnetTestParams); } } diff --git a/src/dotnet-test-console/IDotnetTestRunnerFactory.cs b/src/dotnet-test-console/IDotnetTestRunnerFactory.cs index 8dfc9599f..ccb0dc47b 100644 --- a/src/dotnet-test-console/IDotnetTestRunnerFactory.cs +++ b/src/dotnet-test-console/IDotnetTestRunnerFactory.cs @@ -5,6 +5,6 @@ namespace Microsoft.DotNet.Tools.Test { public interface IDotnetTestRunnerFactory { - IDotnetTestRunner Create(int? port); + IDotnetTestRunner Create(DotnetTestParams dotnetTestParams); } } diff --git a/src/dotnet-test-console/TestCommand.cs b/src/dotnet-test-console/TestCommand.cs index 1a2adb3ad..eda766f1e 100644 --- a/src/dotnet-test-console/TestCommand.cs +++ b/src/dotnet-test-console/TestCommand.cs @@ -15,6 +15,14 @@ namespace Microsoft.DotNet.Tools.Test { private readonly IDotnetTestRunnerFactory _dotnetTestRunnerFactory; + public static int Run(string[] args) + { + var dotnetTestRunnerResolverFactory = new DotnetTestRunnerResolverFactory(new ProjectReader()); + var testCommand = new TestCommand(new DotnetTestRunnerFactory(dotnetTestRunnerResolverFactory)); + + return testCommand.DoRun(args); + } + public TestCommand(IDotnetTestRunnerFactory testRunnerFactory) { _dotnetTestRunnerFactory = testRunnerFactory; @@ -41,60 +49,7 @@ namespace Microsoft.DotNet.Tools.Test RegisterForParentProcessExit(dotnetTestParams.ParentProcessId.Value); } - var projectPath = GetProjectPath(dotnetTestParams.ProjectOrAssemblyPath); - var runtimeIdentifiers = !string.IsNullOrEmpty(dotnetTestParams.Runtime) ? - new[] { dotnetTestParams.Runtime } : - RuntimeEnvironmentRidExtensions.GetAllCandidateRuntimeIdentifiers(); - var exitCode = 0; - - // Create a workspace - var workspace = new BuildWorkspace(ProjectReaderSettings.ReadFromEnvironment()); - - if (dotnetTestParams.Framework != null) - { - var projectContext = workspace.GetProjectContext(projectPath, dotnetTestParams.Framework); - if (projectContext == null) - { - Reporter.Error.WriteLine($"Project '{projectPath}' does not support framework: {dotnetTestParams.UnparsedFramework}"); - return 1; - } - projectContext = workspace.GetRuntimeContext(projectContext, runtimeIdentifiers); - - exitCode = RunTest(projectContext, dotnetTestParams, workspace); - } - else - { - var summary = new Summary(); - var projectContexts = workspace.GetProjectContextCollection(projectPath) - .EnsureValid(projectPath) - .FrameworkOnlyContexts - .Select(c => workspace.GetRuntimeContext(c, runtimeIdentifiers)) - .ToList(); - - // Execute for all TFMs the project targets. - foreach (var projectContext in projectContexts) - { - var result = RunTest(projectContext, dotnetTestParams, workspace); - if (result == 0) - { - summary.Passed++; - } - else - { - summary.Failed++; - if (exitCode == 0) - { - // If tests fail in more than one TFM, we'll have it use the result of the first one - // as the exit code. - exitCode = result; - } - } - } - - summary.Print(); - } - - return exitCode; + return RunTest(dotnetTestParams); } catch (InvalidOperationException ex) { @@ -108,13 +63,6 @@ namespace Microsoft.DotNet.Tools.Test } } - public static int Run(string[] args) - { - var testCommand = new TestCommand(new DotnetTestRunnerFactory()); - - return testCommand.DoRun(args); - } - private static void RegisterForParentProcessExit(int id) { var parentProcess = Process.GetProcesses().FirstOrDefault(p => p.Id == id); @@ -142,50 +90,10 @@ namespace Microsoft.DotNet.Tools.Test } } - private int RunTest(ProjectContext projectContext, DotnetTestParams dotnetTestParams, BuildWorkspace workspace) + private int RunTest(DotnetTestParams dotnetTestParams) { - var testRunner = projectContext.ProjectFile.TestRunner; - var dotnetTestRunner = _dotnetTestRunnerFactory.Create(dotnetTestParams.Port); - return dotnetTestRunner.RunTests(projectContext, dotnetTestParams, workspace); - } - - private static string GetProjectPath(string projectPath) - { - projectPath = projectPath ?? Directory.GetCurrentDirectory(); - - if (!projectPath.EndsWith(Project.FileName)) - { - projectPath = Path.Combine(projectPath, Project.FileName); - } - - if (!File.Exists(projectPath)) - { - throw new InvalidOperationException($"{projectPath} does not exist."); - } - - return projectPath; - } - - private class Summary - { - public int Passed { get; set; } - - public int Failed { get; set; } - - public int Total => Passed + Failed; - - public void Print() - { - var summaryMessage = $"SUMMARY: Total: {Total} targets, Passed: {Passed}, Failed: {Failed}."; - if (Failed > 0) - { - Reporter.Error.WriteLine(summaryMessage.Red()); - } - else - { - Reporter.Output.WriteLine(summaryMessage); - } - } + var dotnetTestRunner = _dotnetTestRunnerFactory.Create(dotnetTestParams); + return dotnetTestRunner.RunTests(dotnetTestParams); } } } \ No newline at end of file diff --git a/src/dotnet-test-console/BaseDotnetTestRunner.cs b/src/dotnet-test-console/TestProjectBuilder.cs similarity index 50% rename from src/dotnet-test-console/BaseDotnetTestRunner.cs rename to src/dotnet-test-console/TestProjectBuilder.cs index 4cb82efd9..ffaafbf70 100644 --- a/src/dotnet-test-console/BaseDotnetTestRunner.cs +++ b/src/dotnet-test-console/TestProjectBuilder.cs @@ -2,46 +2,29 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Collections.Generic; -using System.Runtime.InteropServices.ComTypes; using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.ProjectModel; namespace Microsoft.DotNet.Tools.Test { - public abstract class BaseDotnetTestRunner : IDotnetTestRunner + public class TestProjectBuilder { - public int RunTests(ProjectContext projectContext, DotnetTestParams dotnetTestParams, BuildWorkspace workspace) + public int BuildTestProject(ProjectContext projectContext, DotnetTestParams dotnetTestParams) { - var result = BuildTestProject(projectContext, dotnetTestParams, workspace); - - return result == 0 ? DoRunTests(projectContext, dotnetTestParams) : result; + return dotnetTestParams.NoBuild ? 0 : DoBuildTestProject(projectContext, dotnetTestParams); } - internal abstract int DoRunTests(ProjectContext projectContext, DotnetTestParams dotnetTestParams); - - private int BuildTestProject(ProjectContext projectContext, DotnetTestParams dotnetTestParams, BuildWorkspace workspace) - { - if (dotnetTestParams.NoBuild) - { - return 0; - } - - return DoBuildTestProject(projectContext, dotnetTestParams, workspace); - } - - private int DoBuildTestProject(ProjectContext projectContext, DotnetTestParams dotnetTestParams, BuildWorkspace workspace) + private int DoBuildTestProject(ProjectContext projectContext, DotnetTestParams dotnetTestParams) { var strings = new List { - $"--configuration", - dotnetTestParams.Config, - $"{dotnetTestParams.ProjectOrAssemblyPath}" + $"{dotnetTestParams.ProjectOrAssemblyPath}", + $"--configuration", dotnetTestParams.Config, + "--framework", projectContext.TargetFramework.ToString() }; - // Build the test specifically for the target framework \ rid of the ProjectContext. This avoids building the project - // for tfms that the user did not request. - strings.Add("--framework"); - strings.Add(projectContext.TargetFramework.ToString()); + // Build the test specifically for the target framework \ rid of the ProjectContext. + // This avoids building the project for tfms that the user did not request. if (!string.IsNullOrEmpty(dotnetTestParams.BuildBasePath)) { @@ -66,4 +49,4 @@ namespace Microsoft.DotNet.Tools.Test return result; } } -} +} \ No newline at end of file diff --git a/src/dotnet-test-console/TestRunners/AssemblyTestRunnerResolver.cs b/src/dotnet-test-console/TestRunners/AssemblyTestRunnerResolver.cs index 4686f1074..99a741de3 100644 --- a/src/dotnet-test-console/TestRunners/AssemblyTestRunnerResolver.cs +++ b/src/dotnet-test-console/TestRunners/AssemblyTestRunnerResolver.cs @@ -13,14 +13,14 @@ namespace Microsoft.DotNet.Tools.Test private readonly IDirectory _directory; - public AssemblyTestRunnerResolver(string directoryOfAssemblyUnderTest) : - this(directoryOfAssemblyUnderTest, FileSystemWrapper.Default.Directory) + public AssemblyTestRunnerResolver(string assemblyUnderTest) : + this(assemblyUnderTest, FileSystemWrapper.Default.Directory) { } - internal AssemblyTestRunnerResolver(string directoryOfAssemblyUnderTest, IDirectory directory) + internal AssemblyTestRunnerResolver(string assemblyUnderTest, IDirectory directory) { - _directoryOfAssemblyUnderTest = Path.GetDirectoryName(directoryOfAssemblyUnderTest); + _directoryOfAssemblyUnderTest = new FileInfo(assemblyUnderTest).Directory.FullName; _directory = directory; } diff --git a/src/dotnet-test-console/TestRunners/DotnetTestRunnerResolverFactory.cs b/src/dotnet-test-console/TestRunners/DotnetTestRunnerResolverFactory.cs index d0ddf2438..6d65cb686 100644 --- a/src/dotnet-test-console/TestRunners/DotnetTestRunnerResolverFactory.cs +++ b/src/dotnet-test-console/TestRunners/DotnetTestRunnerResolverFactory.cs @@ -1,6 +1,7 @@ // 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 Microsoft.DotNet.ProjectModel; namespace Microsoft.DotNet.Tools.Test @@ -16,7 +17,7 @@ namespace Microsoft.DotNet.Tools.Test public ITestRunnerResolver Create(DotnetTestParams dotnetTestParams) { - var testRunnerResolver = dotnetTestParams.ProjectOrAssemblyPath.EndsWith(".dll") ? + var testRunnerResolver = dotnetTestParams.IsTestingAssembly ? GetAssemblyTestRunnerResolver(dotnetTestParams) : GetProjectJsonTestRunnerResolver(dotnetTestParams); diff --git a/src/dotnet-test-console/TestRunners/ProjectJsonTestRunner.cs b/src/dotnet-test-console/TestRunners/ProjectJsonTestRunner.cs new file mode 100644 index 000000000..102c240ef --- /dev/null +++ b/src/dotnet-test-console/TestRunners/ProjectJsonTestRunner.cs @@ -0,0 +1,148 @@ +// 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; +using System.IO; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.InternalAbstractions; +using Microsoft.DotNet.ProjectModel; +using System.Linq; +using NuGet.Frameworks; + +namespace Microsoft.DotNet.Tools.Test +{ + public class ProjectJsonTestRunner : IDotnetTestRunner + { + private readonly Func _nextRunner; + private readonly TestProjectBuilder _testProjectBuilder; + + public ProjectJsonTestRunner( + Func nextRunner) + { + _nextRunner = nextRunner; + _testProjectBuilder = new TestProjectBuilder(); + } + + public int RunTests(DotnetTestParams dotnetTestParams) + { + var projectPath = GetProjectPath(dotnetTestParams.ProjectOrAssemblyPath); + var runtimeIdentifiers = !string.IsNullOrEmpty(dotnetTestParams.Runtime) + ? new[] {dotnetTestParams.Runtime} + : RuntimeEnvironmentRidExtensions.GetAllCandidateRuntimeIdentifiers(); + var exitCode = 0; + + // Create a workspace + var workspace = new BuildWorkspace(ProjectReaderSettings.ReadFromEnvironment()); + + if (dotnetTestParams.Framework != null) + { + var projectContext = workspace.GetProjectContext(projectPath, dotnetTestParams.Framework); + if (projectContext == null) + { + Reporter.Error.WriteLine( + $"Project '{projectPath}' does not support framework: {dotnetTestParams.UnparsedFramework}"); + return 1; + } + projectContext = workspace.GetRuntimeContext(projectContext, runtimeIdentifiers); + + exitCode = RunTests(projectContext, dotnetTestParams); + } + else + { + var summary = new Summary(); + var projectContexts = workspace.GetProjectContextCollection(projectPath) + .EnsureValid(projectPath) + .FrameworkOnlyContexts + .Select(c => workspace.GetRuntimeContext(c, runtimeIdentifiers)) + .ToList(); + + // Execute for all TFMs the project targets. + foreach (var projectContext in projectContexts) + { + var result = RunTests(projectContext, dotnetTestParams); + if (result == 0) + { + summary.Passed++; + } + else + { + summary.Failed++; + if (exitCode == 0) + { + // If tests fail in more than one TFM, we'll have it use the result of the first one + // as the exit code. + exitCode = result; + } + } + } + + summary.Print(); + } + + return exitCode; + } + + private int RunTests(ProjectContext projectContext, DotnetTestParams dotnetTestParams) + { + var result = _testProjectBuilder.BuildTestProject(projectContext, dotnetTestParams); + + if (result == 0) + { + var commandFactory = + new ProjectDependenciesCommandFactory( + projectContext.TargetFramework, + dotnetTestParams.Config, + dotnetTestParams.Output, + dotnetTestParams.BuildBasePath, + projectContext.ProjectDirectory); + + var assemblyUnderTest = new AssemblyUnderTest(projectContext, dotnetTestParams); + + var framework = projectContext.TargetFramework; + + result = _nextRunner(commandFactory, assemblyUnderTest.Path, framework).RunTests(dotnetTestParams); + } + + return result; + } + + private static string GetProjectPath(string projectPath) + { + projectPath = projectPath ?? Directory.GetCurrentDirectory(); + + if (!projectPath.EndsWith(Project.FileName)) + { + projectPath = Path.Combine(projectPath, Project.FileName); + } + + if (!File.Exists(projectPath)) + { + throw new InvalidOperationException($"{projectPath} does not exist."); + } + + return projectPath; + } + + private class Summary + { + public int Passed { get; set; } + + public int Failed { get; set; } + + private int Total => Passed + Failed; + + public void Print() + { + var summaryMessage = $"SUMMARY: Total: {Total} targets, Passed: {Passed}, Failed: {Failed}."; + if (Failed > 0) + { + Reporter.Error.WriteLine(summaryMessage.Red()); + } + else + { + Reporter.Output.WriteLine(summaryMessage); + } + } + } + } +} \ No newline at end of file diff --git a/test/dotnet-test.Tests/GivenThatWeWantToRunTestsInTheConsole.cs b/test/dotnet-test.Tests/GivenThatWeWantToRunTestsInTheConsole.cs index 93db4eff0..fb0f0f3e6 100644 --- a/test/dotnet-test.Tests/GivenThatWeWantToRunTestsInTheConsole.cs +++ b/test/dotnet-test.Tests/GivenThatWeWantToRunTestsInTheConsole.cs @@ -97,6 +97,20 @@ namespace Microsoft.Dotnet.Tools.Test.Tests result.Should().Pass(); } + [Fact] + public void It_runs_tests_for_an_assembly_passed_as_param() + { + var buildCommand = new BuildCommand(_projectFilePath); + var result = buildCommand.Execute(); + result.Should().Pass(); + + var assemblyUnderTestPath = Path.Combine(_defaultOutputPath, buildCommand.GetPortableOutputName()); + + var testCommand = new DotnetTestCommand(); + result = testCommand.Execute($"{assemblyUnderTestPath}"); + result.Should().Pass(); + } + [Theory] [MemberData("ArgumentNames")] public void It_fails_correctly_with_unspecified_arguments_with_long_form(string argument)