Skip to content

Commit e475ed1

Browse files
committed
add functionality and update readme
1 parent eb2ad6d commit e475ed1

File tree

8 files changed

+105
-5
lines changed

8 files changed

+105
-5
lines changed

FineCodeCoverageTests/AppOptionsProvider_Tests.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,8 @@ internal void Should_Use_Deseralized_String_From_Store_For_AppOption_Property(Fu
307307
{ nameof(IAppOptions.ShowPartiallyCoveredInOverviewMargin),true},
308308
{ nameof(IAppOptions.ShowUncoveredInOverviewMargin),true},
309309
{ nameof(IAppOptions.ShowToolWindowToolbar),true},
310+
{nameof(IAppOptions.ExcludeAssemblies),new string[]{ "Exclude"} },
311+
{nameof(IAppOptions.IncludeAssemblies),new string[]{ "Include"} },
310312
};
311313
var mockJsonConvertService = autoMocker.GetMock<IJsonConvertService>();
312314
mockJsonConvertService.Setup(

FineCodeCoverageTests/CoverageProject_Settings_Tests.cs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using AutoMoq;
12
using FineCodeCoverage.Core.Utilities;
23
using FineCodeCoverage.Engine.Model;
34
using FineCodeCoverage.Options;
@@ -12,7 +13,7 @@
1213
using System.Threading.Tasks;
1314
using System.Xml.Linq;
1415

15-
namespace Test
16+
namespace FineCodeCoverageTests
1617
{
1718
public class CoverageProject_Settings_Tests
1819
{
@@ -675,5 +676,34 @@ public async Task Should_Provide_The_Merged_Result_Using_Project_Settings()
675676
var coverageProjectSettings = await coverageProjectSettingsManager.GetSettingsAsync(coverageProject);
676677
Assert.AreSame(mergedSettings, coverageProjectSettings);
677678
}
679+
680+
[Test]
681+
public async Task Should_Add_Common_Assembly_Excludes_Includes()
682+
{
683+
var mockAppOptions = new Mock<IAppOptions>();
684+
mockAppOptions.SetupAllProperties();
685+
var appOptions = mockAppOptions.Object;
686+
appOptions.Exclude = new string[] { "oldexclude" };
687+
appOptions.Include = new string[] { "oldinclude" };
688+
appOptions.ModulePathsExclude = new string[] { "msexclude" };
689+
appOptions.ModulePathsInclude = new string[] { "msinclude" };
690+
appOptions.ExcludeAssemblies = new string[] { "excludeassembly" };
691+
appOptions.IncludeAssemblies = new string[] { "includeassembly" };
692+
693+
var autoMoqer = new AutoMoqer();
694+
var coverageProjectSettingsManager = autoMoqer.Create<CoverageProjectSettingsManager>();
695+
autoMoqer.GetMock<ISettingsMerger>().Setup(settingsMerger => settingsMerger.Merge(
696+
It.IsAny<IAppOptions>(),
697+
It.IsAny<List<XElement>>(),
698+
It.IsAny<XElement>()
699+
)).Returns(appOptions);
700+
701+
var settings = await coverageProjectSettingsManager.GetSettingsAsync(new Mock<ICoverageProject>().Object);
702+
703+
Assert.That(settings.Exclude, Is.EquivalentTo(new string[] { "oldexclude", "[excludeassembly]*" }));
704+
Assert.That(settings.Include, Is.EquivalentTo(new string[] { "oldinclude", "[includeassembly]*" }));
705+
Assert.That(settings.ModulePathsExclude, Is.EquivalentTo(new string[] { "msexclude", ".*\\excludeassembly.dll$" }));
706+
Assert.That(settings.ModulePathsInclude, Is.EquivalentTo(new string[] { "msinclude", ".*\\includeassembly.dll$" }));
707+
}
678708
}
679709
}

FineCodeCoverageTests/MsCodeCoverage/RunSettingsTemplateReplacementsFactory_Tests.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ internal class TestMsCodeCoverageOptions : IMsCodeCoverageOptions
3030

3131
public bool IncludeTestAssembly { get; set; }
3232
public bool IncludeReferencedProjects { get; set; }
33+
public string[] ExcludeAssemblies { get; set; }
34+
public string[] IncludeAssemblies { get; set; }
3335
}
3436

