diff --git a/src/Microsoft.DotNet.Arcade.Sdk/tools/Coverlet/Coverlet.props b/src/Microsoft.DotNet.Arcade.Sdk/tools/Coverlet/Coverlet.props
new file mode 100644
index 00000000000..81cb420054c
--- /dev/null
+++ b/src/Microsoft.DotNet.Arcade.Sdk/tools/Coverlet/Coverlet.props
@@ -0,0 +1,14 @@
+
+
+
+
+ opencover
+ 0
+ line,branch,method
+ minimum
+ normal
+
+ Html
+ warning
+
+
diff --git a/src/Microsoft.DotNet.Arcade.Sdk/tools/Coverlet/Coverlet.targets b/src/Microsoft.DotNet.Arcade.Sdk/tools/Coverlet/Coverlet.targets
new file mode 100644
index 00000000000..e042e00a3c9
--- /dev/null
+++ b/src/Microsoft.DotNet.Arcade.Sdk/tools/Coverlet/Coverlet.targets
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+ <_TestAssembly>%(TestRunWithRunner.Identity)
+ <_CoverageOutputFile>%(TestRunWithRunner.ResultsCodeCoveragePath)
+ <_TestRunner>%(TestRunWithRunner.TestRunner)
+ <_TestRunner>$(_TestRunner.Replace('"', '\"'))
+ <_TestRunnerArgs>%(TestRunWithRunner.TestRunnerArgs)
+ <_TestRunnerArgs>$(_TestRunnerArgs.Replace('"', '\"'))
+ <_ReportCoverageDirectory>$(ArtifactsLogDir)codecoverage/$([System.IO.Path]::GetFileNameWithoutExtension('$(_TestAssembly)'))
+
+ <_CoverletArgs>"$(_TestAssembly)" --format $(CoverletFormat) --output "$(_CoverageOutputFile)" --threshold $(CoverletThreshold) --threshold-type "$(CoverletThresholdType)" --threshold-stat $(CoverletThresholdStat) --verbosity $(CoverletVerbosity) --target "$(_TestRunner)" --targetargs "$(_TestRunnerArgs)"
+ <_CoverletCommand>"$(DotNetTool)" tool run coverlet $(_CoverletArgs)
+
+
+
+
+
+
+
+ <_ReportGeneratorArgs>"--reports:$(_CoverageOutputFile)" "--targetdir:$(_ReportCoverageDirectory)" "-reporttypes:$(ReportGeneratorReportType)" "-verbosity:$(ReportGeneratorVerbosity)"
+ <_ReportGeneratorCommand>"$(DotNetTool)" tool run reportgenerator $(_ReportGeneratorArgs)
+
+
+
+
+
diff --git a/src/Microsoft.DotNet.Arcade.Sdk/tools/Tests.props b/src/Microsoft.DotNet.Arcade.Sdk/tools/Tests.props
index fc7c90d7e05..48d60839cd9 100644
--- a/src/Microsoft.DotNet.Arcade.Sdk/tools/Tests.props
+++ b/src/Microsoft.DotNet.Arcade.Sdk/tools/Tests.props
@@ -6,7 +6,7 @@
false
true
-
+
false
true
@@ -39,10 +39,16 @@
XUnit
+
+ Coverlet
+
true
+
+
+
diff --git a/src/Microsoft.DotNet.Arcade.Sdk/tools/Tests.targets b/src/Microsoft.DotNet.Arcade.Sdk/tools/Tests.targets
index e3cedb18a29..8f7eb194ec7 100644
--- a/src/Microsoft.DotNet.Arcade.Sdk/tools/Tests.targets
+++ b/src/Microsoft.DotNet.Arcade.Sdk/tools/Tests.targets
@@ -14,12 +14,27 @@
Full
+
+ false
+
+
$(PlatformTarget)
x64
+
+
+ $(_GetTestsToRunTarget);
+ RunTests
+
+
+
+ $(_GetTestsToRunTarget);
+ PrepareForRunTests;
+ RunCodeCoverage;
+
-
+
@@ -50,6 +65,7 @@
$(ArtifactsTestResultsDir)$(_ResultFileNameNoExt).xml
$(ArtifactsTestResultsDir)$(_ResultFileNameNoExt).html
$(ArtifactsLogDir)$(_ResultFileNameNoExt).log
+ $(ArtifactsLogDir)$(_ResultFileNameNoExt).codecoverage.xml
$(TestRunnerAdditionalArguments)
@@ -69,4 +85,7 @@
+
+
+
diff --git a/src/Microsoft.DotNet.Arcade.Sdk/tools/XUnit/XUnit.targets b/src/Microsoft.DotNet.Arcade.Sdk/tools/XUnit/XUnit.targets
index e25da54ae49..72d326cb4e5 100644
--- a/src/Microsoft.DotNet.Arcade.Sdk/tools/XUnit/XUnit.targets
+++ b/src/Microsoft.DotNet.Arcade.Sdk/tools/XUnit/XUnit.targets
@@ -22,14 +22,11 @@
Condition="'$(XUnitCoreSettingsFile)' != '' and '$(TargetFrameworkIdentifier)' == '.NETCoreApp'" />
-
-
-
+
+
+
<_TestEnvironment>%(TestToRun.EnvironmentDisplay)
<_TestAssembly>%(TestToRun.Identity)
@@ -47,10 +44,10 @@
<_TargetDir>$([System.IO.Path]::GetDirectoryName('$(_TestAssembly)'))\
<_CoreRuntimeConfigPath>$(_TargetDir)$(_TargetFileNameNoExt).runtimeconfig.json
<_CoreDepsPath>$(_TargetDir)$(_TargetFileNameNoExt).deps.json
-
+
<_TestRunner Condition="'%(TestToRun.Architecture)'=='x86' And Exists('$(DotNetRoot)x86\dotnet.exe')">$(DotNetRoot)x86\dotnet.exe
<_TestRunner Condition="'$(_TestRunner)'==''">$(DotNetTool)
-
+
<_TestRunnerArgs>exec --depsfile "$(_CoreDepsPath)" --runtimeconfig "$(_CoreRuntimeConfigPath)" $(TestRuntimeAdditionalArguments) "$(NuGetPackageRoot)xunit.runner.console/$(XUnitVersion)/tools/$(_TestRunnerTargetFramework)/xunit.console.dll" "$(_TestAssembly)" -noautoreporters -xml "%(TestToRun.ResultsXmlPath)" -html "%(TestToRun.ResultsHtmlPath)" $(_TestRunnerAdditionalArguments)
@@ -66,20 +63,43 @@
<_TestRunner Condition="'$(_TestRuntime)' != 'Mono'">$(_XUnitConsoleExePath)
+
+
+ $(_TestRunner)
+ $(_TestRunnerArgs)
+
+
+
+
+
+
+
+
+
- <_TestRunnerCommand>"$(_TestRunner)" $(_TestRunnerArgs)
+ <_TestEnvironment>%(TestRunWithRunner.EnvironmentDisplay)
+ <_TestAssembly>%(TestRunWithRunner.Identity)
+ <_TestRunnerAdditionalArguments>%(TestRunWithRunner.TestRunnerAdditionalArguments)
-
- <_TestRunnerCommand Condition="'$(TestCaptureOutput)' != 'false'">$(_TestRunnerCommand) > "%(TestToRun.ResultsStdOutPath)" 2>&1
+ <_TestRunnerCommand Condition="'$(TestCaptureOutput)' != 'false'">$(_TestRunnerCommand) > "%(TestRunWithRunner.ResultsStdOutPath)" 2>&1
- <_OutputFiles Include="%(TestToRun.ResultsXmlPath)" />
- <_OutputFiles Include="%(TestToRun.ResultsHtmlPath)" />
- <_OutputFiles Include="%(TestToRun.ResultsStdOutPath)" />
+ <_OutputFiles Include="%(TestRunWithRunner.ResultsXmlPath)" />
+ <_OutputFiles Include="%(TestRunWithRunner.ResultsHtmlPath)" />
+ <_OutputFiles Include="%(TestRunWithRunner.ResultsStdOutPath)" />
@@ -93,8 +113,8 @@
-
@@ -104,11 +124,11 @@
- <_ResultsFileToDisplay>%(TestToRun.ResultsHtmlPath)
+ <_ResultsFileToDisplay>%(TestRunWithRunner.ResultsHtmlPath)
<_ResultsFileToDisplay Condition="!Exists('$(_ResultsFileToDisplay)')">%(TestToRun.ResultsStdOutPath)
-