diff --git a/Microsoft.DotNet.Cli.sln b/Microsoft.DotNet.Cli.sln index b14444f67..42939001f 100644 --- a/Microsoft.DotNet.Cli.sln +++ b/Microsoft.DotNet.Cli.sln @@ -166,6 +166,8 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "dotnet-migrate.Tests", "tes EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.Tools.Test", "src\Microsoft.DotNet.Tools.Test\Microsoft.DotNet.Tools.Test.xproj", "{6D028154-5518-4A56-BAD6-938A90E5BCF6}" EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "dotnet-vstest.Tests", "test\dotnet-vstest.Tests\dotnet-vstest.Tests.xproj", "{9F5AE280-A040-4160-9799-6504D907742D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -946,6 +948,22 @@ Global {6D028154-5518-4A56-BAD6-938A90E5BCF6}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU {6D028154-5518-4A56-BAD6-938A90E5BCF6}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU {6D028154-5518-4A56-BAD6-938A90E5BCF6}.RelWithDebInfo|x64.Build.0 = Release|Any CPU + {9F5AE280-A040-4160-9799-6504D907742D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9F5AE280-A040-4160-9799-6504D907742D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9F5AE280-A040-4160-9799-6504D907742D}.Debug|x64.ActiveCfg = Debug|Any CPU + {9F5AE280-A040-4160-9799-6504D907742D}.Debug|x64.Build.0 = Debug|Any CPU + {9F5AE280-A040-4160-9799-6504D907742D}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU + {9F5AE280-A040-4160-9799-6504D907742D}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU + {9F5AE280-A040-4160-9799-6504D907742D}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU + {9F5AE280-A040-4160-9799-6504D907742D}.MinSizeRel|x64.Build.0 = Debug|Any CPU + {9F5AE280-A040-4160-9799-6504D907742D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9F5AE280-A040-4160-9799-6504D907742D}.Release|Any CPU.Build.0 = Release|Any CPU + {9F5AE280-A040-4160-9799-6504D907742D}.Release|x64.ActiveCfg = Release|Any CPU + {9F5AE280-A040-4160-9799-6504D907742D}.Release|x64.Build.0 = Release|Any CPU + {9F5AE280-A040-4160-9799-6504D907742D}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU + {9F5AE280-A040-4160-9799-6504D907742D}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU + {9F5AE280-A040-4160-9799-6504D907742D}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU + {9F5AE280-A040-4160-9799-6504D907742D}.RelWithDebInfo|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1007,5 +1025,6 @@ Global {0E083818-2320-4388-8007-4F720FD5C634} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F} {1F2EF070-AC5F-4078-AFB0-65745AC691B9} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7} {6D028154-5518-4A56-BAD6-938A90E5BCF6} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F} + {9F5AE280-A040-4160-9799-6504D907742D} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7} EndGlobalSection EndGlobal diff --git a/TestAssets/TestProjects/VSTestDotNetCoreProject/Tests.cs b/TestAssets/TestProjects/VSTestDotNetCoreProject/Tests.cs new file mode 100644 index 000000000..06cf2371b --- /dev/null +++ b/TestAssets/TestProjects/VSTestDotNetCoreProject/Tests.cs @@ -0,0 +1,19 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace TestNamespace +{ + [TestClass] + public class VSTestTests + { + [TestMethod] + public void VSTestPassTest() + { + } + + [TestMethod] + public void VSTestFailTest() + { + Assert.Fail(); + } + } +} \ No newline at end of file diff --git a/TestAssets/TestProjects/VSTestDotNetCoreProject/VSTestDotNetCoreProject.csproj b/TestAssets/TestProjects/VSTestDotNetCoreProject/VSTestDotNetCoreProject.csproj new file mode 100644 index 000000000..f4fa033eb --- /dev/null +++ b/TestAssets/TestProjects/VSTestDotNetCoreProject/VSTestDotNetCoreProject.csproj @@ -0,0 +1,25 @@ + + + + + + Library + .NETCoreApp + v1.0 + bin\$(Configuration)\netcoreapp1.0 + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TestAssets/TestProjects/VSTestDotNetCoreProject/project.json b/TestAssets/TestProjects/VSTestDotNetCoreProject/project.json new file mode 100644 index 000000000..a576bf82a --- /dev/null +++ b/TestAssets/TestProjects/VSTestDotNetCoreProject/project.json @@ -0,0 +1,21 @@ +{ + "dependencies": { + "MSTest.TestAdapter": "1.0.3-preview", + "MSTest.TestFramework": "1.0.1-preview" + }, + "frameworks": { + "netcoreapp1.0": { + "dependencies": { + "Microsoft.NETCore.Sdk": "1.0.0-alpha-20160914-1", + "Microsoft.NETCore.App": { + "version": "1.0.1", + "type": "platform" + } + }, + "imports": [ + "dnxcore50", + "portable-net45+win8" + ] + } + } +} diff --git a/src/dotnet/Program.cs b/src/dotnet/Program.cs index 26bec1a2d..e7b452a44 100644 --- a/src/dotnet/Program.cs +++ b/src/dotnet/Program.cs @@ -23,6 +23,7 @@ using Microsoft.DotNet.Tools.Restore; using Microsoft.DotNet.Tools.Restore3; using Microsoft.DotNet.Tools.Run; using Microsoft.DotNet.Tools.Test; +using Microsoft.DotNet.Tools.VSTest; using Microsoft.DotNet.Tools.Migrate; using NuGet.Frameworks; @@ -45,6 +46,7 @@ namespace Microsoft.DotNet.Cli ["build3"] = Build3Command.Run, ["run3"] = Run3Command.Run, ["restore3"] = Restore3Command.Run, + ["vstest"] = VSTestCommand.Run, ["pack3"] = Pack3Command.Run, ["migrate"] = MigrateCommand.Run, ["projectmodel-server"] = ProjectModelServerCommand.Run, diff --git a/src/dotnet/commands/dotnet-help/HelpCommand.cs b/src/dotnet/commands/dotnet-help/HelpCommand.cs index 740111f5f..65dcf8b99 100644 --- a/src/dotnet/commands/dotnet-help/HelpCommand.cs +++ b/src/dotnet/commands/dotnet-help/HelpCommand.cs @@ -32,7 +32,8 @@ Commands: publish Publishes a .NET project for deployment (including the runtime) run Compiles and immediately executes a .NET project test Runs unit tests using the test runner specified in the project - pack Creates a NuGet package"; + pack Creates a NuGet package + vstest Runs tests from the specified files"; public static int Run(string[] args) { diff --git a/src/dotnet/commands/dotnet-vstest/Program.cs b/src/dotnet/commands/dotnet-vstest/Program.cs new file mode 100644 index 000000000..8cc29074f --- /dev/null +++ b/src/dotnet/commands/dotnet-vstest/Program.cs @@ -0,0 +1,17 @@ +// 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.Cli.Utils; +using Microsoft.DotNet.Cli; + +namespace Microsoft.DotNet.Tools.VSTest +{ + public class VSTestCommand + { + public static int Run(string[] args) + { + DebugHelper.HandleDebugSwitch(ref args); + return new VSTestForwardingApp(args).Execute(); + } + } +} \ No newline at end of file diff --git a/src/dotnet/commands/dotnet-vstest/VSTestForwardingApp.cs b/src/dotnet/commands/dotnet-vstest/VSTestForwardingApp.cs new file mode 100644 index 000000000..32e91070f --- /dev/null +++ b/src/dotnet/commands/dotnet-vstest/VSTestForwardingApp.cs @@ -0,0 +1,33 @@ +// 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.Cli.Utils; +using System; +using System.Collections.Generic; +using System.IO; + +namespace Microsoft.DotNet.Cli +{ + public class VSTestForwardingApp + { + private const string VstestAppName = "vstest.console.dll"; + private readonly ForwardingApp _forwardingApp; + + public VSTestForwardingApp(IEnumerable argsToForward) + { + _forwardingApp = new ForwardingApp( + GetVSTestExePath(), + argsToForward); + } + + public int Execute() + { + return _forwardingApp.Execute(); + } + + private string GetVSTestExePath() + { + return Path.Combine(AppContext.BaseDirectory, VstestAppName); + } + } +} diff --git a/src/redist/project.json b/src/redist/project.json index df0eca11c..f4a78e433 100644 --- a/src/redist/project.json +++ b/src/redist/project.json @@ -20,7 +20,8 @@ "Microsoft.Build.Targets": "0.1.0-preview-00038-160914", "Microsoft.Build": "0.1.0-preview-00038-160914", "System.Runtime.Serialization.Xml": "4.1.0", - "NuGet.Build.Tasks": "3.6.0-beta.1.msbuild.9" + "NuGet.Build.Tasks": "3.6.0-beta.1.msbuild.9", + "Microsoft.TestPlatform.CLI": "15.0.0-preview-20160915-01" }, "frameworks": { "netcoreapp1.0": { diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/VSTestCommand.cs b/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/VSTestCommand.cs new file mode 100644 index 000000000..b191a4231 --- /dev/null +++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/VSTestCommand.cs @@ -0,0 +1,27 @@ +// 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.Cli.Utils; + +namespace Microsoft.DotNet.Tools.Test.Utilities +{ + public sealed class VSTestCommand: TestCommand + { + public VSTestCommand() + :base("dotnet") + { + } + + public override CommandResult Execute(string args = "") + { + args = $"vstest {args}"; + return base.Execute(args); + } + + public override CommandResult ExecuteWithCapturedOutput(string args = "") + { + args = $"vstest {args}"; + return base.ExecuteWithCapturedOutput(args); + } + } +} diff --git a/test/dotnet-vstest.Tests/VSTestTests.cs b/test/dotnet-vstest.Tests/VSTestTests.cs new file mode 100644 index 000000000..4a3a9b61a --- /dev/null +++ b/test/dotnet-vstest.Tests/VSTestTests.cs @@ -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.Tools.Test.Utilities; +using Xunit; +using System; +using System.IO; +using FluentAssertions; +using Microsoft.DotNet.TestFramework; +using Microsoft.DotNet.Cli.Utils; + +namespace Microsoft.DotNet.Cli.VSTest.Tests +{ + public class VSTestTests: TestBase + { + [Fact] + public void TestsFromAGivenContainerShouldRunWithExpectedOutput() + { + // Copy DotNetCoreTestProject project in output directory of project dotnet-vstest.Tests + string testAppName = "VSTestDotNetCoreProject"; + TestInstance testInstance = TestAssetsManager.CreateTestInstance(testAppName).WithLockFiles(); + + string testProjectDirectory = testInstance.TestRoot; + + // Build project DotNetCoreTestProject + new Build3Command() + .WithWorkingDirectory(testProjectDirectory) + .Execute() + .Should() + .Pass(); + + // Prepare args to send vstest + string configuration = Environment.GetEnvironmentVariable("CONFIGURATION") ?? "Debug"; + string testAdapterPath = Path.Combine(testProjectDirectory, "bin", configuration, "netcoreapp1.0"); + string outputDll = Path.Combine(testAdapterPath, $"{testAppName}.dll"); + string argsForVstest = string.Concat("\"", outputDll, "\"", " --TestAdapterPath:", "\"", testAdapterPath, "\""); + + // Call vstest + CommandResult result = new VSTestCommand().ExecuteWithCapturedOutput(argsForVstest); + + // Verify + result.StdOut.Should().Contain("Total tests: 2. Passed: 1. Failed: 1. Skipped: 0."); + result.StdOut.Should().Contain("Passed TestNamespace.VSTestTests.VSTestPassTest"); + result.StdOut.Should().Contain("Failed TestNamespace.VSTestTests.VSTestFailTest"); + } + } +} diff --git a/test/dotnet-vstest.Tests/dotnet-vstest.Tests.xproj b/test/dotnet-vstest.Tests/dotnet-vstest.Tests.xproj new file mode 100644 index 000000000..24fd898f5 --- /dev/null +++ b/test/dotnet-vstest.Tests/dotnet-vstest.Tests.xproj @@ -0,0 +1,21 @@ + + + + 14.0.23107 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 9f5ae280-a040-4160-9799-6504d907742d + Microsoft.DotNet.Cli.VSTest.Tests + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin + + + 2.0 + + + + + + \ No newline at end of file diff --git a/test/dotnet-vstest.Tests/project.json b/test/dotnet-vstest.Tests/project.json new file mode 100644 index 000000000..c22afc681 --- /dev/null +++ b/test/dotnet-vstest.Tests/project.json @@ -0,0 +1,24 @@ +{ + "version": "1.0.0-*", + "dependencies": { + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0" + }, + "System.Runtime.Serialization.Primitives": "4.1.1", + "Microsoft.DotNet.Tools.Tests.Utilities": { + "target": "project" + }, + "xunit": "2.2.0-beta3-build3330", + "dotnet-test-xunit": "1.0.0-rc2-330423-54" + }, + "frameworks": { + "netcoreapp1.0": { + "imports": [ + "dotnet5.4", + "portable-net451+win8" + ] + } + }, + "testRunner": "xunit" +}