diff --git a/src/app/Fake.Tools.Pickles/Fake.Tools.Pickles.fsproj b/src/app/Fake.Tools.Pickles/Fake.Tools.Pickles.fsproj
index 788dd9877ee..d50b8ee3a8b 100644
--- a/src/app/Fake.Tools.Pickles/Fake.Tools.Pickles.fsproj
+++ b/src/app/Fake.Tools.Pickles/Fake.Tools.Pickles.fsproj
@@ -5,14 +5,15 @@
Fake.Tools.Pickles
Library
-
+
$(DefineConstants);NETSTANDARD;USE_HTTPCLIENT
-
+
$(DefineConstants);RELEASE
+
diff --git a/src/app/Fake.Tools.Pickles/Pickles.fs b/src/app/Fake.Tools.Pickles/Pickles.fs
index e21c5596bb9..0f37e9fc03b 100644
--- a/src/app/Fake.Tools.Pickles/Pickles.fs
+++ b/src/app/Fake.Tools.Pickles/Pickles.fs
@@ -17,16 +17,16 @@
module Fake.Tools.Pickles
open System
-open System.Text
+open System.IO
+
open Fake.Core
open Fake.IO
open Fake.IO.Globbing
open Fake.IO.FileSystemOperators
-open System.IO
(*
.\packages\Pickles.CommandLine\tools\pickles.exe --help
-Pickles version 2.18.1.0
+Pickles version 2.19.0.0
-f, --feature-directory=VALUE
directory to start scanning recursively for
features
@@ -54,60 +54,70 @@ Pickles version 2.18.1.0
whether to enable comments in the output
--et, --excludeTags=VALUE
exclude scenarios that match this tag
-*)
+ --ht, --hideTags=VALUE Technical tags that shouldn't be displayed
+ (separated by ;)*)
/// Option which allows to specify if failure of pickles should break the build.
-type ErrorLevel =
- /// This option instructs FAKE to break the build if pickles fails to execute
- | Error
- /// With this option set, no exception is thrown if pickles fails to execute
- | DontFailBuild
+type ErrorLevel =
+ /// This option instructs FAKE to break the build if pickles fails to execute
+ | Error
+ /// With this option set, no exception is thrown if pickles fails to execute
+ | DontFailBuild
/// The format of the test results
type TestResultsFormat =
- | NUnit
- | NUnit3
- | XUnit
- | XUnit2
- | MSTest
- | CucumberJSON
- | SpecRun
- | VSTest
+ | NUnit
+ | NUnit3
+ | XUnit
+ | XUnit2
+ | MSTest
+ | CucumberJSON
+ | SpecRun
+ | VSTest
type DocumentationFormat =
- | DHTML
- | HTML
- | Word
- | JSON
- | Excel
+ | DHTML
+ | HTML
+ | Word
+ | JSON
+ | Excel
+ | CucumberJSON
/// The Pickles parameter type
type PicklesParams =
- { /// The path to the Pickles console tool: 'pickles.exe'
- ToolPath : string
- /// The directory to start scanning recursively for features
- FeatureDirectory: string
- /// The language of the feature files
- FeatureFileLanguage: string option
- /// The directory where output files will be placed
- OutputDirectory: string
- /// The format of the output documentation
- OutputFileFormat: DocumentationFormat
- /// the format of the linked test results
- TestResultsFormat: TestResultsFormat
- /// the paths to the linked test results files
- LinkedTestResultFiles: string list
- /// The name of the system under test
- SystemUnderTestName: string option
- /// The version of the system under test
- SystemUnderTestVersion: string option
- /// Maximum time to allow xUnit to run before being killed.
- TimeOut : TimeSpan
- /// Option which allows to specify if failure of pickles should break the build.
- ErrorLevel : ErrorLevel
- /// Option which allows to enable some experimental features
- IncludeExperimentalFeatures : bool option
- }
+ { /// The path to the Pickles console tool: 'pickles.exe'
+ ToolPath : string
+ /// The working directory
+ WorkingDir: string
+ /// The directory to start scanning recursively for features
+ FeatureDirectory: string
+ /// The language of the feature files
+ FeatureFileLanguage: string option
+ /// The directory where output files will be placed
+ OutputDirectory: string
+ /// The format of the output documentation
+ OutputFileFormat: DocumentationFormat
+ /// the format of the linked test results
+ TestResultsFormat: TestResultsFormat
+ /// the paths to the linked test results files
+ LinkedTestResultFiles: string list
+ /// The name of the system under test
+ SystemUnderTestName: string option
+ /// The version of the system under test
+ SystemUnderTestVersion: string option
+ /// Maximum time to allow xUnit to run before being killed.
+ TimeOut : TimeSpan
+ /// Option which allows to specify if failure of pickles should break the build.
+ ErrorLevel : ErrorLevel
+ /// Option which allows to enable some experimental features
+ IncludeExperimentalFeatures : bool option
+ /// As of version 2.6, Pickles includes Gherkin #-style comments. As of version 2.7, this inclusion is configurable.
+ EnableComments: bool option
+ /// exclude scenarios that match this tags
+ ExcludeTags: string list
+ /// Technical tags that shouldn't be displayed
+ HideTags: string list
+ }
let private currentDirectory = Directory.GetCurrentDirectory()
@@ -127,82 +137,141 @@ let private currentDirectory = Directory.GetCurrentDirectory()
/// - `TimeOut` - 5 minutes
/// - `ErrorLevel` - `Error`
/// - `IncludeExperimentalFeatures` - `None`
+/// - `EnableComments` - true
+/// - `ExcludeTags` - []
+/// - `HideTags` - []
let private PicklesDefaults =
- {
- ToolPath = Tools.findToolInSubPath "pickles.exe" currentDirectory
- FeatureDirectory = currentDirectory
- FeatureFileLanguage = None
- OutputDirectory = currentDirectory > "Documentation"
- OutputFileFormat = DHTML
- TestResultsFormat = NUnit
- LinkedTestResultFiles = []
- SystemUnderTestName = None
- SystemUnderTestVersion = None
- TimeOut = TimeSpan.FromMinutes 5.
- ErrorLevel = Error
- IncludeExperimentalFeatures = None
- }
+ {
+ ToolPath = Tools.findToolInSubPath "pickles.exe" currentDirectory
+ WorkingDir = currentDirectory
+ FeatureDirectory = null
+ FeatureFileLanguage = None
+ OutputDirectory = null
+ OutputFileFormat = DHTML
+ TestResultsFormat = NUnit
+ LinkedTestResultFiles = []
+ SystemUnderTestName = None
+ SystemUnderTestVersion = None
+ TimeOut = TimeSpan.FromMinutes 5.
+ ErrorLevel = Error
+ IncludeExperimentalFeatures = None
+ EnableComments = None
+ ExcludeTags = []
+ HideTags = []
+ }
let private buildPicklesArgs parameters =
- let outputFormat = match parameters.OutputFileFormat with
- | DHTML -> "dhtml"
- | HTML -> "html"
- | Word -> "word"
- | JSON -> "json"
- | Excel -> "excel"
-
- let testResultFormat = match parameters.LinkedTestResultFiles with
- | [] -> None
- | _ -> match parameters.TestResultsFormat with
- | NUnit -> Some "nunit"
- | NUnit3 -> Some "nunit3"
- | XUnit -> Some "xunit"
- | XUnit2 -> Some "xunit2"
- | MSTest -> Some "mstest"
- | CucumberJSON -> Some "cucumberjson"
- | SpecRun -> Some "specrun"
- | VSTest -> Some "vstest"
-
- let linkedResultFiles = match parameters.LinkedTestResultFiles with
- | [] -> None
- | _ -> parameters.LinkedTestResultFiles
- |> Seq.map (fun f -> sprintf "\"%s\"" f)
- |> String.concat ";"
- |> Some
- let experimentalFeatures = match parameters.IncludeExperimentalFeatures with
- | Some true -> Some "--exp"
- | _ -> None
+ let experimentalFeatures =
+ seq {
+ match parameters.IncludeExperimentalFeatures with
+ | Some true -> yield "--exp"
+ | _ -> ()
+ }
- new StringBuilder()
- |> StringBuilder.appendWithoutQuotes (sprintf " -f \"%s\"" parameters.FeatureDirectory)
- |> StringBuilder.appendWithoutQuotes (sprintf " -o \"%s\"" parameters.OutputDirectory)
- |> StringBuilder.appendIfSome parameters.SystemUnderTestName (sprintf " --sn %s")
- |> StringBuilder.appendIfSome parameters.SystemUnderTestVersion (sprintf " --sv %s")
- |> StringBuilder.appendIfSome parameters.FeatureFileLanguage (sprintf " -l %s")
- |> StringBuilder.appendWithoutQuotes (sprintf " --df %s" outputFormat)
- |> StringBuilder.appendIfSome testResultFormat (sprintf " --trfmt %s")
- |> StringBuilder.appendIfSome linkedResultFiles (sprintf " --lr %s")
- |> StringBuilder.appendIfSome experimentalFeatures (sprintf "%s")
- |> StringBuilder.toText
-
-module internal ResultHandling =
- let (|OK|Failure|) = function
- | 0 -> OK
- | x -> Failure x
+ let enableComments =
+ seq {
+ match parameters.EnableComments with
+ | Some true -> yield "--enableComments=true"
+ | Some false -> yield "--enableComments=false"
+ | _ -> ()
+ }
+
+ let yieldIfNotNullOrWhitespace paramName value =
+ seq {
+ if String.isNullOrWhiteSpace value
+ then ()
+ else
+ yield sprintf "-%s" paramName
+ yield value
+ }
+
+ let yieldIfSome paramName value =
+ seq {
+ match value with
+ | Some v ->
+ yield sprintf "--%s" paramName
+ yield v
+ | _ -> ()
+ }
+
+ let yieldTags paramName value =
+ seq {
+ match value with
+ | [] -> ()
+ | tags ->
+ yield sprintf "--%s" paramName
+ yield tags |> String.concat ";"
+ }
+
+ [
+ yield! parameters.FeatureDirectory |> yieldIfNotNullOrWhitespace "f"
+ yield! parameters.OutputDirectory |> yieldIfNotNullOrWhitespace "o"
+ yield! parameters.SystemUnderTestName |> yieldIfSome "sn"
+ yield! parameters.SystemUnderTestVersion |> yieldIfSome "sv"
+ yield! parameters.FeatureFileLanguage |> yieldIfSome "l"
+ yield! match parameters.OutputFileFormat |> string |> String.toLower with
+ | "html" -> None
+ | v -> Some v
+ |> yieldIfSome "df"
+ yield! match parameters.LinkedTestResultFiles with
+ | [] -> None
+ | _ -> parameters.TestResultsFormat
+ |> string
+ |> String.toLower
+ |> Some
+ |> yieldIfSome "trfmt"
+ yield! match parameters.LinkedTestResultFiles with
+ | [] -> None
+ | _ -> parameters.LinkedTestResultFiles
+ |> String.concat ";"
+ |> Some
+ |> yieldIfSome "lr"
+ yield! experimentalFeatures
+ yield! enableComments
+ yield! parameters.ExcludeTags |> yieldTags "et"
+ yield! parameters.HideTags |> yieldTags "ht"
+ ]
+ |> Arguments.OfArgs
+
+module internal ResultHandling =
+ let (|OK|Failure|) = function
+ | 0 -> OK
+ | x -> Failure x
- let buildErrorMessage = function
- | OK -> None
- | Failure errorCode ->
- Some (sprintf "Pickles reported an error (Error code %d)" errorCode)
+ let buildErrorMessage = function
+ | OK -> None
+ | Failure errorCode ->
+ Some (sprintf "Pickles reported an error (Error code %d)" errorCode)
- let failBuildWithMessage = function
- | DontFailBuild -> Trace.traceImportant
- | _ -> failwith
+ let failBuildWithMessage = function
+ | DontFailBuild -> Trace.traceImportant
+ | _ -> failwith
- let failBuildIfPicklesReportedError errorLevel =
- buildErrorMessage
- >> Option.iter (failBuildWithMessage errorLevel)
+ let failBuildIfPicklesReportedError errorLevel =
+ buildErrorMessage
+ >> Option.iter (failBuildWithMessage errorLevel)
+
+/// Builds the report generator command line arguments and process from the given parameters and reports
+/// [omit]
+let internal createProcess setParams =
+ let parameters = setParams PicklesDefaults
+ let args = buildPicklesArgs parameters
+ let tool = parameters.ToolPath
+
+ CreateProcess.fromCommand (RawCommand(tool, args))
+ |> CreateProcess.withFramework
+ |> CreateProcess.withWorkingDirectory parameters.WorkingDir
+ |> CreateProcess.withTimeout parameters.TimeOut
+ |> CreateProcess.addOnExited
+ (fun data exitCode ->
+ ResultHandling.failBuildIfPicklesReportedError parameters.ErrorLevel exitCode
+ data)
+ |> fun command ->
+ Trace.trace command.CommandLine
+ command
+
+
/// Runs pickles living documentation generator via the given tool
/// Will fail if the pickles command line tool terminates with a non zero exit code.
///
@@ -212,15 +281,11 @@ module internal ResultHandling =
/// ## Parameters
/// - `setParams` - Function used to manipulate the default `PicklesParams` value
let convert setParams =
- use __ = Trace.traceTask "Pickles" ""
- let parameters = setParams PicklesDefaults
- let makeProcessStartInfo info =
- { info with FileName = parameters.ToolPath
- WorkingDirectory = "."
- Arguments = parameters |> buildPicklesArgs }
- |> Process.withFramework
-
- let result = Process.execSimple makeProcessStartInfo parameters.TimeOut
+ use __ = Trace.traceTask "Pickles" "Generating documentations"
+
+ let result =
+ createProcess setParams
+ |> Proc.run
+ |> ignore
- ResultHandling.failBuildIfPicklesReportedError parameters.ErrorLevel result
- __.MarkSuccess()
+ __.MarkSuccess()
diff --git a/src/app/Fake.Tools.Pickles/VisibleTo.fs b/src/app/Fake.Tools.Pickles/VisibleTo.fs
new file mode 100644
index 00000000000..9a497f59ddc
--- /dev/null
+++ b/src/app/Fake.Tools.Pickles/VisibleTo.fs
@@ -0,0 +1,7 @@
+
+namespace System
+open System.Runtime.CompilerServices
+
+[]
+[]
+do ()
\ No newline at end of file
diff --git a/src/test/Fake.Core.UnitTests/Fake.Core.UnitTests.fsproj b/src/test/Fake.Core.UnitTests/Fake.Core.UnitTests.fsproj
index 9a4b46e464b..e488eddcf18 100644
--- a/src/test/Fake.Core.UnitTests/Fake.Core.UnitTests.fsproj
+++ b/src/test/Fake.Core.UnitTests/Fake.Core.UnitTests.fsproj
@@ -9,6 +9,7 @@
+
@@ -33,6 +34,7 @@
+
diff --git a/src/test/Fake.Core.UnitTests/Fake.DotNet.Testing.SpecFlow.fs b/src/test/Fake.Core.UnitTests/Fake.DotNet.Testing.SpecFlow.fs
index 7463d9f2738..3024aaff402 100644
--- a/src/test/Fake.Core.UnitTests/Fake.DotNet.Testing.SpecFlow.fs
+++ b/src/test/Fake.Core.UnitTests/Fake.DotNet.Testing.SpecFlow.fs
@@ -21,7 +21,7 @@ let runCreateProcess setParams =
let expectedPath = Path.Combine("specflow", "specflow.exe")
Expect.equal file expectedPath "Expected specflow.exe"
- expectedPath, (Command.RawCommand(file, Arguments.OfArgs args)).CommandLine
+ expectedPath, (RawCommand(file, args)).CommandLine
[]
let tests =
diff --git a/src/test/Fake.Core.UnitTests/Fake.Testing.ArgumentHelper.fs b/src/test/Fake.Core.UnitTests/Fake.Testing.ArgumentHelper.fs
index 6b0288f1149..51a653c956d 100644
--- a/src/test/Fake.Core.UnitTests/Fake.Testing.ArgumentHelper.fs
+++ b/src/test/Fake.Core.UnitTests/Fake.Testing.ArgumentHelper.fs
@@ -6,9 +6,14 @@ open Expecto
let checkIfMono (file, args) =
match Environment.isWindows, Process.monoPath with
| false, Some s when file = s ->
- Expect.isGreaterThanOrEqual args.Args.Length 3 "Expected mono arguments"
- Expect.equal args.Args.[0] "--debug" "Expected first flag to be '--debug'"
- args.Args.[1], Arguments.OfArgs args.Args.[2..]
+ match args.Args |> Array.toList with
+ | debugFlag :: file :: rest ->
+ Expect.equal debugFlag "--debug" "Expected first flag to be '--debug'"
+ file, Arguments.OfArgs rest
+ | a ->
+ Expect.isGreaterThanOrEqual a.Length 2 "Expected mono arguments"
+ file, args
+
| true, _ -> file, args
| _ ->
Trace.traceFAKE "Mono was not found in test!"
diff --git a/src/test/Fake.Core.UnitTests/Fake.Testing.ReportGenerator.fs b/src/test/Fake.Core.UnitTests/Fake.Testing.ReportGenerator.fs
index 7153af435e7..a81c8237f9f 100644
--- a/src/test/Fake.Core.UnitTests/Fake.Testing.ReportGenerator.fs
+++ b/src/test/Fake.Core.UnitTests/Fake.Testing.ReportGenerator.fs
@@ -21,7 +21,8 @@ let runCreateProcess setParams =
let expectedPath = Path.Combine("reportgenerator", "ReportGenerator.exe")
Expect.equal file expectedPath "Expected ReportGenerator.exe"
- expectedPath, (Command.RawCommand(file, Arguments.OfArgs args)).CommandLine
+
+ expectedPath, (RawCommand(file, args)).CommandLine
[]
let tests =
diff --git a/src/test/Fake.Core.UnitTests/Fake.Tools.Pickles.fs b/src/test/Fake.Core.UnitTests/Fake.Tools.Pickles.fs
new file mode 100644
index 00000000000..ac86b324d2c
--- /dev/null
+++ b/src/test/Fake.Core.UnitTests/Fake.Tools.Pickles.fs
@@ -0,0 +1,73 @@
+module Fake.Tools.Pickles.Tests
+
+open System.IO
+open Fake.Core
+open Fake.Testing
+open Fake.Tools
+open Expecto
+
+let runCreateProcess setParams =
+ let cp =
+ Pickles.createProcess
+ (fun param ->
+ { setParams param with
+ ToolPath = Path.Combine("pickles", "pickles.exe") } )
+
+ let file, args =
+ match cp.Command with
+ | RawCommand(file, args) -> file, args
+ | _ -> failwithf "expected RawCommand"
+ |> ArgumentHelper.checkIfMono
+
+ let expectedPath = Path.Combine("pickles", "pickles.exe")
+ Expect.equal file expectedPath "Expected pickles.exe"
+
+ expectedPath, (RawCommand(file, args)).CommandLine
+
+
+[]
+let tests =
+ testList "Fake.Tools.Pickles.Tests" [
+ testCase "Test that new argument generation works with minimal parameters" <| fun _ ->
+ let expectedPath, commandLine =
+ runCreateProcess id
+
+ Expect.equal
+ commandLine
+ (sprintf "%s --df dhtml" expectedPath)
+ "expected proper command line"
+
+ testCase "Test that new argument generation works with all parameters" <| fun _ ->
+ let expectedPath, commandLine =
+ runCreateProcess
+ (fun param ->
+ { param with
+ FeatureDirectory = "features"
+ OutputDirectory = "output"
+ SystemUnderTestName = Some "sut"
+ SystemUnderTestVersion = Some "sutver"
+ FeatureFileLanguage = Some "de"
+ OutputFileFormat = Pickles.DocumentationFormat.DHTML
+ LinkedTestResultFiles = [ "TestResult1.xml"; "TestResult2.xml" ]
+ TestResultsFormat = Pickles.TestResultsFormat.XUnit2
+ IncludeExperimentalFeatures = Some true
+ EnableComments = Some false
+ ExcludeTags = [ "et1"; "et2" ]
+ HideTags = [ "ht1"; "ht2" ] })
+
+ Expect.equal
+ commandLine
+ (sprintf "%s -f features -o output --sn sut --sv sutver --l de --df dhtml --trfmt xunit2 --lr TestResult1.xml;TestResult2.xml --exp --enableComments=false --et et1;et2 --ht ht1;ht2" expectedPath) "expected proper command line"
+
+ testCase "Test that output file format is ommitted if it is HTML" <| fun _ ->
+ let expectedPath, commandLine =
+ runCreateProcess
+ (fun param ->
+ { param with
+ OutputFileFormat = Pickles.DocumentationFormat.HTML })
+
+ Expect.equal
+ commandLine
+ (sprintf "%s " expectedPath)
+ "expected proper command line"
+ ]