3537
internal static class ReplacementsAssertions
@@ -51,6 +53,7 @@ public static void AssertAllEmpty(IRunSettingsTemplateReplacements replacements)
5153
}
5254
}
5355

56+
5457
internal class RunSettingsTemplateReplacementsFactory_UserRunSettings_Tests
5558
{
5659
private RunSettingsTemplateReplacementsFactory runSettingsTemplateReplacementsFactory;
@@ -694,5 +697,7 @@ internal class TestCoverageProjectOptions : IAppOptions
694697
public bool ShowToolWindowToolbar { get; set; }
695698
public bool Hide0Coverable { get; set; }
696699
public bool Hide0Coverage { get; set; }
700+
public string[] ExcludeAssemblies { get; set; }
701+
public string[] IncludeAssemblies { get; set; }
697702
}
698703
}

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ tool for most developers. It is currently in Beta.
2020

2121
With the old coverage it was possible for FCC to provide an abstraction over each tool's exclusion / inclusion options. This abstraction does not work for MS code coverage.
2222
Thus you will find that there are separate configuration options for Ms coverage vs old coverage and options that are common to the two.
23+
Assembly level exclusions and inclusions can be achieved - see ExcludeAssemblies and IncludeAssemblies.
2324
Configuration is ( mostly ) determined from Visual Studio options, finecodecoverage-settings.xml files and project msbuild properties. All of these settings are optional.
2425
For options that have a project scope, these settings form a hierarchy where lower levels override or, for collections, override or merge with the level above. This is described in detail further on.
2526

