Skip to content

Commit 0e05965

Browse files
Added ms code coverage support
1 parent 57ab677 commit 0e05965

17 files changed

+337
-70
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,6 @@ x64/
2020
# NCrunch
2121
*.ncrunchsolution
2222
*.ncrunchproject
23-
_NCrunch_WebCompiler
23+
_NCrunch_WebCompiler
24+
/.fcc
25+
/fcc.xml

FineCodeCoverage/FineCodeCoverage.csproj

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@
7777
<Link>Resources\reportparts.xml</Link>
7878
<IncludeInVSIX>true</IncludeInVSIX>
7979
</Content>
80+
<Content Include="fineCodeCoverageSettings.xml">
81+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
82+
<IncludeInVSIX>true</IncludeInVSIX>
83+
</Content>
8084
<Content Include="ZippedTools\coverlet.collector.3.0.3.zip">
8185
<IncludeInVSIX>true</IncludeInVSIX>
8286
</Content>
@@ -92,6 +96,9 @@
9296
<Content Include="ZippedTools\reportGenerator.4.7.1.zip">
9397
<IncludeInVSIX>true</IncludeInVSIX>
9498
</Content>
99+
<Content Include="ZippedTools\microsoft.codecoverage.17.1.0.zip">
100+
<IncludeInVSIX>true</IncludeInVSIX>
101+
</Content>
95102
<VSCTCompile Include="..\Shared Files\OutputToolWindowPackage.vsct">
96103
<Link>OutputToolWindowPackage.vsct</Link>
97104
<ResourceName>Menus.ctmenu</ResourceName>
@@ -104,6 +111,7 @@
104111
<Link>Resources\OutputToolWindowCommand.png</Link>
105112
<IncludeInVSIX>true</IncludeInVSIX>
106113
</Content>
114+
<None Include="README.md" />
107115
<!--
108116
<None Include="Key.snk" />
109117
-->
@@ -129,6 +137,9 @@
129137
<PackageReference Include="Microsoft.VisualStudio.SDK" Version="16.0.206" ExcludeAssets="runtime">
130138
<IncludeAssets>compile; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
131139
</PackageReference>
140+
<PackageReference Include="Microsoft.VisualStudio.Shell.15.0">
141+
<Version>16.10.31225.38</Version>
142+
</PackageReference>
132143
<PackageReference Include="Microsoft.VisualStudio.TestWindow.Interfaces">
133144
<Version>11.0.61030</Version>
134145
</PackageReference>
6.98 MB
Binary file not shown.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
3+
<!--
4+
Edit this xml file to configure the code coverage for FCC. See
5+
https://docs.microsoft.com/en-us/visualstudio/test/customizing-code-coverage-analysis?view=vs-2022
6+
for details.
7+
8+
The resulting runsettings file actually used for test runs is put into .fcc/fcc.runsettings
9+
-->
10+
<RunSettings>
11+
<RunConfiguration>
12+
<!-- do not modify the next two lines -->
13+
<ResultsDirectory>%resultsDir%</ResultsDirectory>
14+
<TestAdaptersPaths>%testAdapter%</TestAdaptersPaths>
15+
<CollectSourceInformation>False</CollectSourceInformation>
16+
</RunConfiguration>
17+
<DataCollectionRunSettings>
18+
<DataCollectors>
19+
<DataCollector friendlyName="Code Coverage" enabled="True">
20+
<Configuration>
21+
<CodeCoverage>
22+
<ModulePaths>
23+
<Exclude>
24+
<!-- %exclude% will be replaced with all test assemblies dlls enclosed in <ModulePath>, if you
25+
have specified that they should be excluded in the FCC options.
26+
-->
27+
%exclude%
28+
<!-- if you want to exclude some assemblies add them here e.g. via <ModulePath>xunit.*</ModulePath> -->
29+
</Exclude>
30+
</ModulePaths>
31+
</CodeCoverage>
32+
<Format>Cobertura</Format>
33+
</Configuration>
34+
</DataCollector>
35+
</DataCollectors>
36+
</DataCollectionRunSettings>
37+
</RunSettings>

SharedProject/Core/FCCEngine.cs

