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

Add class and file filter parameters to Fake.Testing.ReportGenerator #2120

Merged
merged 2 commits into from
Oct 11, 2018
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
</PropertyGroup>
<ItemGroup>
<Compile Include="AssemblyInfo.fs" />
<Compile Include="VisibleTo.fs" />
<Compile Include="ReportGenerator.fs" />
</ItemGroup>
<ItemGroup>
Expand Down
140 changes: 96 additions & 44 deletions src/app/Fake.Testing.ReportGenerator/ReportGenerator.fs
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,27 @@
module Fake.Testing.ReportGenerator

open System
open System.Text
open System.IO

open Fake.Core
open Fake.IO
open Fake.IO.Globbing
open Fake.IO.FileSystemOperators

type ReportType =
| Html = 0
| HtmlSummary = 1
| Xml = 2
| XmlSummary = 3
| Latex = 4
| LatexSummary = 5
| Badges = 6
| Html
| HtmlChart
| HtmlInline
| HtmlSummary
| MHtml
| PngChart
| TextSummary
| Xml
| XmlSummary
| Latex
| LatexSummary
| Badges
| CsvSummary

type LogVerbosity =
| Verbose = 0
Expand All @@ -38,7 +45,8 @@ type LogVerbosity =

/// ReportGenerator parameters, for more details see: https://github.com/danielpalme/ReportGenerator.
type ReportGeneratorParams =
{ /// (Required) Path to the ReportGenerator exe file.
{
/// (Required) Path to the ReportGenerator exe file.
ExePath : string
/// (Required) The directory where the generated report should be saved.
TargetDir : string
Expand All @@ -50,9 +58,22 @@ type ReportGeneratorParams =
/// Can be used in future reports to show coverage evolution.
HistoryDir : string
/// Optional list of assemblies that should be included or excluded
/// in the report. Exclusion filters take precedence over inclusion
/// in the report e.g. "-Foo.Test" (default is "+*")
/// Exclusion filters take precedence over inclusion
/// filters. Wildcards are allowed.
Filters : string list
/// Optional list of files that should be included or excluded
/// in the report e.g. "-*.xaml.cs" or "+*.cs" (default is "+*")
/// Exclusion filters take precedence over inclusion
/// filters. Wildcards are allowed.
FileFilters: string list
/// Optional list of classes that should be included or excluded
/// in the report e.g. "-*Tests" (default is "+*")
/// Exclusion filters take precedence over inclusion
/// filters. Wildcards are allowed.
ClassFilters: string list
/// Optional tag or build version
Tag: string option
/// The verbosity level of the log messages.
LogVerbosity : LogVerbosity
/// The directory where the ReportGenerator process will be started.
Expand All @@ -61,56 +82,87 @@ type ReportGeneratorParams =
TimeOut : TimeSpan }

let private currentDirectory = Directory.GetCurrentDirectory ()
let private toolname = "ReportGenerator.exe"

/// ReportGenerator default parameters
let private ReportGeneratorDefaultParams =
{ ExePath = "./tools/ReportGenerator/bin/ReportGenerator.exe"
{ ExePath = Tools.findToolInSubPath toolname (currentDirectory </> "tools" </> "ReportGenerator")
TargetDir = currentDirectory
ReportTypes = [ ReportType.Html ]
SourceDirs = []
HistoryDir = String.Empty
HistoryDir = null
Filters = []
FileFilters = []
ClassFilters = []
Tag = None
LogVerbosity = LogVerbosity.Verbose
WorkingDir = currentDirectory
TimeOut = TimeSpan.FromMinutes 5. }

/// Builds the report generator command line arguments from the given parameters and reports
/// Builds the report generator command line arguments and process from the given parameters and reports
/// [omit]
let private buildReportGeneratorArgs parameters (reports : string seq) =
let reportTypes = parameters.ReportTypes |> List.map (fun rt -> rt.ToString())
let sourceDirs = sprintf "-sourcedirs:%s" (String.Join(";", parameters.SourceDirs))
let filters = sprintf "-filters:%s" (String.Join(";", parameters.Filters))

new StringBuilder()
|> StringBuilder.append (sprintf "-reports:%s" (String.Join(";", reports)))
|> StringBuilder.append (sprintf "-targetdir:%s" parameters.TargetDir)
|> StringBuilder.appendWithoutQuotes (sprintf "-reporttypes:%s" (String.Join(";", reportTypes)))
|> StringBuilder.appendIfTrue (parameters.SourceDirs.Length > 0) sourceDirs
|> StringBuilder.appendStringIfValueIsNotNullOrEmpty (parameters.HistoryDir) (sprintf "-historydir:%s" parameters.HistoryDir)
|> StringBuilder.appendIfTrue (parameters.Filters.Length > 0) filters
|> StringBuilder.appendWithoutQuotes (sprintf "-verbosity:%s" (parameters.LogVerbosity.ToString()))
|> StringBuilder.toText
let internal createProcess setParams (reports : string seq) =
let parameters = setParams ReportGeneratorDefaultParams
let tool = parameters.ExePath

let joinWithSemicolon (xs: string seq) = String.Join(";", xs)

let yieldIfSome paramName (value: string option) =
seq { match value with
| None -> ()
| Some v -> yield sprintf "-%s:%s" paramName v }

let yieldIfNotEmpty paramName (value: string seq) =
seq { match value |> Seq.toList with
| [] -> ()
| xs -> yield sprintf "-%s:%s" paramName (xs |> joinWithSemicolon) }

let yieldIfNotNullOrEmpty paramName value =
seq { if String.isNotNullOrEmpty value
then yield sprintf "-%s:%s" paramName value }

let args =
[
yield! reports |> yieldIfNotEmpty "reports"
yield sprintf "-targetdir:%s" parameters.TargetDir

yield! parameters.ReportTypes
|> List.map (fun rt -> rt.ToString())
|> yieldIfNotEmpty "reporttypes"

yield! parameters.SourceDirs |> yieldIfNotEmpty "sourcedirs"
yield! parameters.HistoryDir |> yieldIfNotNullOrEmpty "historydir"
yield! parameters.Filters |> yieldIfNotEmpty "assemblyfilters"
yield! parameters.ClassFilters |> yieldIfNotEmpty "classfilters"
yield! parameters.FileFilters |> yieldIfNotEmpty "filefilters"
yield! parameters.Tag |> yieldIfSome "tag"
yield sprintf "-verbosity:%s" (parameters.LogVerbosity.ToString())
]
|> Arguments.OfArgs

CreateProcess.fromCommand (RawCommand(tool, args))
|> CreateProcess.withFramework
|> CreateProcess.withWorkingDirectory parameters.WorkingDir
|> CreateProcess.ensureExitCode
|> fun command ->
Trace.trace command.CommandLine
command

/// Runs ReportGenerator on one or more coverage reports.
/// ## Parameters
///
/// - `setParams` - Function used to overwrite the default ReportGenerator parameters.
/// - `reports` - Coverage reports.
let generateReports setParams (reports : string list) =
let taskName = "ReportGenerator"
let description = "Generating reports"

use __ = Trace.traceTask taskName description
let param = setParams ReportGeneratorDefaultParams

let processArgs = buildReportGeneratorArgs param reports
Trace.tracefn "ReportGenerator command\n%s %s" param.ExePath processArgs

let processStartInfo info =
{ info with FileName = param.ExePath
WorkingDirectory = if param.WorkingDir |> String.isNullOrEmpty then info.WorkingDirectory else param.WorkingDir
Arguments = processArgs } |> Process.withFramework
match Process.execSimple processStartInfo param.TimeOut with
| 0 -> ()
| v -> failwithf "ReportGenerator reported errors: %i" v
__.MarkSuccess()
use __ = Trace.traceTask "ReportGenerator" "Generating reports"

match reports with
| [] ->
Trace.trace "No reports given. Ignoring task"
| reports ->
reports
|> createProcess setParams
|> Proc.run
|> ignore

__.MarkSuccess()
7 changes: 7 additions & 0 deletions src/app/Fake.Testing.ReportGenerator/VisibleTo.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

namespace System
open System.Runtime.CompilerServices

[<assembly: InternalsVisibleTo("Fake.Core.IntegrationTests")>]
[<assembly: InternalsVisibleTo("Fake.Core.UnitTests")>]
do ()
2 changes: 2 additions & 0 deletions src/test/Fake.Core.UnitTests/Fake.Core.UnitTests.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<ProjectReference Include="..\..\app\Fake.DotNet.MSBuild\Fake.DotNet.MSBuild.fsproj" />
<ProjectReference Include="..\..\app\Fake.DotNet.Testing.NUnit\Fake.DotNet.Testing.NUnit.fsproj" />
<ProjectReference Include="..\..\app\Fake.DotNet.Testing.SpecFlow\Fake.DotNet.Testing.SpecFlow.fsproj" />
<ProjectReference Include="..\..\app\Fake.Testing.ReportGenerator\Fake.Testing.ReportGenerator.fsproj" />
<ProjectReference Include="..\..\app\Fake.Core.SemVer\Fake.Core.SemVer.fsproj" />
<ProjectReference Include="..\..\app\Fake.Core.Target\Fake.Core.Target.fsproj" />
<ProjectReference Include="..\..\app\Fake.Core.ReleaseNotes\Fake.Core.ReleaseNotes.fsproj" />
Expand All @@ -30,6 +31,7 @@
<Compile Include="Fake.DotNet.MSBuild.fs" />
<Compile Include="Fake.DotNet.Testing.NUnit.fs" />
<Compile Include="Fake.DotNet.Testing.SpecFlow.fs" />
<Compile Include="Fake.Testing.ReportGenerator.fs" />
<Compile Include="Fake.Tools.Git.fs" />
<Compile Include="Fake.IO.Zip.fs" />
<Compile Include="Fake.Core.Process.fs" />
Expand Down
51 changes: 51 additions & 0 deletions src/test/Fake.Core.UnitTests/Fake.Testing.ReportGenerator.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
module Fake.Testing.ReportGeneratorTests

open System.IO
open Fake.Core
open Fake.Testing
open Expecto

let runCreateProcess setParams =
let cp =
["report1.xml"; "report2.xml"]
|> Fake.Testing.ReportGenerator.createProcess (fun param ->
{ setParams param with
ExePath = Path.Combine("reportgenerator", "ReportGenerator.exe")
TargetDir = "targetDir"})

let file, args =
match cp.Command with
| RawCommand(file, args) -> file, args
| _ -> failwithf "expected RawCommand"
|> ArgumentHelper.checkIfMono

let expectedPath = Path.Combine("reportgenerator", "ReportGenerator.exe")
Expect.equal file expectedPath "Expected ReportGenerator.exe"
expectedPath, cp.Command.CommandLine

[<Tests>]
let tests =
testList "Fake.Testing.ReportGenerator.Tests" [
testCase "Test that new argument generation with default parameters" <| fun _ ->
let expectedPath, commandLine =
runCreateProcess id

Expect.equal commandLine
(sprintf "%s -reports:report1.xml;report2.xml -targetdir:targetDir -reporttypes:Html -verbosity:Verbose" expectedPath) "expected proper command line"

testCase "Test that new argument generation with all parameters" <| fun _ ->
let expectedPath, commandLine =
runCreateProcess (fun p ->
{ p with
ReportTypes = [ ReportGenerator.ReportType.Html
ReportGenerator.ReportType.MHtml ]
SourceDirs = [ "source1"; "source2" ]
HistoryDir = "history"
Filters = [ "+a1*"; "-a2*" ]
ClassFilters = [ "+c1*"; "-c2*" ]
FileFilters = [ "+f1*"; "-f2*" ]
Tag = Some "mytag" })

Expect.equal commandLine
(sprintf "%s -reports:report1.xml;report2.xml -targetdir:targetDir -reporttypes:Html;MHtml -sourcedirs:source1;source2 -historydir:history -assemblyfilters:+a1*;-a2* -classfilters:+c1*;-c2* -filefilters:+f1*;-f2* -tag:mytag -verbosity:Verbose" expectedPath) "expected proper command line"
]