@@ -260,6 +261,8 @@ RunMsCodeCoverage Change to IfInRunSettings to only collect w
260261
261262
IncludeTestAssembly Specifies whether to report code coverage of the test assembly
262263
IncludeReferencedProjects Set to true to add all referenced projects to Include.
264+
IncludeAssemblies Provide a list of assemblies to include in coverage. The dll name without extension is used for matching.
265+
ExcludeAssemblies Provide a list of assemblies to exclude from coverage. The dll name without extension is used for matching.
263266
264267
*** OpenCover / Coverlet
265268
AdjacentBuildOutput If your tests are dependent upon their path set this to true.
@@ -321,7 +324,8 @@ ThresholdForCrapScore When [crap score](https://testing.googleblog.
321324
```
322325
## Exclusions and inclusions
323326
You probably want to set IncludeReferencedProjects to true. This will ensure that you do not get coverage for testing frameworks - only your code.
324-
327+
Coverlet and OpenCover use [filter expressions](https://github.com/coverlet-coverage/coverlet/blob/master/Documentation/MSBuildIntegration.md#filters).
328+
Ms code coverage uses [regexes](https://learn.microsoft.com/en-us/visualstudio/test/customizing-code-coverage-analysis?view=vs-2022#regular-expressions).
325329

326330
## FCC Output
327331
FCC outputs, by default, inside each test project's Debug folder.

SharedProject/Core/Model/CoverageProjectSettingsManager.cs

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
using FineCodeCoverage.Options;
2+
using System;
3+
using System.Collections.Generic;
24
using System.ComponentModel.Composition;
35
using System.IO;
6+
using System.Linq;
47
using System.Threading.Tasks;
58

69
namespace FineCodeCoverage.Engine.Model
@@ -32,7 +35,44 @@ public async Task<IAppOptions> GetSettingsAsync(ICoverageProject coverageProject
3235
var projectDirectory = Path.GetDirectoryName(coverageProject.ProjectFile);
3336
var settingsFilesElements = fccSettingsFilesProvider.Provide(projectDirectory);
3437
var projectSettingsElement = await coverageProjectSettingsProvider.ProvideAsync(coverageProject);
35-
return settingsMerger.Merge(appOptionsProvider.Get(), settingsFilesElements, projectSettingsElement);
38+
var merged = settingsMerger.Merge(appOptionsProvider.Get(), settingsFilesElements, projectSettingsElement);
39+
AddCommonAssemblyExcludesIncludes(merged);
40+
return merged;
41+
}
42+
43+
private void AddCommonAssemblyExcludesIncludes(IAppOptions appOptions)
44+
{
45+
var (newOldStyleExclude,newMsExclude) = AddCommon(appOptions.Exclude, appOptions.ModulePathsExclude, appOptions.ExcludeAssemblies);
46+
var (newOldStyleInclude,newMsInclude) = AddCommon(appOptions.Include, appOptions.ModulePathsInclude, appOptions.IncludeAssemblies);
47+
appOptions.Exclude = newOldStyleExclude;
48+
appOptions.Include = newOldStyleInclude;
49+
appOptions.ModulePathsExclude = newMsExclude;
50+
appOptions.ModulePathsInclude = newMsInclude;
51+
}
52+
53+
private (string[] newOldStyle,string[] newMs) AddCommon(string[] oldStyle,string[] ms, string[] common )
54+
{
55+
if(common == null)
56+
{
57+
return(oldStyle,ms);
58+
}
59+
var newMs = ListFromExisting(ms);
60+
var newOldStyle = ListFromExisting(oldStyle);
61+
62+
common.ToList().ForEach(assemblyFileName =>
63+
{
64+
var msModulePath = $".*\\{assemblyFileName}.dll$";
65+
newMs.Add(msModulePath);
66+
var old = $"[{assemblyFileName}]*";
67+
newOldStyle.Add(old);
68+
});
69+
70+
return (newOldStyle.ToArray(), newMs.ToArray());
71+
}
72+
73+
private List<string> ListFromExisting(string[] existing)
74+
{
75+
return new List<string>(existing ?? new string[0]);
3676
}
3777
}
3878

SharedProject/Options/AppOptionsPage.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,18 @@ private static IAppOptionsStorageProvider GetAppOptionsStorageProvider()
7878
@"Specifies whether to report code coverage of the test assembly
7979
")]
8080
public bool IncludeTestAssembly { get; set; }
81+
82+
[Category(commonExcludeIncludeCategory)]
83+
[Description(
84+
@"Provide a list of assemblies to exclude from coverage. The dll name without extension is used for matching.
85+
")]
86+
public string[] ExcludeAssemblies { get; set; }
87+
88+
[Category(commonExcludeIncludeCategory)]
89+
[Description(
90+
@"Provide a list of assemblies to include in coverage. The dll name without extension is used for matching.
91+
")]
92+
public string[] IncludeAssemblies { get; set; }
8193
#endregion
8294

8395
#region old exclude include

SharedProject/Options/AppOptionsProvider.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,5 +205,7 @@ internal class AppOptions : IAppOptions
205205

206206
public bool IncludeReferencedProjects { get; set; }
207207
public bool ShowToolWindowToolbar { get; set; }
208+
public string[] ExcludeAssemblies { get; set; }
209+
public string[] IncludeAssemblies { get; set; }
208210
}
209211
}

SharedProject/Options/IAppOptions.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ internal interface IFCCCommonOptions
55
bool Enabled { get; set; }
66
bool IncludeTestAssembly { get; set; }
77
bool IncludeReferencedProjects { get; set; }
8+
9+
string[] ExcludeAssemblies { get; set; }
10+
string[] IncludeAssemblies { get; set; }
811
}
912

1013
internal interface IMsCodeCoverageIncludesExcludesOptions
@@ -23,15 +26,17 @@ internal interface IMsCodeCoverageIncludesExcludesOptions
2326
string[] FunctionsExclude { get; set; }
2427
}
2528
internal interface IMsCodeCoverageOptions : IMsCodeCoverageIncludesExcludesOptions, IFCCCommonOptions { }
26-
2729
internal enum RunMsCodeCoverage { No, IfInRunSettings, Yes }
2830

29-
internal interface IAppOptions : IMsCodeCoverageOptions, IFCCCommonOptions
31+
internal interface IOpenCoverCoverletExcludeIncludeOptions
3032
{
3133
string[] Exclude { get; set; }
3234
string[] ExcludeByAttribute { get; set; }
3335
string[] ExcludeByFile { get; set; }
3436
string[] Include { get; set; }
37+
}
38+
internal interface IAppOptions : IMsCodeCoverageOptions, IOpenCoverCoverletExcludeIncludeOptions, IFCCCommonOptions
39+
{
3540
bool RunInParallel { get; set; }
3641
int RunWhenTestsExceed { get; set; }
3742
string ToolsDirectory { get; set; }

0 commit comments

Comments
 (0)