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

Xunit2 support WIP #575

Merged
merged 6 commits into from
Oct 30, 2014
Merged
Show file tree
Hide file tree
Changes from 5 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
1 change: 1 addition & 0 deletions src/app/FakeLib/FakeLib.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
<Compile Include="UnitTest\NUnit\Sequential.fs" />
<Compile Include="UnitTest\NUnit\Parallel.fs" />
<Compile Include="UnitTest\XUnitHelper.fs" />
<Compile Include="UnitTest\XUnit2Helper.fs" />
<Compile Include="UnitTest\MSpecHelper.fs" />
<Compile Include="UnitTest\MSTest.fs" />
<Compile Include="UnitTest\ProcessTestRunner.fs" />
Expand Down
192 changes: 192 additions & 0 deletions src/app/FakeLib/UnitTest/XUnit2Helper.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
[<AutoOpen>]
Copy link
Member

Choose a reason for hiding this comment

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

please remove this. We try to get rid of autoopen

/// Contains tasks to run [xUnit](http://xunit.codeplex.com/) unit tests.
module Fake.XUnit2Helper

open System
open System.IO
open System.Text

(*
Copy link
Member

Choose a reason for hiding this comment

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

do we need this?

Copy link
Author

Choose a reason for hiding this comment

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

autoopen or the rest?
Keep in mind this is a copy of the XUnitHelper.

Copy link
Member

Choose a reason for hiding this comment

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

please remove the autoopen

2014-10-28 13:03 GMT+01:00 Sotirios Mantziaris notifications@github.com:

In src/app/FakeLib/UnitTest/XUnit2Helper.fs:

@@ -0,0 +1,192 @@
+[]
+/// Contains tasks to run xUnit unit tests.
+module Fake.XUnit2Helper
+
+open System
+open System.IO
+open System.Text
+
+(*

autoopen or the rest?
Keep in mind this is a copy of the XUnitHelper.


Reply to this email directly or view it on GitHub
https://github.com/fsharp/FAKE/pull/575/files#r19465721.

xUnit.net console test runner (64-bit .NET 4.0.30319.34209)
Copyright (C) 2014 Outercurve Foundation.

usage: xunit.console <assemblyFile> [configFile] [options]

Valid options:
-parallel option : set parallelization based on option
: none - turn off all parallelization
: collections - only parallelize collections
: assemblies - only parallelize assemblies
: all - parallelize assemblies & collections
-maxthreads count : maximum thread count for collection parallelization
: 0 - run with unbounded thread count
: >0 - limit task thread pool size to 'count'
-silent : do not output running test count
-noshadow : do not shadow copy assemblies
-teamcity : forces TeamCity mode (normally auto-detected)
-appveyor : forces AppVeyor CI mode (normally auto-detected)
-wait : wait for input after completion
-trait "name=value" : only run tests with matching name/value traits
: if specified more than once, acts as an OR operation
-notrait "name=value" : do not run tests with matching name/value traits
: if specified more than once, acts as an AND operation
-xml <filename> : output results to xUnit.net v2 style XML file
-xmlv1 <filename> : output results to xUnit.net v1 style XML file
-html <filename> : output results to HTML file
*)

type ParallelOption =
| None = 0
| Collections = 1
| Assemblies = 2
| All = 3

/// Option which allows to specify if an xUnit error should break the build.
type XUnit2ErrorLevel = TestRunnerErrorLevel // a type alias to keep backwards compatibility

/// The xUnit parameter type
type XUnit2Params =
{ /// The path to the xunit.console.exe - FAKE will scan all subfolders to find it automatically.
ToolPath : string
/// The file name of the config file (optional).
ConfigFile : string
/// set parallelization based on option
/// none - turn off all parallelization
/// collections - only parallelize collections
/// assemblies - only parallelize assemblies
/// all - parallelize assemblies & collections
Parallel : ParallelOption
/// maximum thread count for collection parallelization
/// 0 - run with unbounded thread count
/// >0 - limit task thread pool size to 'count'
MaxThreads : int
/// Output running test count
Silent : bool
/// Shadow copy
ShadowCopy : bool
/// forces TeamCity mode (normally auto-detected)
Teamcity : bool
/// forces AppVeyor CI mode (normally auto-detected)
Appveyor : bool
// wait for input after completion
Wait : bool
/// The working directory (optional).
WorkingDir : string
/// If the timeout is reached the xUnit task will be killed. Default is 5 minutes.
TimeOut : TimeSpan
/// Test runner error level. Option which allows to specify if an xUnit error should break the build.
ErrorLevel : XUnit2ErrorLevel
/// Include named traits with comma separated values
IncludeTraits : (string * string) option
/// Exclude named traits with comma separated values
ExcludeTraits : (string * string) option
/// output results to xUnit.net v2 style XML file
XmlOutput : bool
/// output results to xUnit.net v1 style XML file
XmlOutputV1 : bool
/// output results to HTML file
HtmlOutput : bool
/// output directory
OutputDir : string }

/// The xUnit default parameters
let empty2Trait : (string * string) option = None

let XUnit2Defaults =
{ ToolPath = findToolInSubPath "xunit.console.exe" (currentDirectory @@ "tools" @@ "xUnit")
ConfigFile = null
Parallel = ParallelOption.None
MaxThreads = 0
Silent = false
ShadowCopy = true
Teamcity = false
Appveyor = false
Wait = false
WorkingDir = null
TimeOut = TimeSpan.FromMinutes 5.
ErrorLevel = Error
IncludeTraits = empty2Trait
ExcludeTraits = empty2Trait
XmlOutput = false
XmlOutputV1 = false
HtmlOutput = false
OutputDir = null }

/// Builds the command line arguments from the given parameter record and the given assemblies.
/// [omit]
let buildXUnit2Args parameters assembly =
let fi = fileInfo assembly
let name = fi.Name

let dir =
if isNullOrEmpty parameters.OutputDir then String.Empty
else Path.GetFullPath parameters.OutputDir

let traits includeExclude (name, values : string) =
values.Split([| ',' |], System.StringSplitOptions.RemoveEmptyEntries)
|> Seq.collect (fun value ->
[| includeExclude
sprintf "\"%s=%s\"" name value |])
|> String.concat " "

let parallelOptionsText =
parameters.Parallel.ToString().ToLower()

new StringBuilder()
|> appendFileNamesIfNotNull [ assembly ]
|> append "-parallel"
|> append (sprintf "%s" parallelOptionsText)
|> append "-maxthreads"
|> append (sprintf "%i" parameters.MaxThreads)
|> appendIfFalse parameters.ShadowCopy "-noshadow"
|> appendIfTrue (buildServer = TeamCity) "-teamcity"
|> appendIfTrue (buildServer = AppVeyor) "-appveyor"
|> appendIfTrue parameters.Wait "-wait"
|> appendIfTrue parameters.Silent "-silent"
|> appendIfTrue parameters.XmlOutput (sprintf "-xml\" \"%s" (dir @@ (name + ".xml")))
|> appendIfTrue parameters.XmlOutputV1 (sprintf "-xmlv1\" \"%s" (dir @@ (name + ".xml")))
|> appendIfTrue parameters.HtmlOutput (sprintf "-html\" \"%s" (dir @@ (name + ".html")))
|> appendIfSome parameters.IncludeTraits (traits "-trait")
|> appendIfSome parameters.ExcludeTraits (traits "-notrait")
|> toText


/// Runs xUnit unit tests in the given assemblies via the given xUnit runner.
/// Will fail if the runner terminates with non-zero exit code for any of the assemblies.
/// Offending assemblies will be listed in the error message.
///
/// The xUnit runner terminates with a non-zero exit code if any of the tests
/// in the given assembly fail.
/// ## Parameters
///
/// - `setParams` - Function used to manipulate the default XUnitParams value.
/// - `assemblies` - Sequence of one or more assemblies containing xUnit unit tests.
///
/// ## Sample usage
///
/// Target "Test" (fun _ ->
/// !! (testDir + @"\xUnit.Test.*.dll")
/// |> xUnit (fun p -> {p with OutputDir = testDir })
/// )
let xUnit2 setParams assemblies =
let details = separated ", " assemblies
traceStartTask "xUnit2" details
let parameters = setParams XUnit2Defaults

let runTests assembly =
let args = buildXUnit2Args parameters assembly
0 = ExecProcess (fun info ->
info.FileName <- parameters.ToolPath
info.WorkingDirectory <- parameters.WorkingDir
info.Arguments <- args) parameters.TimeOut

let failedTests =
[ for asm in List.ofSeq assemblies do
if runTests asm |> not then yield asm ]

if not (List.isEmpty failedTests) then
sprintf "xUnit2 failed for the following assemblies: %s" (separated ", " failedTests)
|> match parameters.ErrorLevel with
| Error | FailOnFirstError -> failwith
| DontFailBuild -> traceImportant
traceEndTask "xUnit2" details
1 change: 1 addition & 0 deletions src/test/Test.FAKECore/Test.FAKECore.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@
<Compile Include="FileHandling\CleanDirectorySpecs.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="FileHandling\GlobbingSpecs.cs" />
<Compile Include="XUnit2HelperSpecs.cs" />
<Compile Include="XUnitHelperSpecs.cs" />
</ItemGroup>
<ItemGroup>
Expand Down
29 changes: 29 additions & 0 deletions src/test/Test.FAKECore/XUnit2HelperSpecs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System;
using Fake;
using Machine.Specifications;
using Microsoft.FSharp.Core;

namespace Test.FAKECore
{
public class XUnit2HelperSpecs
{
It args_should_not_include_traits = () => BuildXUnit2Args(XUnit2Helper.empty2Trait, XUnit2Helper.empty2Trait).ShouldNotContain("trait");
It args_should_include_one_trait = () => BuildXUnit2Args(Trait("name", "value"), XUnit2Helper.empty2Trait).ShouldContain(@" -trait ""name=value""");
It args_should_include_two_traits = () => BuildXUnit2Args(Trait("name", "value1,value2"), XUnit2Helper.empty2Trait).ShouldContain(@" -trait ""name=value1"" -trait ""name=value2""");
It args_should_exclude_one_trait = () => BuildXUnit2Args(XUnit2Helper.empty2Trait, Trait("name", "value")).ShouldContain(@"-notrait ""name=value""");
It args_should_exclude_two_traits = () => BuildXUnit2Args(XUnit2Helper.empty2Trait, Trait("name", "value1,value2")).ShouldContain(@" -notrait ""name=value1"" -notrait ""name=value2""");
It args_should_contain_paraller = () => BuildXUnit2Args(XUnit2Helper.empty2Trait, XUnit2Helper.empty2Trait).ShouldContain(@"-parallel");

private static FSharpOption<Tuple<string, string>> Trait(string name, string values)
{
return new FSharpOption<Tuple<string, string>>(new Tuple<string, string>(name,values));
}

private static string BuildXUnit2Args(FSharpOption<Tuple<string, string>> includeTrait, FSharpOption<Tuple<string, string>> excludeTrait)
{
var parameters = new XUnit2Helper.XUnit2Params("", "", XUnit2Helper.ParallelOption.None, 0, false, false,
true, false, false,null, TimeSpan.FromMinutes(5), UnitTestCommon.TestRunnerErrorLevel.Error, includeTrait, excludeTrait, false, false, true, "");
return XUnit2Helper.buildXUnit2Args(parameters, "test.dll");
}
}
}