Lines changed: 61 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,28 @@ internal class FCCEngine : IFCCEngine
2121
{
2222
internal int InitializeWait { get; set; } = 5000;
2323
internal const string initializationFailedMessagePrefix = "Initialization failed. Please check the following error which may be resolved by reopening visual studio which will start the initialization process again.";
24-
private readonly object colorThemeService;
24+
private readonly object colorThemeService;
2525
private CancellationTokenSource cancellationTokenSource;
26-
26+
2727
public event UpdateMarginTagsDelegate UpdateMarginTags;
2828
public event UpdateOutputWindowDelegate UpdateOutputWindow;
29-
29+
3030
public string AppDataFolderPath { get; private set; }
3131
public List<CoverageLine> CoverageLines { get; internal set; }
32+
public string SolutionPath { get; set; }
33+
3234

3335
private readonly ICoverageUtilManager coverageUtilManager;
34-
private readonly ICoberturaUtil coberturaUtil;
36+
private readonly ICoberturaUtil coberturaUtil;
37+
private readonly IMsCodeCoverageRunSettingsService msCodeCoverageRunSettingsService;
3538
private readonly IMsTestPlatformUtil msTestPlatformUtil;
3639
private readonly IReportGeneratorUtil reportGeneratorUtil;
3740
private readonly IProcessUtil processUtil;
3841
private readonly IAppOptionsProvider appOptionsProvider;
3942
private readonly ILogger logger;
4043
private readonly IAppDataFolder appDataFolder;
4144
private readonly IServiceProvider serviceProvider;
42-
45+
4346
private IInitializeStatusProvider initializeStatusProvider;
4447
private readonly ICoverageToolOutputManager coverageOutputManager;
4548
internal System.Threading.Tasks.Task reloadCoverageTask;
@@ -48,13 +51,14 @@ internal class FCCEngine : IFCCEngine
4851
public FCCEngine(
4952
ICoverageUtilManager coverageUtilManager,
5053
ICoberturaUtil coberturaUtil,
51-
IMsTestPlatformUtil msTestPlatformUtil,
54+
IMsTestPlatformUtil msTestPlatformUtil,
5255
IReportGeneratorUtil reportGeneratorUtil,
5356
IProcessUtil processUtil,
5457
IAppOptionsProvider appOptionsProvider,
5558
ILogger logger,
5659
IAppDataFolder appDataFolder,
5760
ICoverageToolOutputManager coverageOutputManager,
61+
IMsCodeCoverageRunSettingsService msCodeCoverageRunSettingsService,
5862
[Import(typeof(SVsServiceProvider))]
5963
IServiceProvider serviceProvider
6064
)
@@ -68,7 +72,8 @@ IServiceProvider serviceProvider
6872
this.appOptionsProvider = appOptionsProvider;
6973
this.logger = logger;
7074
this.appDataFolder = appDataFolder;
71-
this.serviceProvider = serviceProvider;
75+
this.serviceProvider = serviceProvider;
76+
this.msCodeCoverageRunSettingsService = msCodeCoverageRunSettingsService;
7277
colorThemeService = serviceProvider.GetService(typeof(SVsColorThemeService));
7378
}
7479

@@ -91,6 +96,7 @@ public void Initialize(IInitializeStatusProvider initializeStatusProvider)
9196
reportGeneratorUtil.Initialize(AppDataFolderPath);
9297
msTestPlatformUtil.Initialize(AppDataFolderPath);
9398
coverageUtilManager.Initialize(AppDataFolderPath);
99+
msCodeCoverageRunSettingsService.Initialize(AppDataFolderPath);
94100
}
95101

96102
public void ClearUI()
@@ -102,13 +108,13 @@ public void ClearUI()
102108
}
103109

