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

Opencover migration #1586

Merged
merged 3 commits into from
Jun 11, 2017
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
3 changes: 2 additions & 1 deletion build.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,8 @@ let dotnetAssemblyInfos =
"Fake.Testing.Common", "Common testing data types"
"Fake.Tracing.NAntXml", "NAntXml"
"Fake.Windows.Chocolatey", "Running and packaging with Chocolatey"
"Fake.Testing.SonarQube", "Analyzing your project with SonarQube" ]
"Fake.Testing.SonarQube", "Analyzing your project with SonarQube"
"Fake.DotNet.Testing.OpenCover", "Code coverage with OpenCover" ]

let assemblyInfos =
[ "./src/app/FAKE/AssemblyInfo.fs",
Expand Down
51 changes: 51 additions & 0 deletions help/markdown/dotnet-testing-opencover.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Analyze your code coverage with OpenCover

From the [project](https://github.com/OpenCover/opencover):
"A code coverage tool for .NET 2 and above (WINDOWS OS only), support for 32 and 64 processes with both branch and sequence points."

It will analyze the code coverage during testing and generates an XML report which can be used to generates HTML pages or uploaded to online services like [coveralls](https://coveralls.io/) or [codecov](https://codecov.io/).

## Minimal working example

open Fake.DotNet.Testing

OpenCover.Run (fun p ->
{ p with
TestRunnerExePath = "./Tools/NUnit/nunit-console.exe";
})
"project-file.nunit /config:Release /noshadow /xml:artifacts/nunit.xml /framework:net-4.0"

By default, the OpenCover module looks for the OpenCover Console in the OpenCover installation path '%LOCALAPPDATA%/Apps/OpenCover' directory. This can be overwritten using the `ExePath` property of the parameters.

## Version

open Fake.DotNet.Testing

OpenCover.Version None

## Full example

open Fake.DotNet.Testing
open Fake.DotNet.Testing.OpenCover

Target "OpenCover" (fun _ ->
OpenCover.Version (fun p -> { p with ExePath = "./tools/OpenCover/tools/OpenCover.Console.exe" })

OpenCover.Run (fun p ->
{ p with
ExePath = "./tools/OpenCover/tools/OpenCover.Console.exe"
TestRunnerExePath = "./tools/xunit.runner.console/tools/xunit.console.exe";
Output = "coverage.xml";
Register = RegisterUser;
Filter = "+[MyProject]*";
ExcludeByAttribute = [ "*.ExcludeFromCodeCoverage*" ];
ExcludeByFile = [ "Program.cs"; "Window.cs" ];
ExcludeDirs = [ "Test1"; "Test2" ];
HideSkipped = [File; Attribute];
MergeOutput = true;
ReturnTargetCode = Offset 5;
SearchDirs = [ "c:\projects\common\bin\debug\dnx451" ];
SkipAutoProps = true;
})
"MyProject.Tests.dll -noshadow"
)
1 change: 1 addition & 0 deletions help/templates/template.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
<li><a href="@(prefix)404.html">Testing - NUnit</a></li>
<li><a href="@(prefix)404.html">Testing - MSpec</a></li>
<li><a href="@(prefix)404.html">Testing - XUnit2</a></li>
<li><a href="@(prefix)dotnet-testing-opencover.html">Testing - OpenCover</a></li>
<li><a href="@(prefix)dotnet-nuget.html">NuGet</a></li>
<li><a href="@(prefix)404.html">Paket</a></li>
</ul>
Expand Down
15 changes: 15 additions & 0 deletions src/Fake-netcore.sln
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Fake.netcore", "app\Fake.ne
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Fake.Testing.SonarQube", "app\Fake.Testing.SonarQube\Fake.Testing.SonarQube.fsproj", "{2A985028-4410-40F7-992C-5397DC1ED116}"
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Fake.DotNet.Testing.OpenCover", "app\Fake.DotNet.Testing.OpenCover\Fake.DotNet.Testing.OpenCover.fsproj", "{A9AF015B-43C9-405E-BF74-CE936B8418F9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -424,6 +426,18 @@ Global
{2A985028-4410-40F7-992C-5397DC1ED116}.Release|x64.Build.0 = Release|x64
{2A985028-4410-40F7-992C-5397DC1ED116}.Release|x86.ActiveCfg = Release|x86
{2A985028-4410-40F7-992C-5397DC1ED116}.Release|x86.Build.0 = Release|x86
{A9AF015B-43C9-405E-BF74-CE936B8418F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A9AF015B-43C9-405E-BF74-CE936B8418F9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A9AF015B-43C9-405E-BF74-CE936B8418F9}.Debug|x64.ActiveCfg = Debug|x64
{A9AF015B-43C9-405E-BF74-CE936B8418F9}.Debug|x64.Build.0 = Debug|x64
{A9AF015B-43C9-405E-BF74-CE936B8418F9}.Debug|x86.ActiveCfg = Debug|x86
{A9AF015B-43C9-405E-BF74-CE936B8418F9}.Debug|x86.Build.0 = Debug|x86
{A9AF015B-43C9-405E-BF74-CE936B8418F9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A9AF015B-43C9-405E-BF74-CE936B8418F9}.Release|Any CPU.Build.0 = Release|Any CPU
{A9AF015B-43C9-405E-BF74-CE936B8418F9}.Release|x64.ActiveCfg = Release|x64
{A9AF015B-43C9-405E-BF74-CE936B8418F9}.Release|x64.Build.0 = Release|x64
{A9AF015B-43C9-405E-BF74-CE936B8418F9}.Release|x86.ActiveCfg = Release|x86
{A9AF015B-43C9-405E-BF74-CE936B8418F9}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{E2CF8635-E7C4-4470-92DD-F706F052BF7B} = {7BFFAE76-DEE9-417A-A79B-6A6644C4553A}
Expand Down Expand Up @@ -455,5 +469,6 @@ Global
{80314941-78D5-4928-B943-93FC945E050F} = {7BFFAE76-DEE9-417A-A79B-6A6644C4553A}
{CDFB2B10-050A-4188-8F72-2BCC61E9814F} = {7BFFAE76-DEE9-417A-A79B-6A6644C4553A}
{2A985028-4410-40F7-992C-5397DC1ED116} = {7BFFAE76-DEE9-417A-A79B-6A6644C4553A}
{A9AF015B-43C9-405E-BF74-CE936B8418F9} = {7BFFAE76-DEE9-417A-A79B-6A6644C4553A}
EndGlobalSection
EndGlobal
17 changes: 17 additions & 0 deletions src/app/Fake.DotNet.Testing.OpenCover/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 Code coverage with OpenCover")>]
[<assembly: AssemblyProductAttribute("FAKE - F# Make")>]
[<assembly: AssemblyVersionAttribute("5.0.0")>]
[<assembly: AssemblyInformationalVersionAttribute("5.0.0")>]
[<assembly: AssemblyFileVersionAttribute("5.0.0")>]
do ()

module internal AssemblyVersionInformation =
let [<Literal>] AssemblyTitle = "FAKE - F# Make Code coverage with OpenCover"
let [<Literal>] AssemblyProduct = "FAKE - F# Make"
let [<Literal>] AssemblyVersion = "5.0.0"
let [<Literal>] AssemblyInformationalVersion = "5.0.0"
let [<Literal>] AssemblyFileVersion = "5.0.0"
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<Project Sdk="FSharp.NET.Sdk;Microsoft.NET.Sdk" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VersionPrefix>1.0.0-alpha-10</VersionPrefix>
<!--<TargetFrameworks>net46;netstandard1.6</TargetFrameworks>-->
<TargetFramework>netstandard1.6</TargetFramework>
<DefineConstants>$(DefineConstants);NO_DOTNETCORE_BOOTSTRAP</DefineConstants>
<DebugType>pdbonly</DebugType>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<AssemblyName>Fake.Windows.Chocolatey</AssemblyName>
<OutputType>Library</OutputType>
<PackageTargetFallback Condition=" '$(TargetFramework)' == 'netstandard1.6' ">$(PackageTargetFallback);portable-net45+win8;dnxcore50</PackageTargetFallback>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard1.6' ">
<DefineConstants>$(DefineConstants);NETSTANDARD;USE_HTTPCLIENT</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DefineConstants>$(DefineConstants);RELEASE</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Compile Include="AssemblyInfo.fs" />
<Compile Include="OpenCover.fs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Fake.Core.Environment\Fake.Core.Environment.fsproj" />
<ProjectReference Include="..\Fake.Core.Tracing\Fake.Core.Tracing.fsproj" />
<ProjectReference Include="..\Fake.Core.Process\Fake.Core.Process.fsproj" />
<ProjectReference Include="..\Fake.Core.String\Fake.Core.String.fsproj" />
<ProjectReference Include="..\Fake.IO.FileSystem\Fake.IO.FileSystem.fsproj" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="dotnet-compile-fsc">
<Version>1.0.0-preview2-020000</Version>
</DotNetCliToolReference>
</ItemGroup>
<Import Project="..\..\..\.paket\Paket.Restore.targets" />
</Project>
163 changes: 163 additions & 0 deletions src/app/Fake.DotNet.Testing.OpenCover/OpenCover.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
/// Contains a task which can be used to run [OpenCover](https://github.com/sawilde/opencover) on .NET assemblies.
module Fake.DotNet.Testing.OpenCover

open System
open System.IO
open System.Text
open Fake.Core
open Fake.Core.Process
open Fake.Core.String
open Fake.IO.FileSystem
open Fake.IO.FileSystem.Operators

type RegisterType =
| Manual
| Register
| RegisterUser

type HideSkippedType =
| All
| File
| Filter
| Attribute
| MissingPdb

type ReturnTargetCodeType = No | Yes | Offset of int

/// OpenCover parameters, for more details see: https://github.com/OpenCover/opencover/wiki/Usage#console-application-usage.
type OpenCoverParams =
{ /// (Required) Path to the OpenCover console application
ExePath : string
/// (Required) Path to the NUnit/XUnit console runner
TestRunnerExePath : string
/// The location and name of the output xml file.
/// If no value is supplied then the current directory
/// will be used and the output filename will be results.xml.
Output : string
/// Use this to register and de-register the code coverage profiler.
Register : RegisterType
/// A list of filters to apply to selectively include or exclude assemblies and classes from coverage results.
Filter : string
/// The timeout for the OpenCover process.
TimeOut : TimeSpan
/// The directory where the OpenCover process will be started.
WorkingDir : string
/// This option is used to merge the coverage results for an assembly regardless of where it was loaded
/// assuming the assembly has the same file-hash in each location.
MergeByHash : bool
/// Exclude a class or method by filter(s) that match attributes that have been applied. An * can be used as a wildcard.
ExcludeByAttribute: string list
/// Exclude a class (or methods) by filter(s) that match the filenames. An * can be used as a wildcard.
ExcludeByFile : string list
/// Assemblies being loaded from these locations will be ignored.
ExcludeDirs : string list
/// Remove information from output file that relates to classes/modules that have been skipped (filtered) due to the use of the parameters ExcludeBy*, Filter or where the PDB is missing.
HideSkipped : HideSkippedType list
/// Allow to merge the results with an existing file (specified by Output parameter). So the coverage from the output file will be loaded first (if exists).
MergeOutput : bool
/// Return the target process return code instead of the OpenCover console return code. Use the offset to return the OpenCover console at a value outside the range returned by the target process.
ReturnTargetCode : ReturnTargetCodeType
/// Alternative locations to look for PDBs.
SearchDirs : string list
/// Neither track nor record auto-implemented properties.
/// That is, skip getters and setters like these: public bool Service { get; set; }
SkipAutoProps : bool
/// This options is used to add additional optional arguments, could be somthing like "-returntargetcode "
OptionalArguments : string }

/// OpenCover default parameters
let OpenCoverDefaults =
{ ExePath = if Environment.isMono then String.Empty else Environment.environVar "LOCALAPPDATA" @@ "Apps" @@ "OpenCover" @@ "OpenCover.Console.exe"
TestRunnerExePath = if Environment.isMono then String.Empty else Environment.ProgramFiles @@ "NUnit" @@ "bin" @@ "nunit-console.exe"
Output = String.Empty
Register = Manual
Filter = String.Empty
TimeOut = TimeSpan.FromMinutes 5.
WorkingDir = Directory.GetCurrentDirectory()
MergeByHash = false
ExcludeByAttribute = []
ExcludeByFile = []
ExcludeDirs = []
HideSkipped = []
MergeOutput = false
ReturnTargetCode = No
SearchDirs = []
SkipAutoProps = false
OptionalArguments = String.Empty }

/// Builds the command line arguments from the given parameter record
/// [omit]
let private buildOpenCoverArgs param targetArgs =
let quote arg = sprintf "\"%s\"" arg
let printParam paramName = sprintf "-%s" paramName
let printParamWithValue paramName paramValue = sprintf "-%s:%s" paramName paramValue
let mergeListAsValues paramList valueModification = paramList |> List.fold (fun acc x -> acc + (match acc with ""-> "" | _ -> ";") + valueModification x) ""
let printParamListAsValuesWithModification paramName paramList valueModification = printParamWithValue paramName (mergeListAsValues paramList valueModification)
let printParamListAsValuesWithQuote paramName paramList = printParamWithValue paramName (quote (mergeListAsValues paramList (fun v -> v)))
let printParamListAsValues paramName paramList = printParamListAsValuesWithModification paramName paramList (fun v -> string v)

new StringBuilder()
|> appendWithoutQuotes (printParamWithValue "target" (quote (param.TestRunnerExePath |> Path.getFullName)))
|> appendWithoutQuotes (printParamWithValue "targetargs" (quote targetArgs))
|> appendIfTrueWithoutQuotes (isNotNullOrEmpty param.Output) (printParamWithValue "output" (quote param.Output))
|> appendWithoutQuotes (match param.Register with
| Manual -> String.Empty
| Register -> printParam "register"
| RegisterUser -> printParamWithValue "register" "user")
|> appendIfTrueWithoutQuotes (isNotNullOrEmpty param.Filter) (printParamWithValue "filter" (quote param.Filter))
|> appendIfTrueWithoutQuotes param.MergeByHash (printParam "mergebyhash")
|> appendIfTrueWithoutQuotes (not param.ExcludeByAttribute.IsEmpty) (printParamListAsValuesWithQuote "excludebyattribute" param.ExcludeByAttribute)
|> appendIfTrueWithoutQuotes (not param.ExcludeByFile.IsEmpty) (printParamListAsValuesWithQuote "excludebyfile" param.ExcludeByFile)
|> appendIfTrueWithoutQuotes (not param.ExcludeDirs.IsEmpty) (printParamListAsValuesWithQuote "excludedirs" param.ExcludeDirs)
|> appendIfTrueWithoutQuotes (not param.HideSkipped.IsEmpty) (printParamListAsValues "hideskipped" param.HideSkipped)
|> appendIfTrueWithoutQuotes param.MergeOutput (printParam "mergeoutput")
|> appendWithoutQuotes (match param.ReturnTargetCode with
| No -> String.Empty
| Yes -> printParam "returntargetcode"
| Offset o -> printParamWithValue "returntargetcode" (string o))
|> appendIfTrueWithoutQuotes (not param.SearchDirs.IsEmpty) (printParamListAsValuesWithQuote "searchdirs" param.SearchDirs)
|> appendIfTrueWithoutQuotes param.SkipAutoProps (printParam "skipautoprops")
|> appendIfTrueWithoutQuotes (isNotNullOrEmpty param.OptionalArguments) param.OptionalArguments
|> toText

/// Runs OpenCover on a group of assemblies.
/// ## Parameters
///
/// - `setParams` - Function used to overwrite the default OpenCover parameters.
/// - `targetArgs` - Test runner arguments.
///
/// ## Sample
///
/// OpenCover.Run (fun p -> { p with TestRunnerExePath = "./Tools/NUnit/nunit-console.exe" })
/// "project-file.nunit /config:Release /noshadow /xml:artifacts/nunit.xml /framework:net-4.0"
let Run setParams targetArgs =
use __ = Trace.traceTask "OpenCover" "Gathering coverage statistics"
let param = setParams OpenCoverDefaults

let processArgs = buildOpenCoverArgs param targetArgs
Trace.tracefn "OpenCover command\n%s %s" param.ExePath processArgs
let ok =
execProcess (fun info ->
info.FileName <- param.ExePath
if param.WorkingDir <> String.Empty then info.WorkingDirectory <- param.WorkingDir
info.Arguments <- processArgs) param.TimeOut
if not ok then failwithf "OpenCover reported errors."

/// Show version OpenCover
/// ## Parameters
///
/// - `setParams` - Function used to overwrite the default OpenCover parameters.
///
/// ## Sample
///
/// OpenCover.Version None
/// OpenCover.Version (fun p -> { p with TestRunnerExePath = "./Tools/NUnit/nunit-console.exe" })
let Version setParams =
use __ = Trace.traceTask "OpenCover" "Version"
let param = match setParams with
| Some setParams -> setParams OpenCoverDefaults
| None -> OpenCoverDefaults

ExecProcess (fun info ->
info.FileName <- param.ExePath
info.Arguments <- "-version") param.TimeOut |> ignore
4 changes: 4 additions & 0 deletions src/app/Fake.DotNet.Testing.OpenCover/paket.references
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
group netcore
FSharp.NET.Sdk
FSharp.Core
NETStandard.Library
17 changes: 17 additions & 0 deletions src/app/Fake.Testing.OpenCover/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 Code coverage with OpenCover")>]
[<assembly: AssemblyProductAttribute("FAKE - F# Make")>]
[<assembly: AssemblyVersionAttribute("5.0.0")>]
[<assembly: AssemblyInformationalVersionAttribute("5.0.0")>]
[<assembly: AssemblyFileVersionAttribute("5.0.0")>]
do ()

module internal AssemblyVersionInformation =
let [<Literal>] AssemblyTitle = "FAKE - F# Make Code coverage with OpenCover"
let [<Literal>] AssemblyProduct = "FAKE - F# Make"
let [<Literal>] AssemblyVersion = "5.0.0"
let [<Literal>] AssemblyInformationalVersion = "5.0.0"
let [<Literal>] AssemblyFileVersion = "5.0.0"
3 changes: 3 additions & 0 deletions src/app/FakeLib/FakeLib.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,9 @@
<Compile Include="..\Fake.Testing.SonarQube\SonarQube.fs">
<Link>Fake.Testing.SonarQube/SonarQube.fs</Link>
</Compile>
<Compile Include="..\Fake.DotNet.Testing.OpenCover\OpenCover.fs">
<Link>Fake.DotNet.Testing.OpenCover/OpenCover.fs</Link>
</Compile>
<Compile Include="UserInputHelper.fs" />
<Compile Include="CSharpHelper.fs" />
<Compile Include="EnvironmentHelper.fs" />
Expand Down
Loading