diff --git a/.gitignore b/.gitignore
index bd4d918a..de9a4f43 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,3 +22,4 @@ x64/
*.ncrunchproject
_NCrunch_WebCompiler
/MSBuild_Logs
+/MigrationBackup/f1627d49/FineCodeCoverageTests
diff --git a/Art/Options-Global.png b/Art/Options-Global.png
index 2f030f15..d1bd3286 100644
Binary files a/Art/Options-Global.png and b/Art/Options-Global.png differ
diff --git a/Art/Output-Coverage.png b/Art/Output-Coverage.png
index 16a68653..f82c794e 100644
Binary files a/Art/Output-Coverage.png and b/Art/Output-Coverage.png differ
diff --git a/Art/Output-RiskHotspots.png b/Art/Output-RiskHotspots.png
index b4d83785..531cfa8b 100644
Binary files a/Art/Output-RiskHotspots.png and b/Art/Output-RiskHotspots.png differ
diff --git a/Art/Output-Summary.png b/Art/Output-Summary.png
index 8b44de21..3e5817b7 100644
Binary files a/Art/Output-Summary.png and b/Art/Output-Summary.png differ
diff --git a/Art/preview-coverage.png b/Art/preview-coverage.png
index 02705ac5..aa88146d 100644
Binary files a/Art/preview-coverage.png and b/Art/preview-coverage.png differ
diff --git a/FineCodeCoverage.sln b/FineCodeCoverage.sln
index cadbfd26..9826e5fe 100644
--- a/FineCodeCoverage.sln
+++ b/FineCodeCoverage.sln
@@ -7,7 +7,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FineCodeCoverage", "FineCod
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution", "Solution", "{208EE360-4076-4680-A9B7-2BA9C17EA9FB}"
ProjectSection(SolutionItems) = preProject
- .editorconfig = .editorconfig
.gitattributes = .gitattributes
.gitignore = .gitignore
.github\workflows\addVsixLinkToIssues.yaml = .github\workflows\addVsixLinkToIssues.yaml
diff --git a/FineCodeCoverage/FineCodeCoverage.csproj b/FineCodeCoverage/FineCodeCoverage.csproj
index 2b17f798..e0a731f1 100644
--- a/FineCodeCoverage/FineCodeCoverage.csproj
+++ b/FineCodeCoverage/FineCodeCoverage.csproj
@@ -150,8 +150,26 @@
1.4.1
+
+ 3.11.0
+
+
+ 3.11.0
+
+
+ 3.11.0
+
+
+ 3.11.0
+
+
+ 3.11.0
+
- 3.8.0
+ 3.11.0
+
+
+ 16.9.20
compile; build; native; contentfiles; analyzers; buildtransitive
@@ -159,6 +177,11 @@
11.0.61030
+
+ 17.9.28
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
diff --git a/FineCodeCoverage/source.extension.vsixmanifest b/FineCodeCoverage/source.extension.vsixmanifest
index a4809dbb..f554f1a2 100644
--- a/FineCodeCoverage/source.extension.vsixmanifest
+++ b/FineCodeCoverage/source.extension.vsixmanifest
@@ -7,7 +7,6 @@
https://marketplace.visualstudio.com/items?itemName=FortuneNgwenya.FineCodeCoverage
Resources\LICENSE
Resources\logo.png
- Resources\preview-coverage.png
visual studio; code coverage; c#; vb; .net core; coverlet; unit test; free; community edition
diff --git a/FineCodeCoverage2022/FineCodeCoverage2022.csproj b/FineCodeCoverage2022/FineCodeCoverage2022.csproj
index c5d38f63..2f44f446 100644
--- a/FineCodeCoverage2022/FineCodeCoverage2022.csproj
+++ b/FineCodeCoverage2022/FineCodeCoverage2022.csproj
@@ -32,7 +32,7 @@
full
false
bin\Debug\
- DEBUG;TRACE
+ TRACE;DEBUG;VS2022
prompt
4
@@ -145,8 +145,26 @@
1.4.1
+
+ 4.8.0
+
+
+ 4.8.0
+
+
+ 4.8.0
+
+
+ 4.8.0
+
+
+ 4.8.0
+
- 4.0.1
+ 4.8.0
+
+
+ 17.7.40
compile; build; native; contentfiles; analyzers; buildtransitive
@@ -154,6 +172,11 @@
11.0.61030
+
+ 17.9.28
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
@@ -167,6 +190,9 @@
1.0.0
+
+ 2.16.36
+
3.3.0
diff --git a/FineCodeCoverage2022/Properties/AssemblyInfo.cs b/FineCodeCoverage2022/Properties/AssemblyInfo.cs
index 1ea8818b..338f561d 100644
--- a/FineCodeCoverage2022/Properties/AssemblyInfo.cs
+++ b/FineCodeCoverage2022/Properties/AssemblyInfo.cs
@@ -31,3 +31,6 @@
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
+
+[assembly: InternalsVisibleTo("FineCodeCoverageTests")]
+[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
diff --git a/FineCodeCoverage2022/source.extension.vsixmanifest b/FineCodeCoverage2022/source.extension.vsixmanifest
index 757c6250..67cfccb0 100644
--- a/FineCodeCoverage2022/source.extension.vsixmanifest
+++ b/FineCodeCoverage2022/source.extension.vsixmanifest
@@ -7,7 +7,6 @@
https://marketplace.visualstudio.com/items?itemName=FortuneNgwenya.FineCodeCoverage
Resources\LICENSE
Resources\logo.png
- Resources\preview-coverage.png
visual studio; code coverage; c#; vb; .net core; coverlet; unit test; free; community edition
diff --git a/FineCodeCoverageTests/AppOptionsProvider_Tests.cs b/FineCodeCoverageTests/AppOptionsProvider_Tests.cs
index 05d6be95..dce37834 100644
--- a/FineCodeCoverageTests/AppOptionsProvider_Tests.cs
+++ b/FineCodeCoverageTests/AppOptionsProvider_Tests.cs
@@ -4,6 +4,7 @@
using AutoMoq;
using FineCodeCoverage.Core.Utilities;
using FineCodeCoverage.Options;
+using Microsoft.VisualStudio.Settings;
using Moq;
using NUnit.Framework;
@@ -13,16 +14,16 @@ public class AppOptionsProvider_Tests
{
private AutoMoqer autoMocker;
private AppOptionsProvider appOptionsProvider;
- private Mock mockWritableSettingsStore;
+ private Mock mockWritableSettingsStore;
[SetUp]
public void Setup()
{
autoMocker = new AutoMoqer();
appOptionsProvider = autoMocker.Create();
- mockWritableSettingsStore = new Mock();
- var mockWritableSettingsStoreProvider = autoMocker.GetMock();
- mockWritableSettingsStoreProvider.Setup(
+ mockWritableSettingsStore = new Mock();
+ var mockWritableUserSettingsStoreProvider = autoMocker.GetMock();
+ mockWritableUserSettingsStoreProvider.Setup(
writableSettingsStoreProvider => writableSettingsStoreProvider.Provide()
).Returns(mockWritableSettingsStore.Object);
}
@@ -205,7 +206,16 @@ public void Should_Not_Default_Any_Other_AppOptions_Properties()
nameof(IAppOptions.ShowPartiallyCoveredInOverviewMargin),
nameof(IAppOptions.ShowToolWindowToolbar),
nameof(IAppOptions.Hide0Coverable),
- nameof(IAppOptions.DisabledNoCoverage)
+ nameof(IAppOptions.DisabledNoCoverage),
+ nameof(IAppOptions.ShowEditorCoverage),
+ nameof(IAppOptions.ShowCoverageInGlyphMargin),
+ nameof(IAppOptions.ShowCoveredInGlyphMargin),
+ nameof(IAppOptions.ShowUncoveredInGlyphMargin),
+ nameof(IAppOptions.ShowPartiallyCoveredInGlyphMargin),
+ nameof(IAppOptions.ShowLineCoveredHighlighting),
+ nameof(IAppOptions.ShowLinePartiallyCoveredHighlighting),
+ nameof(IAppOptions.ShowLineUncoveredHighlighting),
+ nameof(IAppOptions.UseEnterpriseFontsAndColors)
};
CollectionAssert.AreEquivalent(expectedSetters.Select(s => $"set_{s}"), invocationNames);
}
@@ -273,7 +283,6 @@ internal void Should_Use_Deseralized_String_From_Store_For_AppOption_Property(Fu
{ nameof(IAppOptions.AttributesInclude), new string[]{ "ainclude"}},
{ nameof(IAppOptions.CompanyNamesExclude), new string[]{ "cexclude"}},
{ nameof(IAppOptions.CompanyNamesInclude), new string[]{ "cinclude"}},
- { nameof(IAppOptions.CoverageColoursFromFontsAndColours), true},
{ nameof(IAppOptions.CoverletCollectorDirectoryPath), "p"},
{ nameof(IAppOptions.CoverletConsoleCustomPath), "cp"},
{ nameof(IAppOptions.CoverletConsoleGlobal), true},
@@ -313,14 +322,34 @@ internal void Should_Use_Deseralized_String_From_Store_For_AppOption_Property(Fu
{ nameof(IAppOptions.ShowCoverageInOverviewMargin),true},
{ nameof(IAppOptions.ShowCoveredInOverviewMargin),true},
{ nameof(IAppOptions.ShowPartiallyCoveredInOverviewMargin),true},
+ { nameof(IAppOptions.ShowDirtyInOverviewMargin), true },
+ { nameof(IAppOptions.ShowNewInOverviewMargin), true },
{ nameof(IAppOptions.ShowUncoveredInOverviewMargin),true},
+ { nameof(IAppOptions.ShowNotIncludedInOverviewMargin),true},
{ nameof(IAppOptions.ShowToolWindowToolbar),true},
{nameof(IAppOptions.ExcludeAssemblies),new string[]{ "Exclude"} },
{nameof(IAppOptions.IncludeAssemblies),new string[]{ "Include"} },
{nameof(IAppOptions.NamespaceQualification),NamespaceQualification.AlwaysUnqualified },
{nameof(IAppOptions.OpenCoverRegister),OpenCoverRegister.Default },
{nameof(IAppOptions.OpenCoverTarget),"" },
- {nameof(IAppOptions.OpenCoverTargetArgs),"" }
+ {nameof(IAppOptions.OpenCoverTargetArgs),"" },
+ {nameof(IAppOptions.ShowEditorCoverage),true },
+ {nameof(IAppOptions.ShowCoverageInGlyphMargin),true },
+ {nameof(IAppOptions.ShowCoveredInGlyphMargin),true },
+ {nameof(IAppOptions.ShowPartiallyCoveredInGlyphMargin),true },
+ {nameof(IAppOptions.ShowUncoveredInGlyphMargin),true },
+ {nameof(IAppOptions.ShowDirtyInGlyphMargin),true },
+ {nameof(IAppOptions.ShowNewInGlyphMargin),true },
+ {nameof(IAppOptions.ShowNotIncludedInGlyphMargin),true },
+ {nameof(IAppOptions.ShowLineCoverageHighlighting),true },
+ {nameof(IAppOptions.ShowLineCoveredHighlighting),true },
+ {nameof(IAppOptions.ShowLinePartiallyCoveredHighlighting),true },
+ {nameof(IAppOptions.ShowLineUncoveredHighlighting),true },
+ {nameof(IAppOptions.ShowLineDirtyHighlighting),true },
+ {nameof(IAppOptions.ShowLineNewHighlighting),true },
+ {nameof(IAppOptions.ShowLineNotIncludedHighlighting),true },
+ {nameof(IAppOptions.UseEnterpriseFontsAndColors),true },
+ {nameof(IAppOptions.EditorCoverageColouringMode), EditorCoverageColouringMode.UseRoslynWhenTextChanges }
};
var mockJsonConvertService = autoMocker.GetMock();
mockJsonConvertService.Setup(
diff --git a/FineCodeCoverageTests/CoberturaDeserializer_Tests.cs b/FineCodeCoverageTests/CoberturaDeserializer_Tests.cs
new file mode 100644
index 00000000..d88e3c52
--- /dev/null
+++ b/FineCodeCoverageTests/CoberturaDeserializer_Tests.cs
@@ -0,0 +1,63 @@
+using NUnit.Framework;
+using System.IO;
+using FineCodeCoverage.Engine.Cobertura;
+using System;
+using System.Linq;
+
+namespace FineCodeCoverageTests
+{
+ public class CoberturaDeserializer_Tests
+ {
+ [Test]
+ public void Should_Deserialize_What_Is_Required()
+ {
+ var cobertura = @"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+";
+
+ string fileName = System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".xml";
+ File.WriteAllText(fileName, cobertura);
+ var report = new CoberturaDerializer().Deserialize(fileName);
+ var package = report.Packages.Single();
+ Assert.AreEqual("DemoOpenCover", package.Name);
+ var packageClass = package.Classes.Single();
+ Assert.AreEqual(".LargeClass", packageClass.Name);
+ Assert.AreEqual(@"C:\Users\tonyh\source\repos\DemoOpenCover\DemoOpenCover\LargeClass.cs", packageClass.Filename);
+ Assert.AreEqual(1, packageClass.LineRate);
+ Assert.AreEqual(1, packageClass.BranchRate);
+ Assert.AreEqual(501, packageClass.Complexity);
+ var method = packageClass.Methods.Single();
+ Assert.AreEqual("Method0", method.Name);
+ Assert.AreEqual("()", method.Signature);
+ Assert.AreEqual(1, method.LineRate);
+ Assert.AreEqual(1, method.BranchRate);
+ var line = method.Lines.Single();
+ Assert.AreEqual(1, line.Number);
+ Assert.AreEqual(1, line.Hits);
+ line = packageClass.Lines.Single();
+ Assert.AreEqual(1, line.Number);
+ Assert.AreEqual(1, line.Hits);
+ }
+ }
+}
diff --git a/FineCodeCoverageTests/CoberturaUtil_Tests.cs b/FineCodeCoverageTests/CoberturaUtil_Tests.cs
new file mode 100644
index 00000000..78dc901f
--- /dev/null
+++ b/FineCodeCoverageTests/CoberturaUtil_Tests.cs
@@ -0,0 +1,229 @@
+using System;
+using System.Collections.Generic;
+using AutoMoq;
+using FineCodeCoverage.Core.Utilities;
+using FineCodeCoverage.Engine.Cobertura;
+using FineCodeCoverage.Engine.Model;
+using FineCodeCoverageTests.TestHelpers;
+using Moq;
+using NUnit.Framework;
+
+namespace FineCodeCoverageTests
+{
+ public class CoberturaUtil_Tests
+ {
+ [Test]
+ public void Should_Populate_And_Sort_FileLineCoverage_From_Deserialized_Report()
+ {
+ var autoMoqer = new AutoMoqer();
+ var reportPath = "reportpath";
+
+ var noHitsLine = new Line
+ {
+ Hits = 0,
+ Number = 1
+ };
+ var partialHitsLine = new Line
+ {
+ Hits = 1,
+ ConditionCoverage = "99% .....",
+ Number = 2
+ };
+ var coveredLine = new Line
+ {
+ Hits = 1,
+ ConditionCoverage = "100% .....",
+ Number = 3
+ };
+ var noConditionCoverageLine = new Line
+ {
+ Hits = 1,
+ Number = 4
+ };
+ var coverageReport = new CoverageReport
+ {
+ Packages = new List
+ {
+ new Package
+ {
+ Classes = new List
+ {
+ new Class
+ {
+ Filename = "filename",
+
+ Lines = new List
+ {
+ noHitsLine,
+ partialHitsLine,
+ coveredLine,
+ noConditionCoverageLine
+ }
+
+ }
+ }
+ }
+ }
+ };
+ autoMoqer.Setup(x => x.Deserialize(reportPath)).Returns(coverageReport);
+ var mockFileLineCoverage = new Mock();
+ var expectedLines = new List
+ {
+ CreateExpectedLine(1, CoverageType.NotCovered),
+ CreateExpectedLine(2, CoverageType.Partial),
+ CreateExpectedLine(3, CoverageType.Covered),
+ CreateExpectedLine(4, CoverageType.Covered)
+ };
+ var sorted = false;
+ mockFileLineCoverage.Setup(fileLineCoverage => fileLineCoverage.Add("filename", MoqMatchers.EnumerableExpected(
+ expectedLines,
+ (a, b) => a.Number == b.Number && a.CoverageType == b.CoverageType)
+ )).Callback(() => Assert.That(sorted, Is.False));
+ mockFileLineCoverage.Setup(fileLineCoverage => fileLineCoverage.Sort()).Callback(() => sorted = true);
+
+ autoMoqer.Setup(fileLineCoverageFactory => fileLineCoverageFactory.Create())
+ .Returns(mockFileLineCoverage.Object);
+ var coberturaUtil = autoMoqer.Create();
+
+ var processed = coberturaUtil.ProcessCoberturaXml(reportPath);
+
+
+ Assert.That(processed, Is.SameAs(mockFileLineCoverage.Object));
+ mockFileLineCoverage.VerifyAll();
+ }
+
+ [Test]
+ public void Should_Update_FileLineCoverage_When_File_Renamed()
+ {
+ var autoMoqer = new AutoMoqer();
+ var mockFileRenameListener = autoMoqer.GetMock();
+ Action fileRenamedCallback = null;
+ mockFileRenameListener.Setup(fileRenameListener => fileRenameListener.ListenForFileRename(It.IsAny>()))
+ .Callback>(action => fileRenamedCallback = action);
+
+ var coverageReport = new CoverageReport
+ {
+ Packages = new List()
+ };
+ autoMoqer.Setup(x => x.Deserialize(It.IsAny())).Returns(coverageReport);
+ var mockFileLineCoverage = new Mock();
+ autoMoqer.Setup(fileLineCoverageFactory => fileLineCoverageFactory.Create())
+ .Returns(mockFileLineCoverage.Object);
+ var coberturaUtil = autoMoqer.Create();
+
+ coberturaUtil.ProcessCoberturaXml("");
+ fileRenamedCallback("oldfile", "newfile");
+
+ mockFileLineCoverage.Verify(fileLineCoverage => fileLineCoverage.UpdateRenamed("oldfile", "newfile"), Times.Once);
+
+ }
+
+ [Test]
+ public void Should_Not_Throw_When_File_Renamed_And_No_Coverage()
+ {
+ var autoMoqer = new AutoMoqer();
+ var mockFileRenameListener = autoMoqer.GetMock();
+ mockFileRenameListener.Setup(fileRenameListener => fileRenameListener.ListenForFileRename(It.IsAny>()))
+ .Callback>(action => action("",""));
+
+ var coberturaUtil = autoMoqer.Create();
+
+
+ }
+
+ private void SourceFilesTest(
+ Action sourceFilesAssertion,
+ List packages,
+ string assemblyName,
+ string qualifiedClassName,
+ int file = -1)
+ {
+ var autoMoqer = new AutoMoqer();
+ autoMoqer.Setup(fileLineCoverageFactory => fileLineCoverageFactory.Create())
+ .Returns(new Mock().Object);
+
+ var coverageReport = new CoverageReport
+ {
+ Packages = packages
+ };
+ autoMoqer.Setup(x => x.Deserialize(It.IsAny())).Returns(coverageReport);
+
+ var coberturaUtil = autoMoqer.Create();
+ coberturaUtil.ProcessCoberturaXml("");
+
+ var sourceFiles = coberturaUtil.GetSourceFiles(assemblyName, qualifiedClassName, file);
+ sourceFilesAssertion(sourceFiles);
+ }
+
+ [Test]
+ public void Should_Return_Empty_Source_Files_If_Assembly_Not_In_The_CoverageReport()
+ {
+ var packages = new List
+ {
+ new Package
+ {
+ Name = "otherassembly",
+ Classes = new List()
+ }
+ };
+
+ SourceFilesTest(sourceFiles => Assert.That(sourceFiles, Is.Empty), packages, "missingassembly", "qcn");
+ }
+
+ private void AssemblyInReportTest(Action sourceFilesAssertion, int fileIndex = -1)
+ {
+ var packages = new List
+ {
+ new Package
+ {
+ Name = "assembly",
+ Classes = new List
+ {
+ new Class
+ {
+ Name = "qcn",
+ Filename = "file1",
+ Lines = new List{ }
+ },
+ new Class
+ {
+ Name = "qcn",
+ Filename = "file2",
+ Lines = new List{ }
+ },
+ new Class
+ {
+ Name = "other",
+ Filename = "file3",
+ Lines = new List{ }
+ }
+ }
+ }
+ };
+
+ SourceFilesTest(sourceFilesAssertion, packages, "assembly", "qcn",fileIndex);
+ }
+
+ [Test]
+ public void Should_Return_Source_Files_Of_All_Matching_Classes_When_FileIndex_Is_Minus1()
+ {
+ AssemblyInReportTest(sourceFiles => Assert.That(sourceFiles, Is.EqualTo(new List { "file1", "file2"})));
+ }
+
+ [TestCase(0)]
+ [TestCase(1)]
+ public void Should_Return_Single_SourceFile_When_FileIndex_Is_Not_Minus1(int fileIndex)
+ {
+ var expectedFile = fileIndex == 0 ? "file1" : "file2";
+ AssemblyInReportTest(sourceFiles => Assert.That(sourceFiles, Is.EqualTo(new List { expectedFile })),fileIndex);
+ }
+
+ private static ILine CreateExpectedLine(int number, CoverageType coverageType)
+ {
+ var mockLine = new Mock();
+ mockLine.SetupGet(x => x.Number).Returns(number);
+ mockLine.SetupGet(x => x.CoverageType).Returns(coverageType);
+ return mockLine.Object;
+ }
+ }
+}
diff --git a/FineCodeCoverageTests/CoverageProject_Settings_Tests.cs b/FineCodeCoverageTests/CoverageProject_Settings_Tests.cs
index 5335b8ac..05eac5a9 100644
--- a/FineCodeCoverageTests/CoverageProject_Settings_Tests.cs
+++ b/FineCodeCoverageTests/CoverageProject_Settings_Tests.cs
@@ -2,7 +2,7 @@
using FineCodeCoverage.Core.Utilities;
using FineCodeCoverage.Engine.Model;
using FineCodeCoverage.Options;
-using FineCodeCoverageTests.Test_helpers;
+using FineCodeCoverageTests.TestHelpers;
using Moq;
using NUnit.Framework;
using StructureMap.AutoMocking;
@@ -85,7 +85,7 @@ private List Provide(string projectDirectoryFCCOptions, string solutio
public class CoverageProjectSettingsProvider_Tests
{
[Test]
- public async Task Should_Return_The_FineCodeCoverage_Labelled_PropertyGroup()
+ public async Task Should_Return_The_FineCodeCoverage_Labelled_PropertyGroup_Async()
{
var coverageProjectSettingsProvider = new CoverageProjectSettingsProvider(null);
var mockCoverageProject = new Mock();
@@ -108,7 +108,7 @@ public async Task Should_Return_The_FineCodeCoverage_Labelled_PropertyGroup()
[TestCase(true)]
[TestCase(false)]
- public async Task Should_Return_Using_VsBuild_When_No_Labelled_PropertyGroup(bool returnNull)
+ public async Task Should_Return_Using_VsBuild_When_No_Labelled_PropertyGroup_Async(bool returnNull)
{
var mockCoverageProject = new Mock();
var coverageProjectGuid = Guid.NewGuid();
@@ -635,7 +635,7 @@ private XElement CreateIncludeReferencedProjectsElement(bool include)
public class CoverageProjectSettingsManager_Tests
{
[Test]
- public async Task Should_Provide_The_Merged_Result_Using_Global_Options()
+ public async Task Should_Provide_The_Merged_Result_Using_Global_Options_Async()
{
var mockAppOptionsProvider = new Mock();
var mockAppOptions = new Mock();
@@ -662,7 +662,7 @@ public async Task Should_Provide_The_Merged_Result_Using_Global_Options()
}
[Test]
- public async Task Should_Provide_The_Merged_Result_Using_FCC_Settings_Files()
+ public async Task Should_Provide_The_Merged_Result_Using_FCC_Settings_Files_Async()
{
var mockCoverageProject = new Mock();
mockCoverageProject.Setup(cp => cp.ProjectFile).Returns("SomeProject/SomeProject.csproj");
@@ -693,7 +693,7 @@ public async Task Should_Provide_The_Merged_Result_Using_FCC_Settings_Files()
}
[Test]
- public async Task Should_Provide_The_Merged_Result_Using_Project_Settings()
+ public async Task Should_Provide_The_Merged_Result_Using_Project_Settings_Async()
{
var coverageProject = new Mock().Object;
@@ -723,7 +723,7 @@ public async Task Should_Provide_The_Merged_Result_Using_Project_Settings()
}
[Test]
- public async Task Should_Add_Common_Assembly_Excludes_Includes()
+ public async Task Should_Add_Common_Assembly_Excludes_Includes_Async()
{
var mockAppOptions = new Mock();
mockAppOptions.SetupAllProperties();
diff --git a/FineCodeCoverageTests/CoverageToolOutput_Tests/AppOptionsCoverageToolOutputFolderSolutionProvider_Tests.cs b/FineCodeCoverageTests/CoverageToolOutput_Tests/AppOptionsCoverageToolOutputFolderSolutionProvider_Tests.cs
index ead21d0e..32dc7b9d 100644
--- a/FineCodeCoverageTests/CoverageToolOutput_Tests/AppOptionsCoverageToolOutputFolderSolutionProvider_Tests.cs
+++ b/FineCodeCoverageTests/CoverageToolOutput_Tests/AppOptionsCoverageToolOutputFolderSolutionProvider_Tests.cs
@@ -7,7 +7,7 @@
using AutoMoq;
using FineCodeCoverage.Engine;
using FineCodeCoverage.Options;
-using FineCodeCoverageTests.Test_helpers;
+using FineCodeCoverageTests.TestHelpers;
using Moq;
using NUnit.Framework;
diff --git a/FineCodeCoverageTests/CoverageToolOutput_Tests/CoverageToolOutputFolderFromSolutionProvider_Tests.cs b/FineCodeCoverageTests/CoverageToolOutput_Tests/CoverageToolOutputFolderFromSolutionProvider_Tests.cs
index 1918f5f3..8d6d032a 100644
--- a/FineCodeCoverageTests/CoverageToolOutput_Tests/CoverageToolOutputFolderFromSolutionProvider_Tests.cs
+++ b/FineCodeCoverageTests/CoverageToolOutput_Tests/CoverageToolOutputFolderFromSolutionProvider_Tests.cs
@@ -7,7 +7,7 @@
using FineCodeCoverage.Core.Utilities;
using FineCodeCoverage.Engine;
using FineCodeCoverage.Engine.Model;
-using FineCodeCoverageTests.Test_helpers;
+using FineCodeCoverageTests.TestHelpers;
using Moq;
using NUnit.Framework;
diff --git a/FineCodeCoverageTests/CoverageToolOutput_Tests/CoverageToolOutput_Exports_Tests.cs b/FineCodeCoverageTests/CoverageToolOutput_Tests/CoverageToolOutput_Exports_Tests.cs
index 7e81b05e..e6ae0d00 100644
--- a/FineCodeCoverageTests/CoverageToolOutput_Tests/CoverageToolOutput_Exports_Tests.cs
+++ b/FineCodeCoverageTests/CoverageToolOutput_Tests/CoverageToolOutput_Exports_Tests.cs
@@ -4,7 +4,7 @@
using System.Text;
using System.Threading.Tasks;
using FineCodeCoverage.Engine;
-using FineCodeCoverageTests.Test_helpers;
+using FineCodeCoverageTests.TestHelpers;
using NUnit.Framework;
namespace FineCodeCoverageTests
diff --git a/FineCodeCoverageTests/CoverageToolOutput_Tests/FccOutputExistenceCoverageToolOutputFolderSolutionProvider_Tests.cs b/FineCodeCoverageTests/CoverageToolOutput_Tests/FccOutputExistenceCoverageToolOutputFolderSolutionProvider_Tests.cs
index e2009e3e..cf6276fe 100644
--- a/FineCodeCoverageTests/CoverageToolOutput_Tests/FccOutputExistenceCoverageToolOutputFolderSolutionProvider_Tests.cs
+++ b/FineCodeCoverageTests/CoverageToolOutput_Tests/FccOutputExistenceCoverageToolOutputFolderSolutionProvider_Tests.cs
@@ -7,7 +7,7 @@
using AutoMoq;
using FineCodeCoverage.Core.Utilities;
using FineCodeCoverage.Engine;
-using FineCodeCoverageTests.Test_helpers;
+using FineCodeCoverageTests.TestHelpers;
using NUnit.Framework;
namespace FineCodeCoverageTests.CoverageToolOutput_Tests
diff --git a/FineCodeCoverageTests/CoverageToolOutput_Tests/SolutionFolderProvider_Tests.cs b/FineCodeCoverageTests/CoverageToolOutput_Tests/SolutionFolderProvider_Tests.cs
index 0a1cd1d6..69675a62 100644
--- a/FineCodeCoverageTests/CoverageToolOutput_Tests/SolutionFolderProvider_Tests.cs
+++ b/FineCodeCoverageTests/CoverageToolOutput_Tests/SolutionFolderProvider_Tests.cs
@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using System.IO;
using FineCodeCoverage.Core.Utilities;
using FineCodeCoverage.Engine;
using NUnit.Framework;
@@ -13,7 +8,7 @@ namespace FineCodeCoverageTests.CoverageToolOutput_Tests
class SolutionFolderProvider_Tests
{
private string tempDirectory;
- private FileUtil fileUtil = new FileUtil();
+ private readonly FileUtil fileUtil = new FileUtil();
[SetUp]
public void Create_Temp_Directory()
diff --git a/FineCodeCoverageTests/CoverageUtilManager_Tests.cs b/FineCodeCoverageTests/CoverageUtilManager_Tests.cs
index d3ffdfbc..655b07b9 100644
--- a/FineCodeCoverageTests/CoverageUtilManager_Tests.cs
+++ b/FineCodeCoverageTests/CoverageUtilManager_Tests.cs
@@ -35,7 +35,7 @@ public void Initialize_Should_Initialize_The_Coverage_Utils()
[TestCase(true)]
[TestCase(false)]
- public async Task Should_Run_The_Appropriate_Cover_Tool_Based_On_IsDotNetSdkStyle(bool isDotNetSdkStyle)
+ public async Task Should_Run_The_Appropriate_Cover_Tool_Based_On_IsDotNetSdkStyle_Async(bool isDotNetSdkStyle)
{
var mockProject = new Mock();
mockProject.Setup(cp => cp.IsDotNetSdkStyle()).Returns(isDotNetSdkStyle);
diff --git a/FineCodeCoverageTests/CoverletConsole_Tests.cs b/FineCodeCoverageTests/CoverletConsole_Tests.cs
index 3bda5f47..2cbe7342 100644
--- a/FineCodeCoverageTests/CoverletConsole_Tests.cs
+++ b/FineCodeCoverageTests/CoverletConsole_Tests.cs
@@ -57,10 +57,6 @@ private void AssertHasSetting(List coverletSettings, string setting)
Assert.IsTrue(coverletSettings.Any(coverletSetting => coverletSetting == setting));
}
- private void AssertHasEscapedSetting(List coverletSettings, string setting)
- {
- AssertHasSetting(coverletSettings, CommandLineArguments.AddQuotes(setting));
- }
}
public class CoverletConsoleExecuteRequestProvider_Tests
@@ -154,7 +150,7 @@ public void Should_Initilize_IFCCCoverletConsoleExeProvider()
}
[Test]
- public async Task Should_Execute_The_Request_From_The_Execute_Request_Provider_With_Space_Delimited_Settings()
+ public async Task Should_Execute_The_Request_From_The_Execute_Request_Provider_With_Space_Delimited_Settings_Async()
{
await RunSuccessfullyAsync();
@@ -162,7 +158,7 @@ public async Task Should_Execute_The_Request_From_The_Execute_Request_Provider_W
}
[Test]
- public async Task Should_Log_Settings_Before_Executing()
+ public async Task Should_Log_Settings_Before_Executing_Async()
{
var mockLogger = mocker.GetMock();
mockLogger.Setup(logger => logger.Log(It.IsAny>())).Callback>(messages =>
@@ -202,7 +198,7 @@ public void Should_Log_With_ExecuteResponse_ExitCode_And_Output_When_ExitCode_Is
}
[Test]
- public async Task Should_Log_The_ExecuteResponse_Output_On_Success()
+ public async Task Should_Log_The_ExecuteResponse_Output_On_Success_Async()
{
var mockLogger = mocker.GetMock();
mockLogger.Setup(logger => logger.Log(It.IsAny())).Callback(messages =>
diff --git a/FineCodeCoverageTests/CoverletDataCollectorUtil_CanUseDataCollector_Tests.cs b/FineCodeCoverageTests/CoverletDataCollectorUtil_CanUseDataCollector_Tests.cs
index 740e54a7..8af564e7 100644
--- a/FineCodeCoverageTests/CoverletDataCollectorUtil_CanUseDataCollector_Tests.cs
+++ b/FineCodeCoverageTests/CoverletDataCollectorUtil_CanUseDataCollector_Tests.cs
@@ -5,7 +5,7 @@
using FineCodeCoverage.Core.Utilities;
using FineCodeCoverage.Engine.Coverlet;
using FineCodeCoverage.Engine.Model;
-using FineCodeCoverageTests.Test_helpers;
+using FineCodeCoverageTests.TestHelpers;
using Moq;
using NUnit.Framework;
diff --git a/FineCodeCoverageTests/CoverletDataCollectorUtil_RunAsync_Tests.cs b/FineCodeCoverageTests/CoverletDataCollectorUtil_RunAsync_Tests.cs
index 8b60562d..0aaa407e 100644
--- a/FineCodeCoverageTests/CoverletDataCollectorUtil_RunAsync_Tests.cs
+++ b/FineCodeCoverageTests/CoverletDataCollectorUtil_RunAsync_Tests.cs
@@ -60,7 +60,7 @@ private DirectoryInfo CreateTemporaryDirectory()
[Test]
- public async Task Should_Get_Settings_With_TestDllFile()
+ public async Task Should_Get_Settings_With_TestDllFile_Async()
{
mockCoverageProject.Setup(cp => cp.TestDllFile).Returns("test.dll");
mockCoverageProject.Setup(cp => cp.CoverageOutputFolder).Returns("");
@@ -71,7 +71,7 @@ public async Task Should_Get_Settings_With_TestDllFile()
}
[Test]
- public async Task Should_Get_Settings_With_Exclude_From_CoverageProject_And_RunSettings()
+ public async Task Should_Get_Settings_With_Exclude_From_CoverageProject_And_RunSettings_Async()
{
var projectExclude = new string[] { "excluded" };
mockCoverageProject.Setup(cp => cp.Settings.Exclude).Returns(projectExclude);
@@ -84,7 +84,7 @@ public async Task Should_Get_Settings_With_Exclude_From_CoverageProject_And_RunS
}
[Test]
- public async Task Should_Not_Throw_When_Project_Setttings_Exclude_Is_Null()
+ public async Task Should_Not_Throw_When_Project_Setttings_Exclude_Is_Null_Async()
{
var referencedExcluded = new List { "referencedExcluded" };
mockCoverageProject.Setup(cp => cp.ExcludedReferencedProjects).Returns(referencedExcluded);
@@ -95,7 +95,7 @@ public async Task Should_Not_Throw_When_Project_Setttings_Exclude_Is_Null()
}
[Test]
- public async Task Should_Get_Settings_With_ExcludeByFile_From_CoverageProject_And_RunSettings()
+ public async Task Should_Get_Settings_With_ExcludeByFile_From_CoverageProject_And_RunSettings_Async()
{
var projectExcludeByFile = new string[] { "excludedByFile" };
mockCoverageProject.Setup(cp => cp.Settings.ExcludeByFile).Returns(projectExcludeByFile);
@@ -107,7 +107,7 @@ public async Task Should_Get_Settings_With_ExcludeByFile_From_CoverageProject_An
}
[Test]
- public async Task Should_Get_Settings_With_ExcludeByAttribute_From_CoverageProject_And_RunSettings()
+ public async Task Should_Get_Settings_With_ExcludeByAttribute_From_CoverageProject_And_RunSettings_Async()
{
var projectExcludeByAttribute = new string[] { "excludedByAttribute" };
mockCoverageProject.Setup(cp => cp.Settings.ExcludeByAttribute).Returns(projectExcludeByAttribute);
@@ -117,7 +117,7 @@ public async Task Should_Get_Settings_With_ExcludeByAttribute_From_CoverageProje
}
[Test]
- public async Task Should_Get_Settings_With_Include_From_CoverageProject_And_RunSettings()
+ public async Task Should_Get_Settings_With_Include_From_CoverageProject_And_RunSettings_Async()
{
var projectInclude= new string[] { "included" };
mockCoverageProject.Setup(cp => cp.Settings.Include).Returns(projectInclude);
@@ -130,7 +130,7 @@ public async Task Should_Get_Settings_With_Include_From_CoverageProject_And_RunS
[TestCase(true,"true")]
[TestCase(false, "false")]
- public async Task Should_Get_Settings_With_IncludeTestAssembly_From_CoverageProject_And_RunSettings(bool projectIncludeTestAssembly, string runSettingsIncludeTestAssembly)
+ public async Task Should_Get_Settings_With_IncludeTestAssembly_From_CoverageProject_And_RunSettings_Async(bool projectIncludeTestAssembly, string runSettingsIncludeTestAssembly)
{
mockCoverageProject.Setup(cp => cp.Settings.IncludeTestAssembly).Returns(projectIncludeTestAssembly);
mockCoverageProject.Setup(cp => cp.CoverageOutputFolder).Returns("");
@@ -141,7 +141,7 @@ public async Task Should_Get_Settings_With_IncludeTestAssembly_From_CoverageProj
[TestCase(true)]
[TestCase(false)]
- public async Task Should_Initialize_With_Options_And_Run_Settings_First(bool runSettingsOnly)
+ public async Task Should_Initialize_With_Options_And_Run_Settings_First_Async(bool runSettingsOnly)
{
mockCoverageProject.Setup(cp => cp.RunSettingsFile).Returns(".runsettings");
mockCoverageProject.Setup(cp => cp.CoverageOutputFolder).Returns("output");
@@ -157,7 +157,7 @@ public async Task Should_Initialize_With_Options_And_Run_Settings_First(bool run
}
[Test]
- public async Task Should_Get_Settings_With_ResultsDirectory()
+ public async Task Should_Get_Settings_With_ResultsDirectory_Async()
{
mockCoverageProject.Setup(cp => cp.CoverageOutputFolder).Returns("outputfolder");
await coverletDataCollectorUtil.RunAsync(CancellationToken.None);
@@ -165,21 +165,21 @@ public async Task Should_Get_Settings_With_ResultsDirectory()
}
[Test]
- public async Task Should_Get_Settings_With_Blame()
+ public async Task Should_Get_Settings_With_Blame_Async()
{
await coverletDataCollectorUtil.RunAsync(CancellationToken.None);
mockDataCollectorSettingsBuilder.Verify(b => b.WithBlame());
}
[Test]
- public async Task Should_Get_Settings_With_NoLogo()
+ public async Task Should_Get_Settings_With_NoLogo_Async()
{
await coverletDataCollectorUtil.RunAsync(CancellationToken.None);
mockDataCollectorSettingsBuilder.Verify(b => b.WithNoLogo());
}
[Test]
- public async Task Should_Get_Settings_With_Diagnostics()
+ public async Task Should_Get_Settings_With_Diagnostics_Async()
{
mockCoverageProject.Setup(cp => cp.CoverageOutputFolder).Returns("outputfolder");
await coverletDataCollectorUtil.RunAsync(CancellationToken.None);
@@ -187,7 +187,7 @@ public async Task Should_Get_Settings_With_Diagnostics()
}
[Test]
- public async Task Should_Get_Settings_With_IncludeDirectory_From_RunSettings()
+ public async Task Should_Get_Settings_With_IncludeDirectory_From_RunSettings_Async()
{
mockRunSettingsCoverletConfiguration.Setup(rsc => rsc.IncludeDirectory).Returns("includeDirectory");
await coverletDataCollectorUtil.RunAsync(CancellationToken.None);
@@ -195,7 +195,7 @@ public async Task Should_Get_Settings_With_IncludeDirectory_From_RunSettings()
}
[Test]
- public async Task Should_Get_Settings_With_SingleHit_From_RunSettings()
+ public async Task Should_Get_Settings_With_SingleHit_From_RunSettings_Async()
{
mockRunSettingsCoverletConfiguration.Setup(rsc => rsc.SingleHit).Returns("true...");
await coverletDataCollectorUtil.RunAsync(CancellationToken.None);
@@ -203,7 +203,7 @@ public async Task Should_Get_Settings_With_SingleHit_From_RunSettings()
}
[Test]
- public async Task Should_Get_Settings_With_UseSourceLink_From_RunSettings()
+ public async Task Should_Get_Settings_With_UseSourceLink_From_RunSettings_Async()
{
mockRunSettingsCoverletConfiguration.Setup(rsc => rsc.UseSourceLink).Returns("true...");
await coverletDataCollectorUtil.RunAsync(CancellationToken.None);
@@ -211,7 +211,7 @@ public async Task Should_Get_Settings_With_UseSourceLink_From_RunSettings()
}
[Test]
- public async Task Should_Get_Settings_With_SkipAutoProps_From_RunSettings()
+ public async Task Should_Get_Settings_With_SkipAutoProps_From_RunSettings_Async()
{
mockRunSettingsCoverletConfiguration.Setup(rsc => rsc.SkipAutoProps).Returns("true...");
await coverletDataCollectorUtil.RunAsync(CancellationToken.None);
@@ -219,7 +219,7 @@ public async Task Should_Get_Settings_With_SkipAutoProps_From_RunSettings()
}
[Test]
- public async Task Should_Log_VSTest_Run_With_Settings()
+ public async Task Should_Log_VSTest_Run_With_Settings_Async()
{
mockCoverageProject.Setup(cp => cp.ProjectName).Returns("TestProject");
mockCoverageProject.Setup(cp => cp.CoverageOutputFolder).Returns("");
@@ -229,7 +229,7 @@ public async Task Should_Log_VSTest_Run_With_Settings()
}
[Test]
- public async Task Should_Execute_DotNet_Test_Collect_XPlat_With_Settings_Using_The_ProcessUtil()
+ public async Task Should_Execute_DotNet_Test_Collect_XPlat_With_Settings_Using_The_ProcessUtil_Async()
{
mockCoverageProject.Setup(cp => cp.ProjectOutputFolder).Returns("projectOutputFolder");
mockCoverageProject.Setup(cp => cp.CoverageOutputFolder).Returns("");
@@ -240,7 +240,7 @@ public async Task Should_Execute_DotNet_Test_Collect_XPlat_With_Settings_Using_T
mocker.Verify(p => p.ExecuteAsync(It.Is(er => er.Arguments == @"test --collect:""XPlat Code Coverage"" settings --test-adapter-path testadapterpath" && er.FilePath == "dotnet" && er.WorkingDirectory == "projectOutputFolder"),ct));
}
- private async Task Use_Custom_TestAdapterPath()
+ private async Task Use_Custom_TestAdapterPath_Async()
{
CreateTemporaryDirectory();
mockCoverageProject.Setup(cp => cp.ProjectOutputFolder).Returns("projectOutputFolder");
@@ -254,21 +254,21 @@ private async Task Use_Custom_TestAdapterPath()
}
[Test]
- public async Task Should_Use_Custom_TestAdapterPath_Quoted_If_Specified_In_Settings_And_Exists()
+ public async Task Should_Use_Custom_TestAdapterPath_Quoted_If_Specified_In_Settings_And_Exists_Async()
{
- var ct = await Use_Custom_TestAdapterPath();
+ var ct = await Use_Custom_TestAdapterPath_Async();
mocker.Verify(p => p.ExecuteAsync(It.Is(er => er.Arguments == $@"test --collect:""XPlat Code Coverage"" settings --test-adapter-path ""{tempDirectory}""" && er.FilePath == "dotnet" && er.WorkingDirectory == "projectOutputFolder"),ct));
}
[Test]
- public async Task Should_Log_When_Using_Custom_TestAdapterPath()
+ public async Task Should_Log_When_Using_Custom_TestAdapterPath_Async()
{
- await Use_Custom_TestAdapterPath();
+ await Use_Custom_TestAdapterPath_Async();
mocker.Verify(l => l.Log($"Using custom coverlet data collector : {tempDirectory}"));
}
[Test]
- public async Task Should_Use_The_ProcessResponseProcessor()
+ public async Task Should_Use_The_ProcessResponseProcessor_Async()
{
mockCoverageProject.Setup(cp => cp.ProjectName).Returns("TestProject");
mockCoverageProject.Setup(cp => cp.CoverageOutputFolder).Returns("");
@@ -289,7 +289,7 @@ public async Task Should_Use_The_ProcessResponseProcessor()
[TestCase(2, false)]
[TestCase(1,true)]
[TestCase(0, true)]
- public async Task Should_Only_Be_Successful_With_ExitCode_0_Or_1(int exitCode, bool expectedSuccess)
+ public async Task Should_Only_Be_Successful_With_ExitCode_0_Or_1_Async(int exitCode, bool expectedSuccess)
{
var mockProcessResponseProcessor = mocker.GetMock();
Func _exitCodePredicate = null;
@@ -303,7 +303,7 @@ public async Task Should_Only_Be_Successful_With_ExitCode_0_Or_1(int exitCode, b
}
[Test]
- public async Task Should_Correct_The_CoberturaPath_Given_Successful_Execution()
+ public async Task Should_Correct_The_CoberturaPath_Given_Successful_Execution_Async()
{
mockCoverageProject.Setup(cp => cp.CoverageOutputFolder).Returns("outputFolder");
mockCoverageProject.Setup(cp => cp.CoverageOutputFile).Returns("outputFile");
diff --git a/FineCodeCoverageTests/CoverletUtil_Tests.cs b/FineCodeCoverageTests/CoverletUtil_Tests.cs
index e5610620..2450d3ab 100644
--- a/FineCodeCoverageTests/CoverletUtil_Tests.cs
+++ b/FineCodeCoverageTests/CoverletUtil_Tests.cs
@@ -29,7 +29,7 @@ public void Should_Initialize_The_GlobalTool_And_DataCollector()
}
[Test]
- public async Task Should_Use_The_DataCollector_If_Possible()
+ public async Task Should_Use_The_DataCollector_If_Possible_Async()
{
var ct = CancellationToken.None;
var project = new Mock().Object;
@@ -44,7 +44,7 @@ public async Task Should_Use_The_DataCollector_If_Possible()
}
[Test]
- public async Task Should_Use_The_Global_Tool_If_Not_Possible()
+ public async Task Should_Use_The_Global_Tool_If_Not_Possible_Async()
{
var ct = CancellationToken.None;
var project = new Mock().Object;
diff --git a/FineCodeCoverageTests/Editor/DynamicCoverage/BufferLineCoverage_Tests.cs b/FineCodeCoverageTests/Editor/DynamicCoverage/BufferLineCoverage_Tests.cs
new file mode 100644
index 00000000..e2b1b50e
--- /dev/null
+++ b/FineCodeCoverageTests/Editor/DynamicCoverage/BufferLineCoverage_Tests.cs
@@ -0,0 +1,456 @@
+using AutoMoq;
+using FineCodeCoverage.Core.Utilities;
+using FineCodeCoverage.Editor.DynamicCoverage;
+using FineCodeCoverage.Editor.Tagging.Base;
+using FineCodeCoverage.Engine;
+using FineCodeCoverage.Engine.Model;
+using FineCodeCoverage.Options;
+using Microsoft.VisualStudio.Text;
+using Microsoft.VisualStudio.Text.Editor;
+using Moq;
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace FineCodeCoverageTests.Editor.DynamicCoverage
+{
+ internal class NormalizedTextChangeCollection : List, INormalizedTextChangeCollection
+ {
+ public bool IncludesLineChanges => throw new NotImplementedException();
+ }
+
+ internal class BufferLineCoverage_Tests
+ {
+ private AutoMoqer autoMoqer;
+ private Mock mockTextSnapshot;
+ private Mock mockTextBuffer;
+ private Mock mockTextView;
+ private ITextSnapshot textSnapshot;
+ private ITextInfo textInfo;
+ private Mock mockAppOptions;
+
+ private ILine CreateLine()
+ {
+ var mockLine = new Mock();
+ mockLine.SetupGet(line => line.Number).Returns(1);
+ mockLine.SetupGet(line => line.CoverageType).Returns(CoverageType.Partial);
+ return mockLine.Object;
+ }
+ private void SetupEditorCoverageColouringMode(AutoMoqer autoMoqer,bool off = false)
+ {
+ mockAppOptions = new Mock();
+ mockAppOptions.SetupGet(appOptions => appOptions.EditorCoverageColouringMode).Returns(off ? EditorCoverageColouringMode.Off : EditorCoverageColouringMode.UseRoslynWhenTextChanges);
+ autoMoqer.Setup(appOptionsProvider => appOptionsProvider.Get()).Returns(mockAppOptions.Object);
+ }
+ private void SimpleTextInfoSetUp(bool editorCoverageOff = false,string contentTypeName = "CSharp")
+ {
+ autoMoqer = new AutoMoqer();
+ SetupEditorCoverageColouringMode(autoMoqer, editorCoverageOff);
+ mockTextView = new Mock();
+ mockTextBuffer = new Mock();
+ mockTextBuffer.Setup(textBuffer => textBuffer.ContentType.TypeName).Returns(contentTypeName);
+ mockTextSnapshot = new Mock();
+ textSnapshot = mockTextSnapshot.Object;
+ mockTextBuffer.Setup(textBuffer => textBuffer.CurrentSnapshot).Returns(textSnapshot);
+ var mockTextInfo = new Mock();
+ mockTextInfo.SetupGet(textInfo => textInfo.TextBuffer).Returns(mockTextBuffer.Object);
+ mockTextInfo.SetupGet(textInfo => textInfo.TextView).Returns(mockTextView.Object);
+ mockTextInfo.SetupGet(textInfo => textInfo.FilePath).Returns("filepath");
+ textInfo = mockTextInfo.Object;
+ autoMoqer.SetInstance(textInfo);
+ }
+
+ [TestCase("CSharp", Language.CSharp)]
+ [TestCase("Basic", Language.VB)]
+ [TestCase("C/C++", Language.CPP)]
+ public void Should_Create_Tracked_Lines_From_Existing_Coverage_Based_Upon_The_Content_Type_Language(string contentTypeName, Language expectedLanguage)
+ {
+ SimpleTextInfoSetUp(false,contentTypeName);
+
+ var lines = new List { CreateLine()};
+ var mockFileLineCoverage = autoMoqer.GetMock();
+ mockFileLineCoverage.Setup(fileLineCoverage => fileLineCoverage.GetLines("filepath")).Returns(lines);
+
+ var bufferLineCoverage = autoMoqer.Create();
+
+ autoMoqer.Verify(trackedLinesFactory => trackedLinesFactory.Create(lines, textSnapshot, expectedLanguage));
+ }
+
+ [Test]
+ public void Should_Not_Create_TrackedLines_If_EditorCoverageColouringMode_Is_Off()
+ {
+ SimpleTextInfoSetUp(true);
+
+ var bufferLineCoverage = autoMoqer.Create();
+
+ autoMoqer.Verify(trackedLinesFactory => trackedLinesFactory.Create(It.IsAny>(), It.IsAny(), It.IsAny()), Times.Never());
+ }
+
+ [Test]
+ public void Should_Not_Create_TrackedLines_From_NewCoverageLinesMessage_If_EditorCoverageColouringMode_Is_Off()
+ {
+ SimpleTextInfoSetUp(true);
+
+ var bufferLineCoverage = autoMoqer.Create();
+
+ var newCoverageLinesMessage = new NewCoverageLinesMessage { CoverageLines = new Mock().Object };
+ bufferLineCoverage.Handle(newCoverageLinesMessage);
+
+ autoMoqer.Verify(trackedLinesFactory => trackedLinesFactory.Create(It.IsAny>(), It.IsAny(), It.IsAny()), Times.Never());
+ }
+
+ [Test]
+ public void Should_Not_Throw_If_No_Initial_Coverage()
+ {
+ SimpleTextInfoSetUp();
+
+ new BufferLineCoverage(null, textInfo, new Mock().Object, null, null,new Mock().Object);
+ }
+
+ [Test]
+ public void GetLines_Should_Delegate_To_TrackedLines()
+ {
+ SimpleTextInfoSetUp();
+
+ var mockTrackedLines = new Mock();
+ var lines = new List();
+ mockTrackedLines.Setup(trackedLines => trackedLines.GetLines(2, 5)).Returns(lines);
+
+ autoMoqer.Setup(
+ trackedLinesFactory => trackedLinesFactory.Create(It.IsAny>(), It.IsAny(), It.IsAny()))
+ .Returns(mockTrackedLines.Object);
+
+ var bufferLineCoverage = autoMoqer.Create();
+
+ Assert.That(bufferLineCoverage.GetLines(2, 5), Is.SameAs(lines));
+ }
+
+ [Test]
+ public void Should_Listen_For_Coverage_Changed()
+ {
+ SimpleTextInfoSetUp();
+
+ var bufferLineCoverage = autoMoqer.Create();
+
+ autoMoqer.Verify(eventAggregator => eventAggregator.AddListener(bufferLineCoverage, null));
+ }
+
+ [Test]
+ public void Should_Have_Empty_Lines_When_Coverage_Cleared()
+ {
+ SimpleTextInfoSetUp();
+
+ autoMoqer.Setup(
+ trackedLinesFactory => trackedLinesFactory.Create(It.IsAny>(), It.IsAny(), It.IsAny()))
+ .Returns(new Mock().Object);
+
+ var bufferLineCoverage = autoMoqer.Create();
+
+ bufferLineCoverage.Handle(new NewCoverageLinesMessage());
+
+ var lines = bufferLineCoverage.GetLines(2, 5);
+ Assert.That(lines, Is.Empty);
+ }
+
+ [TestCase(true)]
+ [TestCase(false)]
+ public void Should_Create_New_TextLines_When_Coverage_Changed_And_Not_Off_In_AppOptions(bool off)
+ {
+ var autoMoqer = new AutoMoqer();
+ SetupEditorCoverageColouringMode(autoMoqer, off);
+ var mockTextBuffer = new Mock();
+ mockTextBuffer.Setup(textBuffer => textBuffer.ContentType.TypeName).Returns("CSharp");
+ var mockCurrentSnapshot = new Mock();
+ mockCurrentSnapshot.SetupGet(snapshot => snapshot.LineCount).Returns(10);
+ mockTextBuffer.SetupSequence(textBuffer => textBuffer.CurrentSnapshot)
+ .Returns(new Mock().Object)
+ .Returns(mockCurrentSnapshot.Object);
+ var mockTextDocument = new Mock();
+ mockTextDocument.SetupGet(textDocument => textDocument.FilePath).Returns("filepath");
+ var mockTextInfo = new Mock();
+ mockTextInfo.SetupGet(textInfo => textInfo.TextBuffer).Returns(mockTextBuffer.Object);
+ mockTextInfo.SetupGet(textInfo => textInfo.FilePath).Returns("filepath");
+ mockTextInfo.SetupGet(textInfo => textInfo.TextView).Returns(new Mock().Object);
+ autoMoqer.SetInstance(mockTextInfo.Object);
+
+ var lines = new List { CreateLine()};
+ var mockNewFileLineCoverage = autoMoqer.GetMock();
+ mockNewFileLineCoverage.Setup(fileLineCoverage => fileLineCoverage.GetLines("filepath")).Returns(lines);
+
+ var mockTrackedLines = new Mock();
+ var dynamicLines = new List();
+ mockTrackedLines.Setup(trackedLines => trackedLines.GetLines(2, 5)).Returns(dynamicLines);
+ autoMoqer.Setup(
+ trackedLinesFactory => trackedLinesFactory.Create(lines, mockCurrentSnapshot.Object, Language.CSharp)
+ ).Returns(mockTrackedLines.Object);
+
+
+ var bufferLineCoverage = autoMoqer.Create();
+
+ bufferLineCoverage.Handle(new NewCoverageLinesMessage { CoverageLines = mockNewFileLineCoverage.Object });
+ var bufferLines = bufferLineCoverage.GetLines(2, 5);
+ if (off)
+ {
+ Assert.That(bufferLines, Is.Empty);
+ }
+ else
+ {
+ Assert.That(bufferLines, Is.SameAs(dynamicLines));
+ }
+ }
+
+ [TestCase(true,true,true,true)]
+ [TestCase(true, false, true, true)]
+ [TestCase(false, true, true, true)]
+ [TestCase(true, false, false, true)]
+ [TestCase(false, false, false, false)]
+ public void Should_Send_CoverageChangedMessage_When_Necessary(
+ bool initialTrackedLines,
+ bool nextTrackedLines,
+ bool hasCoverageLines,
+ bool expectedSends)
+ {
+ SimpleTextInfoSetUp();
+ var trackedLines = new Mock().Object;
+ var mockTrackedLinesFactory = autoMoqer.GetMock();
+ mockTrackedLinesFactory.SetupSequence(trackedLinesFactory => trackedLinesFactory.Create(It.IsAny>(), It.IsAny(), It.IsAny()))
+ .Returns(initialTrackedLines ? trackedLines : null)
+ .Returns(nextTrackedLines ? trackedLines : null);
+ var bufferLineCoverage = autoMoqer.Create();
+
+ var newCoverageLinesMessage = new NewCoverageLinesMessage();
+ if(hasCoverageLines)
+ {
+ newCoverageLinesMessage.CoverageLines = new Mock().Object;
+ }
+ bufferLineCoverage.Handle(newCoverageLinesMessage);
+
+ autoMoqer.Verify(
+ eventAggregator => eventAggregator.SendMessage(
+ It.Is(message => message.AppliesTo == "filepath" && message.BufferLineCoverage == bufferLineCoverage)
+ , null
+ ), expectedSends ? Times.Once() : Times.Never());
+ }
+
+ [TestCase(true)]
+ [TestCase(false)]
+ public void Should_Update_TrackedLines_When_Text_Buffer_ChangedOnBackground(bool textLinesChanged)
+ {
+ SimpleTextInfoSetUp();
+
+ var afterSnapshot = new Mock().Object;
+
+ var newSpan = new Span(1, 2);
+ var mockTrackedLines = new Mock();
+ var changedLineNumbers = textLinesChanged ? new List { 1, 2 } : new List();
+ mockTrackedLines.Setup(trackedLines => trackedLines.GetChangedLineNumbers(afterSnapshot, new List { newSpan }))
+ .Returns(changedLineNumbers);
+ autoMoqer.Setup(trackedLinesFactory => trackedLinesFactory.Create(It.IsAny>(), It.IsAny(), It.IsAny()))
+ .Returns(mockTrackedLines.Object);
+
+
+ var bufferLineCoverage = autoMoqer.Create();
+
+ mockTextBuffer.Raise(textBuffer => textBuffer.ChangedOnBackground += null, CreateTextContentChangedEventArgs(afterSnapshot, newSpan));
+
+ autoMoqer.Verify(
+ eventAggregator => eventAggregator.SendMessage(
+ It.Is(message => message.AppliesTo == "filepath" && message.BufferLineCoverage == bufferLineCoverage && message.ChangedLineNumbers == changedLineNumbers)
+ , null
+ ), Times.Exactly(textLinesChanged ? 1 : 0));
+
+ }
+
+ [Test]
+ public void Should_Not_Throw_When_Text_Buffer_Changed_And_No_Coverage()
+ {
+ SimpleTextInfoSetUp();
+
+ autoMoqer.Setup(
+ trackedLinesFactory => trackedLinesFactory.Create(It.IsAny>(), It.IsAny(), It.IsAny()))
+ .Returns(new Mock().Object);
+
+ var bufferLineCoverage = autoMoqer.Create();
+
+ // clear coverage
+ bufferLineCoverage.Handle(new NewCoverageLinesMessage());
+
+ mockTextBuffer.Raise(textBuffer => textBuffer.Changed += null, CreateTextContentChangedEventArgs(new Mock().Object, new Span(0, 0)));
+ }
+
+ private TextContentChangedEventArgs CreateTextContentChangedEventArgs(ITextSnapshot afterSnapshot, params Span[] newSpans)
+ {
+ var normalizedTextChangeCollection = new NormalizedTextChangeCollection();
+ foreach (var newSpan in newSpans)
+ {
+ var mockTextChange = new Mock();
+ mockTextChange.SetupGet(textChange => textChange.NewSpan).Returns(newSpan);
+ normalizedTextChangeCollection.Add(mockTextChange.Object);
+ };
+
+ var mockBeforeSnapshot = new Mock();
+ mockBeforeSnapshot.Setup(snapshot => snapshot.Version.Changes).Returns(normalizedTextChangeCollection);
+ return new TextContentChangedEventArgs(mockBeforeSnapshot.Object, afterSnapshot, EditOptions.None, null);
+ }
+
+ [Test]
+ public void Should_Stop_Listening_When_TextView_Closed()
+ {
+ SimpleTextInfoSetUp();
+
+ var bufferLineCoverage = autoMoqer.Create();
+
+ mockTextView.Raise(textView => textView.Closed += null, EventArgs.Empty);
+
+ autoMoqer.Verify(eventAggregator => eventAggregator.RemoveListener(bufferLineCoverage));
+ mockTextView.VerifyRemove(textView => textView.Closed -= It.IsAny(), Times.Once);
+ mockTextBuffer.VerifyRemove(textBuffer => textBuffer.Changed -= It.IsAny>(), Times.Once);
+ var mockAppOptionsProvider = autoMoqer.GetMock();
+ mockAppOptionsProvider.VerifyRemove(appOptionsProvider => appOptionsProvider.OptionsChanged -= It.IsAny>(), Times.Once);
+ }
+
+ [Test]
+ public void Should_SaveSerializedCoverage_When_TextView_Closed_And_There_Has_Been_Coverage()
+ {
+ var autoMoqer = new AutoMoqer();
+ SetupEditorCoverageColouringMode(autoMoqer);
+ var mockTextInfo = autoMoqer.GetMock();
+ mockTextInfo.SetupGet(textInfo => textInfo.FilePath).Returns("filepath");
+ mockTextInfo.SetupGet(textInfo => textInfo.TextBuffer.ContentType.TypeName).Returns("contenttypename");
+ mockTextInfo.SetupGet(textInfo => textInfo.TextBuffer.CurrentSnapshot).Returns(new Mock().Object);
+ var mockTextView = new Mock();
+ mockTextInfo.SetupGet(textInfo => textInfo.TextView).Returns(mockTextView.Object);
+ autoMoqer.Setup>(
+ fileLineCoverage => fileLineCoverage.GetLines(It.IsAny(), It.IsAny(), It.IsAny())
+ ).Returns(new List { });
+ var trackedLines = new Mock().Object;
+ autoMoqer.Setup(
+ trackedLinesFactory => trackedLinesFactory.Create(It.IsAny>(), It.IsAny(), It.IsAny())
+ ).Returns(trackedLines);
+ autoMoqer.Setup(
+ trackedLinesFactory => trackedLinesFactory.Serialize(trackedLines)
+ ).Returns("serialized");
+
+ autoMoqer.Create();
+
+ mockTextView.Raise(textView => textView.Closed += null, EventArgs.Empty);
+
+ autoMoqer.Verify(dynamicCoverageStore => dynamicCoverageStore.SaveSerializedCoverage("filepath", "serialized"));
+ }
+
+ [Test]
+ public void Should_Remove_Serialized_Coverage_When_TextView_Closed_And_No_TrackedLines()
+ {
+ var autoMoqer = new AutoMoqer();
+ SetupEditorCoverageColouringMode(autoMoqer);
+ var mockTextInfo = autoMoqer.GetMock();
+ mockTextInfo.SetupGet(textInfo => textInfo.FilePath).Returns("filepath");
+ mockTextInfo.SetupGet(textInfo => textInfo.TextBuffer.ContentType.TypeName).Returns("contenttypename");
+ mockTextInfo.SetupGet(textInfo => textInfo.TextBuffer.CurrentSnapshot).Returns(new Mock().Object);
+ var mockTextView = new Mock();
+ mockTextInfo.SetupGet(textInfo => textInfo.TextView).Returns(mockTextView.Object);
+ autoMoqer.Setup>(
+ fileLineCoverage => fileLineCoverage.GetLines(It.IsAny(), It.IsAny(), It.IsAny())
+ ).Returns(new List { });
+ var trackedLines = new Mock().Object;
+ autoMoqer.Setup(
+ trackedLinesFactory => trackedLinesFactory.Create(It.IsAny>(), It.IsAny(), It.IsAny())
+ ).Returns(trackedLines);
+ autoMoqer.Setup(
+ trackedLinesFactory => trackedLinesFactory.Serialize(trackedLines)
+ ).Returns("serialized");
+
+ var bufferLineCoverage = autoMoqer.Create();
+ // clear coverage
+ bufferLineCoverage.Handle(new NewCoverageLinesMessage());
+
+ mockTextView.Raise(textView => textView.Closed += null, EventArgs.Empty);
+
+ autoMoqer.Verify(dynamicCoverageStore => dynamicCoverageStore.RemoveSerializedCoverage("filepath"));
+ }
+
+ [TestCase(true, "CSharp", Language.CSharp)]
+ [TestCase(true, "Basic", Language.VB)]
+ [TestCase(true, "C/C++", Language.CPP)]
+ [TestCase(false,"",Language.CPP)]
+ public void Should_Create_From_Serialized_Coverage_If_Present(bool hasSerialized,string contentTypeLanguage, Language expectedLanguage)
+ {
+ var autoMoqer = new AutoMoqer();
+ SetupEditorCoverageColouringMode(autoMoqer);
+ var mockTextInfo = autoMoqer.GetMock();
+ mockTextInfo.SetupGet(textInfo => textInfo.TextBuffer.ContentType.TypeName).Returns(contentTypeLanguage);
+ mockTextInfo.SetupGet(textInfo => textInfo.TextView).Returns(new Mock().Object);
+ var currentTextSnaphot = new Mock().Object;
+ mockTextInfo.SetupGet(textInfo => textInfo.TextBuffer.CurrentSnapshot).Returns(currentTextSnaphot);
+ mockTextInfo.SetupGet(textInfo => textInfo.FilePath).Returns("filepath");
+ autoMoqer.Setup(dynamicCoverageStore => dynamicCoverageStore.GetSerializedCoverage("filepath"))
+ .Returns(hasSerialized ? "serialized" : null);
+
+ var mockTrackedLinesNoSerialized = new Mock();
+ autoMoqer.Setup(
+ trackedLinesFactory => trackedLinesFactory.Create(It.IsAny>(), It.IsAny(), It.IsAny())
+ ).Returns(mockTrackedLinesNoSerialized.Object);
+
+ var mockTrackedLinesFromSerialized = new Mock();
+ autoMoqer.Setup(
+ trackedLinesFactory => trackedLinesFactory.Create("serialized", currentTextSnaphot, expectedLanguage)
+ ).Returns(mockTrackedLinesFromSerialized.Object);
+
+
+ var bufferLineCoverage = autoMoqer.Create();
+
+ bufferLineCoverage.GetLines(2, 5);
+
+ var expectedMockTrackedLines = hasSerialized ? mockTrackedLinesFromSerialized : mockTrackedLinesNoSerialized;
+ expectedMockTrackedLines.Verify(trackedLines => trackedLines.GetLines(2, 5), Times.Once);
+ }
+
+ [Test]
+ public void Should_Remove_TrackedLines_When_AppOptions_Changed_And_EditorCoverageColouringMode_Is_Off()
+ {
+ SimpleTextInfoSetUp();
+ var mockTrackedLines = new Mock();
+ mockTrackedLines.Setup(trackedLines => trackedLines.GetLines(It.IsAny(), It.IsAny()))
+ .Returns(new List { new Mock().Object });
+ autoMoqer.Setup(
+ trackedCoverageLinesFactory => trackedCoverageLinesFactory.Create(It.IsAny>(), It.IsAny(), It.IsAny())
+ ).Returns(mockTrackedLines.Object);
+
+ var bufferLineCoverage = autoMoqer.Create();
+ Assert.That(bufferLineCoverage.GetLines(2, 5).Count(), Is.EqualTo(1));
+
+ var mockAppOptions = new Mock();
+ mockAppOptions.SetupGet(appOptions => appOptions.EditorCoverageColouringMode).Returns(EditorCoverageColouringMode.Off);
+ autoMoqer.GetMock().Raise(appOptionsProvider => appOptionsProvider.OptionsChanged += null, mockAppOptions.Object);
+
+ autoMoqer.Verify(eventAggregator => eventAggregator.SendMessage(It.IsAny(), null));
+
+ Assert.That(bufferLineCoverage.GetLines(2, 5), Is.Empty);
+ }
+
+ [Test]
+ public void Should_Not_Remove_TrackedLines_When_AppOptions_Changed_And_EditorCoverageColouringMode_Is_Not_Off()
+ {
+ SimpleTextInfoSetUp();
+ var mockTrackedLines = new Mock();
+ mockTrackedLines.Setup(trackedLines => trackedLines.GetLines(It.IsAny(), It.IsAny()))
+ .Returns(new List { new Mock().Object });
+ autoMoqer.Setup(
+ trackedCoverageLinesFactory => trackedCoverageLinesFactory.Create(It.IsAny>(), It.IsAny(), It.IsAny())
+ ).Returns(mockTrackedLines.Object);
+
+ var bufferLineCoverage = autoMoqer.Create();
+ Assert.That(bufferLineCoverage.GetLines(2, 5).Count(), Is.EqualTo(1));
+
+ var mockAppOptions = new Mock();
+ mockAppOptions.SetupGet(appOptions => appOptions.EditorCoverageColouringMode).Returns(EditorCoverageColouringMode.DoNotUseRoslynWhenTextChanges);
+ autoMoqer.GetMock().Raise(appOptionsProvider => appOptionsProvider.OptionsChanged += null, mockAppOptions.Object);
+
+ autoMoqer.Verify(eventAggregator => eventAggregator.SendMessage(It.IsAny(), null), Times.Never());
+
+ Assert.That(bufferLineCoverage.GetLines(2, 5).Count(), Is.EqualTo(1));
+ }
+
+ }
+}
diff --git a/FineCodeCoverageTests/Editor/DynamicCoverage/CodeSpanRangeContainingCodeTrackerFactory_Tests.cs b/FineCodeCoverageTests/Editor/DynamicCoverage/CodeSpanRangeContainingCodeTrackerFactory_Tests.cs
new file mode 100644
index 00000000..b64360d4
--- /dev/null
+++ b/FineCodeCoverageTests/Editor/DynamicCoverage/CodeSpanRangeContainingCodeTrackerFactory_Tests.cs
@@ -0,0 +1,166 @@
+using AutoMoq;
+using FineCodeCoverage.Editor.DynamicCoverage;
+using FineCodeCoverage.Engine.Model;
+using Microsoft.VisualStudio.Text;
+using Moq;
+using NUnit.Framework;
+using System.Collections.Generic;
+
+namespace FineCodeCoverageTests.Editor.DynamicCoverage
+{
+ internal class CodeSpanRangeContainingCodeTrackerFactory_Tests
+ {
+ [TestCase(SpanTrackingMode.EdgePositive)]
+ [TestCase(SpanTrackingMode.EdgeInclusive)]
+ public void Should_CreateCoverageLines_From_TrackedCoverageLines_And_TrackingSpanRange(SpanTrackingMode spanTrackingMode)
+ {
+ var textSnapshot = new Mock().Object;
+ var mockLine = new Mock();
+ mockLine.SetupGet(line => line.Number).Returns(5);
+ var adjustedLine = 4;
+ var mockLine2 = new Mock();
+ mockLine2.SetupGet(line => line.Number).Returns(6);
+ var adjustedLine2 = 5;
+ var codeSpanRange = new CodeSpanRange(1, 10);
+
+ var autoMoqer = new AutoMoqer();
+ var trackingSpanStart = new Mock().Object;
+ var trackingSpanEnd = new Mock().Object;
+ var trackingSpanLine = new Mock().Object;
+ var trackingSpanLine2 = new Mock