104110
public void StopCoverage()
105-
{
111+
{
106112
if (cancellationTokenSource != null)
107113
{
108114
cancellationTokenSource.Cancel();
109115
}
110116
}
111-
117+
112118
private CancellationToken Reset()
113119
{
114120
ClearUI();
@@ -150,16 +156,16 @@ private void UpdateUI(List<CoverageLine> coverageLines, string reportHtml)
150156
{
151157
CoverageLines = coverageLines;
152158
UpdateMarginTags?.Invoke(new UpdateMarginTagsEventArgs());
153-
RaiseUpdateOutputWindow(reportHtml);
159+
RaiseUpdateOutputWindow(reportHtml);
154160
}
155161

156-
private async System.Threading.Tasks.Task<(List<CoverageLine> coverageLines,string reportFilePath)> RunAndProcessReportAsync(string[] coverOutputFiles,string reportOutputFolder,CancellationToken cancellationToken)
162+
private async System.Threading.Tasks.Task<(List<CoverageLine> coverageLines,string reportFilePath)> RunAndProcessReportAsync(string[] coverOutputFiles, string reportOutputFolder, CancellationToken cancellationToken)
157163
{
158164
cancellationToken.ThrowIfCancellationRequested();
159165

160166
List<CoverageLine> coverageLines = null;
161167
string processedReport = null;
162-
168+
163169
var result = await reportGeneratorUtil.GenerateAsync(coverOutputFiles,reportOutputFolder, true);
164170

165171
if (result.Success)
@@ -227,7 +233,7 @@ private async System.Threading.Tasks.Task PollInitializedStatusAsync(Cancellatio
227233
{
228234
case InitializeStatus.Initialized:
229235
return;
230-
236+
231237
case InitializeStatus.Initializing:
232238
LogReloadCoverageStatus(ReloadCoverageStatus.Initializing);
233239
await System.Threading.Tasks.Task.Delay(InitializeWait);
@@ -241,41 +247,52 @@ private async System.Threading.Tasks.Task PollInitializedStatusAsync(Cancellatio
241247
public void ReloadCoverage(Func<System.Threading.Tasks.Task<List<ICoverageProject>>> coverageRequestCallback)
242248
{
243249
var cancellationToken = Reset();
244-
245-
reloadCoverageTask = System.Threading.Tasks.Task.Run(async () =>
246-
{
247-
List<CoverageLine> coverageLines = null;
248-
string reportHtml = null;
249-
250-
await PollInitializedStatusAsync(cancellationToken);
251-
252-
LogReloadCoverageStatus(ReloadCoverageStatus.Start);
253-
254-
var coverageProjects = await coverageRequestCallback();
255-
256-
coverageOutputManager.SetProjectCoverageOutputFolder(coverageProjects);
257-
var reportOutputFolder = coverageOutputManager.GetReportOutputFolder();
258-
259-
var coverOutputFiles = await RunCoverageAsync(coverageProjects, cancellationToken);
260-
261-
if (coverOutputFiles.Any())
250+
251+
reloadCoverageTask = System.Threading.Tasks.Task.Run(async () =>
262252
{
263-
var (lines, report) = await RunAndProcessReportAsync(coverOutputFiles,reportOutputFolder,cancellationToken);
264-
coverageLines = lines;
265-
reportHtml = report;
266-
}
267-
268-
return (coverageLines, reportHtml);
269-
270-
}, cancellationToken)
271-
.ContinueWith(t =>
272-
{
273-
ReloadCoverageTaskContinuation(t);
253+
List<CoverageLine> coverageLines = null;
254+
string reportHtml = null;
255+
256+
await PollInitializedStatusAsync(cancellationToken);
257+
258+
LogReloadCoverageStatus(ReloadCoverageStatus.Start);
259+
260+
var coverageProjects = await coverageRequestCallback();
261+
coverageOutputManager.SetProjectCoverageOutputFolder(coverageProjects);
262+
var reportOutputFolder = coverageOutputManager.GetReportOutputFolder();
263+
var settings = appOptionsProvider.Get();
264+
if (!settings.MsCodeCoverage)
265+
{
266+
var coverOutputFiles = await RunCoverageAsync(coverageProjects, cancellationToken);
267+
if (coverOutputFiles.Any())
268+
{
269+
(coverageLines, reportHtml) = await RunAndProcessReportAsync(coverOutputFiles, reportOutputFolder, cancellationToken);
270+
}
271+
}
272+
else
273+
{
274+
await PrepareCoverageProjectsAsync(coverageProjects, cancellationToken);
275+
var outputFiles = msCodeCoverageRunSettingsService.GetCoverageFilesFromLastRun();
276+
logger.Log("Number of outputfiles:" + outputFiles.Count);
277+
if (outputFiles.Any())
278+
{
279+
(coverageLines, reportHtml) = await RunAndProcessReportAsync(outputFiles.ToArray(), reportOutputFolder, cancellationToken);
280+
}
281+
}
282+
return (coverageLines, reportHtml);
283+
284+
}, cancellationToken)
285+
.ContinueWith(t =>
286+
{
287+
ReloadCoverageTaskContinuation(t);
274288

275-
}, System.Threading.Tasks.TaskScheduler.Default);
289+
}, System.Threading.Tasks.TaskScheduler.Default);
290+
}
276291

292+
public void PrepareTestRun(ITestOperation testOperation)
293+
{
294+
msCodeCoverageRunSettingsService.PrepareRunSettings(SolutionPath, testOperation);
277295
}
278296

279297
}
280-
281298
}

SharedProject/Core/IFCCEngine.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,15 @@ internal interface IFCCEngine
99
{
1010
event UpdateMarginTagsDelegate UpdateMarginTags;
1111
event UpdateOutputWindowDelegate UpdateOutputWindow;
12-
string AppDataFolderPath { get; }
12+
string AppDataFolderPath { get; }
1313
void Initialize(IInitializeStatusProvider initializeStatusProvider);
1414
void StopCoverage();
15-
void ReloadCoverage(Func<System.Threading.Tasks.Task<List<ICoverageProject>>> coverageRequestCallback);
15+
void ReloadCoverage(Func<System.Threading.Tasks.Task<List<ICoverageProject>>> coverageRequestCallback);
1616
void ClearUI();
1717
List<CoverageLine> CoverageLines { get; }
18+
string SolutionPath { get; set; }
19+
20+
void PrepareTestRun(ITestOperation testOperation);
1821
}
1922

2023
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using FineCodeCoverage.Impl;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Text;
5+
6+
namespace FineCodeCoverage.Engine.MsTestPlatform
7+
{
8+
interface IMsCodeCoverageRunSettingsService
9+
{
10+
void PrepareRunSettings(string solutionPath, ITestOperation testOperation);
11+
IList<String> GetCoverageFilesFromLastRun();
12+
void Initialize(string appDataFolder);
13+
}
14+
}

0 commit comments

Comments
 (0)