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

Port VSTest to FAKE 5 #2008

Merged
merged 8 commits into from
Jul 21, 2018
Merged
Show file tree
Hide file tree
Changes from 3 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
15 changes: 15 additions & 0 deletions Fake.sln
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "Fake.DotNet.Cli.Integration
EndProject
Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "Fake.Core.UserInput", "src\app\Fake.Core.UserInput\Fake.Core.UserInput.fsproj", "{3B0A5EE3-6696-4EBA-BCF9-8136C7F17040}"
EndProject
Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "Fake.DotNet.Testing.VSTest", "src\app\Fake.DotNet.Testing.VSTest\Fake.DotNet.Testing.VSTest.fsproj", "{C4C9D7EE-6A52-42F1-9E04-7C44F0EA8922}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -972,6 +974,18 @@ Global
{3B0A5EE3-6696-4EBA-BCF9-8136C7F17040}.Release|x64.Build.0 = Release|Any CPU
{3B0A5EE3-6696-4EBA-BCF9-8136C7F17040}.Release|x86.ActiveCfg = Release|Any CPU
{3B0A5EE3-6696-4EBA-BCF9-8136C7F17040}.Release|x86.Build.0 = Release|Any CPU
{C4C9D7EE-6A52-42F1-9E04-7C44F0EA8922}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C4C9D7EE-6A52-42F1-9E04-7C44F0EA8922}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C4C9D7EE-6A52-42F1-9E04-7C44F0EA8922}.Debug|x64.ActiveCfg = Debug|Any CPU
{C4C9D7EE-6A52-42F1-9E04-7C44F0EA8922}.Debug|x64.Build.0 = Debug|Any CPU
{C4C9D7EE-6A52-42F1-9E04-7C44F0EA8922}.Debug|x86.ActiveCfg = Debug|Any CPU
{C4C9D7EE-6A52-42F1-9E04-7C44F0EA8922}.Debug|x86.Build.0 = Debug|Any CPU
{C4C9D7EE-6A52-42F1-9E04-7C44F0EA8922}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C4C9D7EE-6A52-42F1-9E04-7C44F0EA8922}.Release|Any CPU.Build.0 = Release|Any CPU
{C4C9D7EE-6A52-42F1-9E04-7C44F0EA8922}.Release|x64.ActiveCfg = Release|Any CPU
{C4C9D7EE-6A52-42F1-9E04-7C44F0EA8922}.Release|x64.Build.0 = Release|Any CPU
{C4C9D7EE-6A52-42F1-9E04-7C44F0EA8922}.Release|x86.ActiveCfg = Release|Any CPU
{C4C9D7EE-6A52-42F1-9E04-7C44F0EA8922}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -1046,6 +1060,7 @@ Global
{29B66A06-1A45-4D65-AC31-7D746449E5D6} = {872B282D-8A3E-459A-B63D-C43C5D73506D}
{48ECC58D-468C-4D44-98B3-854C21EB0D40} = {E09B72E4-D890-46A8-8D14-7367C2E23E9D}
{3B0A5EE3-6696-4EBA-BCF9-8136C7F17040} = {7BFFAE76-DEE9-417A-A79B-6A6644C4553A}
{C4C9D7EE-6A52-42F1-9E04-7C44F0EA8922} = {7BFFAE76-DEE9-417A-A79B-6A6644C4553A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {058A0C5E-2216-4306-8AFB-0AE28320C26A}
Expand Down
1 change: 1 addition & 0 deletions build.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ let dotnetAssemblyInfos =
"Fake.DotNet.Testing.Expecto", "Running expecto test runner"
"Fake.DotNet.Testing.MSpec", "Running mspec test runner"
"Fake.DotNet.Testing.MSTest", "Running mstest test runner"
"Fake.DotNet.Testing.VSTest", "Running vstest test runner"
"Fake.DotNet.Testing.NUnit", "Running nunit test runner"
"Fake.DotNet.Testing.OpenCover", "Code coverage with OpenCover"
"Fake.DotNet.Testing.SpecFlow", "BDD with Gherkin and SpecFlow"
Expand Down
17 changes: 17 additions & 0 deletions src/app/Fake.DotNet.Testing.VSTest/AssemblyInfo.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Auto-Generated by FAKE; do not edit
namespace System
open System.Reflection

[<assembly: AssemblyTitleAttribute("FAKE - F# Make Running VSTest test runner")>]
[<assembly: AssemblyProductAttribute("FAKE - F# Make")>]
[<assembly: AssemblyVersionAttribute("5.1.0")>]
[<assembly: AssemblyInformationalVersionAttribute("5.1.0")>]
[<assembly: AssemblyFileVersionAttribute("5.1.0")>]
do ()

module internal AssemblyVersionInformation =
let [<Literal>] AssemblyTitle = "FAKE - F# Make Running VSTest test runner"
let [<Literal>] AssemblyProduct = "FAKE - F# Make"
let [<Literal>] AssemblyVersion = "5.1.0"
let [<Literal>] AssemblyInformationalVersion = "5.1.0"
let [<Literal>] AssemblyFileVersion = "5.1.0"
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<TargetFrameworks>net46;netstandard1.6;netstandard2.0</TargetFrameworks>
<DefineConstants>$(DefineConstants);NO_DOTNETCORE_BOOTSTRAP</DefineConstants>
<AssemblyName>Fake.DotNet.Testing.MSTest</AssemblyName>
<OutputType>Library</OutputType>
</PropertyGroup>
<PropertyGroup>
<DefineConstants>$(DefineConstants);NETSTANDARD;USE_HTTPCLIENT</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DefineConstants>$(DefineConstants);RELEASE</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Compile Include="AssemblyInfo.fs" />
<Compile Include="VSTest.fs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Fake.Core.Environment\Fake.Core.Environment.fsproj" />
<ProjectReference Include="..\Fake.Core.Trace\Fake.Core.Trace.fsproj" />
<ProjectReference Include="..\Fake.Core.Process\Fake.Core.Process.fsproj" />
<ProjectReference Include="..\Fake.Core.String\Fake.Core.String.fsproj" />
<ProjectReference Include="..\Fake.Testing.Common\Fake.Testing.Common.fsproj" />
</ItemGroup>
<Import Project="..\..\..\.paket\Paket.Restore.targets" />
</Project>
150 changes: 150 additions & 0 deletions src/app/Fake.DotNet.Testing.VSTest/VSTest.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
/// Contains tasks to run [VSTest](https://msdn.microsoft.com/en-us/library/ms182486.aspx) unit tests.
module Fake.DotNet.Testing.VSTest
Copy link
Member

Choose a reason for hiding this comment

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

please add [<RequireQualifiedAccess>]


open Fake.Core
open Fake.Testing.Common
open System
open System.Text

/// [omit]
let vsTestPaths =
Copy link
Member

Choose a reason for hiding this comment

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

internal?

[|
@"[ProgramFilesX86]\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\CommonExtensions\Microsoft\TestWindow"
@"[ProgramFilesX86]\Microsoft Visual Studio 14.0\Common7\IDE\CommonExtensions\Microsoft\TestWindow"
@"[ProgramFilesX86]\Microsoft Visual Studio 12.0\Common7\IDE\CommonExtensions\Microsoft\TestWindow"
@"[ProgramFilesX86]\Microsoft Visual Studio 11.0\Common7\IDE\CommonExtensions\Microsoft\TestWindow"
|]

/// [omit]
let vsTestExe =
if Environment.isMono then failwith "VSTest is not supported on the mono platform"
else "vstest.console.exe"

/// Option which allow to specify if a VSTest error should break the build.
type ErrorLevel = TestRunnerErrorLevel

/// Parameter type to configure [VSTest.Console.exe](https://msdn.microsoft.com/en-us/library/jj155800.aspx)
[<CLIMutable>]
Copy link
Member

Choose a reason for hiding this comment

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

remove CliMutable

type VSTestParams =
{ /// Path to the run settings file to run tests with additional settings such as data collectors (optional).
SettingsPath : string
/// Names of the tests that should be run (optional).
Tests : seq<string>
/// Enables code coverage collection (optional).
EnableCodeCoverage : bool
/// Run the tests in an isolated process (optional).
InIsolation : bool
/// Use installed VSIX extensions in VSTest (optional).
UseVsixExtensions : bool
/// Target platform architecture for test execution (optional). Valid options include "x86", "x64" and "ARM".
Platform : string
/// Target .NET framework version to use for test execution (optional).
Framework : string
/// Run tests that match the given expression (optional). Cannot be used with the Tests argument
TestCaseFilter : string
/// The logger to use for test results (optional).
Logger : string
/// List discovered tests from the given container path (optional).
ListTestsPath : string
/// List installed test discoverers (optional).
ListDiscoverers : bool
/// List installed test executors (optional).
ListExecutors : bool
/// List installed loggers (optional).
ListLoggers : bool
/// List installed settings providers (optional).
ListSettingsProviders : bool
/// Path to VSTest.Console.exe (optional). By default the default install location is searched.
ToolPath : string
/// Working directory (optional).
WorkingDir : string
/// A timeout for the test runner (optional).
TimeOut : TimeSpan
/// Error level for controlling how VSTest failures should break the build (optional).
ErrorLevel : ErrorLevel
/// Path to test adapter e.g. xUnit (optional)
TestAdapterPath: string}

/// VSTest default parameters.
let VSTestDefaults =
Copy link
Member

Choose a reason for hiding this comment

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

internal

{ SettingsPath = null
Tests = []
EnableCodeCoverage = false
InIsolation = true
UseVsixExtensions = false
Platform = null
Framework = null
TestCaseFilter = null
Logger = null
ListTestsPath = null
ListDiscoverers = false
ListExecutors = false
ListLoggers = false
ListSettingsProviders = false
ToolPath =
match Process.tryFindFile vsTestPaths vsTestExe with
| Some path -> path
| None -> ""
WorkingDir = null
TimeOut = TimeSpan.MaxValue
ErrorLevel = ErrorLevel.Error
TestAdapterPath = null }

/// Builds the command line arguments from the given parameter record and the given assemblies.
/// [omit]
let buildVSTestArgs (parameters : VSTestParams) assembly =
Copy link
Member

Choose a reason for hiding this comment

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

internal?

let testsToRun =
if not (Seq.isEmpty parameters.Tests) then
sprintf @"/Tests:%s" (parameters.Tests |> String.separated ",")
else null
new StringBuilder()
|> StringBuilder.appendIfTrue (assembly <> null) assembly
|> StringBuilder.appendIfNotNull parameters.SettingsPath "/Settings:"
|> StringBuilder.appendIfTrue (testsToRun <> null) testsToRun
|> StringBuilder.appendIfTrue parameters.EnableCodeCoverage "/EnableCodeCoverage"
|> StringBuilder.appendIfTrue parameters.InIsolation "/InIsolation"
|> StringBuilder.appendIfTrue parameters.UseVsixExtensions "/UseVsixExtensions:true"
|> StringBuilder.appendIfNotNull parameters.Platform "/Platform:"
|> StringBuilder.appendIfNotNull parameters.Framework "/Framework:"
|> StringBuilder.appendIfNotNull parameters.TestCaseFilter "/TestCaseFilter:"
|> StringBuilder.appendIfNotNull parameters.Logger "/Logger:"
|> StringBuilder.appendIfNotNull parameters.ListTestsPath "/ListTests:"
|> StringBuilder.appendIfTrue parameters.ListDiscoverers "/ListDiscoverers"
|> StringBuilder.appendIfTrue parameters.ListExecutors "/ListExecutors"
|> StringBuilder.appendIfTrue parameters.ListLoggers "/ListLoggers"
|> StringBuilder.appendIfTrue parameters.ListSettingsProviders "/ListSettingsProviders"
|> StringBuilder.appendIfNotNull parameters.TestAdapterPath "/TestAdapterPath:"
|> StringBuilder.toText

/// Runs VSTest command line tool (VSTest.Console.exe) on a group of assemblies.
/// ## Parameters
///
/// - `setParams` - Function used to manipulate the default VSTestParams values.
/// - `assemblies` - Sequence of one or more assemblies containing Microsoft Visual Studio Unit Test Framework unit tests.
///
/// ## Sample usage
///
/// Target.create "Test" (fun _ ->
/// !! (testDir + @"\*.Tests.dll")
/// |> VSTest.VSTest (fun p -> { p with SettingsPath = "Local.RunSettings" })
/// )
let VSTest (setParams : VSTestParams -> VSTestParams) (assemblies : string seq) =
Copy link
Member

Choose a reason for hiding this comment

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

Maybe rename that such that it looks like VSTest.run for example (look how other runners call it).

let details = assemblies |> String.separated ", "
use __ = Trace.traceTask "VSTest" details
let parameters = VSTestDefaults |> setParams
if String.IsNullOrEmpty parameters.ToolPath then failwith "VSTest: No tool path specified, or it could not be found automatically."
let assemblies = assemblies |> Seq.toArray
if Array.isEmpty assemblies then failwith "VSTest: cannot run tests (the assembly list is empty)."
let failIfError assembly exitCode =
if exitCode > 0 && parameters.ErrorLevel <> ErrorLevel.DontFailBuild then
let message = sprintf "%sVSTest test run failed for %s" Environment.NewLine assembly
Trace.traceError message
failwith message
for assembly in assemblies do
let args = buildVSTestArgs parameters assembly
Process.execSimple (fun info ->
{ info with
FileName = parameters.ToolPath
WorkingDirectory = parameters.WorkingDir
Arguments = args }) parameters.TimeOut
|> failIfError assembly
4 changes: 4 additions & 0 deletions src/app/Fake.DotNet.Testing.VSTest/paket.references
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
group netcore

FSharp.Core
NETStandard.Library