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"
+}