From 989532c41cb0f52cb28075ce5c013d00cacb4092 Mon Sep 17 00:00:00 2001 From: Tony Hallett Date: Sat, 1 Jul 2023 19:18:30 +0100 Subject: [PATCH 1/4] intercept user runsettings and disable ms code coverage when all projects associated with runsettings have been disabled --- .../RunSettingsTemplateReplacementsFactory.cs | 3 ++- .../CodeCoverage/UserRunSettingsService.cs | 22 +++++++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/SharedProject/Core/MsTestPlatform/CodeCoverage/RunSettingsTemplateReplacementsFactory.cs b/SharedProject/Core/MsTestPlatform/CodeCoverage/RunSettingsTemplateReplacementsFactory.cs index e9569a37..0f78d7bb 100644 --- a/SharedProject/Core/MsTestPlatform/CodeCoverage/RunSettingsTemplateReplacementsFactory.cs +++ b/SharedProject/Core/MsTestPlatform/CodeCoverage/RunSettingsTemplateReplacementsFactory.cs @@ -146,6 +146,7 @@ public IRunSettingsTemplateReplacements Create( var allProjectDetails = testContainers.Select(tc => userRunSettingsProjectDetailsLookup[tc.Source]).ToList(); var resultsDirectory = allProjectDetails[0].CoverageOutputFolder; var allSettings = allProjectDetails.Select(pd => pd.Settings); + var allProjectsDisabled = allSettings.All(s => !s.Enabled); var mergedSettings = new MergedIncludesExcludesOptions(allSettings); @@ -162,7 +163,7 @@ public IRunSettingsTemplateReplacements Create( var additionalModulePathsInclude = allProjectDetails.SelectMany(projectDetails => projectDetails.IncludedReferencedProjects.Select(rp => MsCodeCoverageRegex.RegexModuleName(rp))); var settings = new CombinedIncludesExcludesOptions(mergedSettings, additionalModulePathsInclude, additionalModulePathsExclude); - return new RunSettingsTemplateReplacements(settings, resultsDirectory, "true", testAdapter); + return new RunSettingsTemplateReplacements(settings, resultsDirectory, (!allProjectsDisabled).ToString(), testAdapter); } public IRunSettingsTemplateReplacements Create(ICoverageProject coverageProject, string testAdapter) diff --git a/SharedProject/Core/MsTestPlatform/CodeCoverage/UserRunSettingsService.cs b/SharedProject/Core/MsTestPlatform/CodeCoverage/UserRunSettingsService.cs index 334bc36a..26989308 100644 --- a/SharedProject/Core/MsTestPlatform/CodeCoverage/UserRunSettingsService.cs +++ b/SharedProject/Core/MsTestPlatform/CodeCoverage/UserRunSettingsService.cs @@ -152,6 +152,7 @@ private IXPathNavigable AddFCCRunSettingsActual(IXPathNavigable inputRunSettingD userRunSettingsProjectDetailsLookup, fccMsTestAdapterPath ); + EnsureTestAdaptersPathsAndReplace(navigator, replacements); EnsureCorrectMsDataCollectorAndReplace(clonedNavigator, replacements); return navigator; @@ -212,14 +213,31 @@ private void EnsureCorrectMsDataCollectorAndReplace(XPathNavigator xpathNavigato xpathNavigator.AppendChild(runSettingsTemplate.DataCollectionRunSettingsElement); } - if (addedMsDataCollector) + // todo - improve this + var disableMsDataCollector = replacements.Enabled.ToLower() == "false"; + if (addedMsDataCollector || disableMsDataCollector) { xpathNavigator.MoveToRoot(); var dataCollectorsNavigator = xpathNavigator.SelectSingleNode("/RunSettings/DataCollectionRunSettings/DataCollectors"); var msDataCollectorNavigator = MoveToMsDataCollectorFromDataCollectors(dataCollectorsNavigator); - ReplaceExcludesIncludes(msDataCollectorNavigator, replacements); + + if (disableMsDataCollector) + { + DisableMsDataCollector(msDataCollectorNavigator); + } + else + { + ReplaceExcludesIncludes(msDataCollectorNavigator, replacements); // no need to replace if we are disabling + } } + } + + private void DisableMsDataCollector(XPathNavigator msDataCollectorNavigator) + { + var element = XElement.Parse(msDataCollectorNavigator.OuterXml); + element.SetAttributeValue("enabled", "false"); + msDataCollectorNavigator.OuterXml = element.ToString(); } private XPathNavigator MoveToMsDataCollectorFromDataCollectors(XPathNavigator navigator) From a28b2445801939c2e1d3f500d3235404ea698a65 Mon Sep 17 00:00:00 2001 From: Tony Hallett Date: Sun, 2 Jul 2023 15:02:12 +0100 Subject: [PATCH 2/4] reset IsCollecting - AddRunSettings calls are duplicated - one before TestExecutionStarting and one after. TestExecutionStarting sets up userRunSettingsProjectDetailsLookup. The logic could probably all be done from AddRunSettings and inputRunSettingDocument.CreateNavigator().BaseURI --- .../CodeCoverage/MsCodeCoverageRunSettingsService.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SharedProject/Core/MsTestPlatform/CodeCoverage/MsCodeCoverageRunSettingsService.cs b/SharedProject/Core/MsTestPlatform/CodeCoverage/MsCodeCoverageRunSettingsService.cs index 55a3b799..3ff25034 100644 --- a/SharedProject/Core/MsTestPlatform/CodeCoverage/MsCodeCoverageRunSettingsService.cs +++ b/SharedProject/Core/MsTestPlatform/CodeCoverage/MsCodeCoverageRunSettingsService.cs @@ -178,7 +178,6 @@ private void ReportEndOfCoverageRunIfError() private Task InitializeIsCollectingAsync(ITestOperation testOperation) { - collectionStatus = MsCodeCoverageCollectionStatus.NotCollecting; runMsCodeCoverage = appOptionsProvider.Get().RunMsCodeCoverage; useMsCodeCoverage = runMsCodeCoverage == RunMsCodeCoverage.Yes; userRunSettingsProjectDetailsLookup = null; @@ -407,6 +406,7 @@ private async Task CleanUpAsync(ITestOperation testOperation) { coverageProjectsByType = await CoverageProjectsByType.CreateAsync(testOperation); await templatedRunSettingsService.CleanUpAsync(coverageProjectsByType.RunSettings); + collectionStatus = MsCodeCoverageCollectionStatus.NotCollecting; } } @@ -415,7 +415,7 @@ public static bool IsTestExecution(this IRunSettingsConfigurationInfo configurat { return configurationInfo.RequestState == RunSettingConfigurationInfoState.Execution; } - + } internal static class UserRunSettingsAnalysisResultExtensions From 21f0c5e13b0e50b4a7a905602e35089e7e4f8353 Mon Sep 17 00:00:00 2001 From: Tony Hallett Date: Sun, 2 Jul 2023 16:50:37 +0100 Subject: [PATCH 3/4] toLower enabled --- .../CodeCoverage/RunSettingsTemplateReplacementsFactory.cs | 2 +- .../Core/MsTestPlatform/CodeCoverage/UserRunSettingsService.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SharedProject/Core/MsTestPlatform/CodeCoverage/RunSettingsTemplateReplacementsFactory.cs b/SharedProject/Core/MsTestPlatform/CodeCoverage/RunSettingsTemplateReplacementsFactory.cs index 0f78d7bb..e4b5579e 100644 --- a/SharedProject/Core/MsTestPlatform/CodeCoverage/RunSettingsTemplateReplacementsFactory.cs +++ b/SharedProject/Core/MsTestPlatform/CodeCoverage/RunSettingsTemplateReplacementsFactory.cs @@ -163,7 +163,7 @@ public IRunSettingsTemplateReplacements Create( var additionalModulePathsInclude = allProjectDetails.SelectMany(projectDetails => projectDetails.IncludedReferencedProjects.Select(rp => MsCodeCoverageRegex.RegexModuleName(rp))); var settings = new CombinedIncludesExcludesOptions(mergedSettings, additionalModulePathsInclude, additionalModulePathsExclude); - return new RunSettingsTemplateReplacements(settings, resultsDirectory, (!allProjectsDisabled).ToString(), testAdapter); + return new RunSettingsTemplateReplacements(settings, resultsDirectory, (!allProjectsDisabled).ToString().ToLower(), testAdapter); } public IRunSettingsTemplateReplacements Create(ICoverageProject coverageProject, string testAdapter) diff --git a/SharedProject/Core/MsTestPlatform/CodeCoverage/UserRunSettingsService.cs b/SharedProject/Core/MsTestPlatform/CodeCoverage/UserRunSettingsService.cs index 26989308..d77cb701 100644 --- a/SharedProject/Core/MsTestPlatform/CodeCoverage/UserRunSettingsService.cs +++ b/SharedProject/Core/MsTestPlatform/CodeCoverage/UserRunSettingsService.cs @@ -214,7 +214,7 @@ private void EnsureCorrectMsDataCollectorAndReplace(XPathNavigator xpathNavigato } // todo - improve this - var disableMsDataCollector = replacements.Enabled.ToLower() == "false"; + var disableMsDataCollector = replacements.Enabled == "false"; if (addedMsDataCollector || disableMsDataCollector) { xpathNavigator.MoveToRoot(); From 625266204e789e91304a0c645598799997d101cd Mon Sep 17 00:00:00 2001 From: Tony Hallett Date: Sun, 2 Jul 2023 16:50:53 +0100 Subject: [PATCH 4/4] update tests --- ...overageRunSettingsService_Collect_Tests.cs | 36 ++++++++++++- ...ttingsTemplateReplacementsFactory_Tests.cs | 42 +++++++++++++++ ...RunSettingsService_AddFCCSettings_Tests.cs | 51 ++++++++++++++++--- 3 files changed, 122 insertions(+), 7 deletions(-) diff --git a/FineCodeCoverageTests/MsCodeCoverage/MsCodeCoverageRunSettingsService_Collect_Tests.cs b/FineCodeCoverageTests/MsCodeCoverage/MsCodeCoverageRunSettingsService_Collect_Tests.cs index c575f823..2b013212 100644 --- a/FineCodeCoverageTests/MsCodeCoverage/MsCodeCoverageRunSettingsService_Collect_Tests.cs +++ b/FineCodeCoverageTests/MsCodeCoverage/MsCodeCoverageRunSettingsService_Collect_Tests.cs @@ -18,8 +18,24 @@ namespace FineCodeCoverageTests.MsCodeCoverage { + internal class MsCodeCoverageRunSettingsService_Test_Execution_Not_Finished_Tests { + [Test] + public void Should_Set_To_Not_Collecting() + { + var autoMocker = new AutoMoqer(); + var msCodeCoverageRunSettingsService = autoMocker.Create(); + + msCodeCoverageRunSettingsService.collectionStatus = MsCodeCoverageCollectionStatus.Collecting; + + var mockTestOperation = new Mock(); + mockTestOperation.Setup(testOperation => testOperation.GetCoverageProjectsAsync()).ReturnsAsync(new List()); + msCodeCoverageRunSettingsService.TestExecutionNotFinishedAsync(mockTestOperation.Object); + + Assert.That(msCodeCoverageRunSettingsService.collectionStatus, Is.EqualTo(MsCodeCoverageCollectionStatus.NotCollecting)); + } + [Test] public async Task Should_Clean_Up_RunSettings_Coverage_Projects() { @@ -68,6 +84,23 @@ internal class MsCodeCoverageRunSettingsService_Collect_Tests { private AutoMoqer autoMocker; private ICoverageProject runSettingsCoverageProject; + private MsCodeCoverageRunSettingsService msCodeCoverageRunSettingsService; + + [Test] + public async Task Should_Set_To_Not_Collecting() + { + var resultsUris = new List() + { + new Uri(@"C:\SomePath\result1.cobertura.xml", UriKind.Absolute), + new Uri(@"C:\SomePath\result2.cobertura.xml", UriKind.Absolute), + new Uri(@"C:\SomePath\result3.xml", UriKind.Absolute), + }; + + var expectedCoberturaFiles = new string[] { @"C:\SomePath\result1.cobertura.xml", @"C:\SomePath\result2.cobertura.xml" }; + await RunAndProcessReportAsync(resultsUris, expectedCoberturaFiles); + + Assert.That(msCodeCoverageRunSettingsService.collectionStatus, Is.EqualTo(MsCodeCoverageCollectionStatus.NotCollecting)); + } [Test] public async Task Should_FCCEngine_RunAndProcessReport_With_CoberturaResults() @@ -119,7 +152,8 @@ private async Task RunAndProcessReportAsync(IEnumerable resultsUris,string[ It.IsAny() )).Returns("ZipDestination"); - var msCodeCoverageRunSettingsService = autoMocker.Create(); + msCodeCoverageRunSettingsService = autoMocker.Create(); + msCodeCoverageRunSettingsService.collectionStatus = MsCodeCoverageCollectionStatus.Collecting; msCodeCoverageRunSettingsService.threadHelper = new TestThreadHelper(); var mockFccEngine = new Mock(); diff --git a/FineCodeCoverageTests/MsCodeCoverage/RunSettingsTemplateReplacementsFactory_Tests.cs b/FineCodeCoverageTests/MsCodeCoverage/RunSettingsTemplateReplacementsFactory_Tests.cs index 33dfb741..bedea084 100644 --- a/FineCodeCoverageTests/MsCodeCoverage/RunSettingsTemplateReplacementsFactory_Tests.cs +++ b/FineCodeCoverageTests/MsCodeCoverage/RunSettingsTemplateReplacementsFactory_Tests.cs @@ -362,6 +362,48 @@ public void Should_Be_Empty_String_Replacement_When_Null() ReplacementsAssertions.AssertAllEmpty(replacements); } + [TestCase(true,true,"true")] + [TestCase(false, true, "true")] + [TestCase(true, false, "true")] + [TestCase(false, false, "false")] + public void Should_Be_Disabled_When_All_Projects_Are_Disabled(bool project1Enabled, bool project2Enabled, string expectedEnabled) + { + var testContainer1 = CreateTestContainer("Source1"); + var testContainer2 = CreateTestContainer("Source2"); + var testContainers = new List() + { + testContainer1, + testContainer2 + }; + Dictionary userRunSettingsProjectDetailsLookup = new Dictionary + { + { + "Source1", + new TestUserRunSettingsProjectDetails + { + CoverageOutputFolder = "", + Settings = new TestMsCodeCoverageOptions{ Enabled = project1Enabled, IncludeTestAssembly = true}, + ExcludedReferencedProjects = new List(), + IncludedReferencedProjects = new List(), + } + }, + { + "Source2", + new TestUserRunSettingsProjectDetails + { + CoverageOutputFolder = "", + Settings = new TestMsCodeCoverageOptions{ Enabled = project2Enabled, IncludeTestAssembly = true}, + ExcludedReferencedProjects = new List(), + IncludedReferencedProjects = new List(), + } + } + }; + + var runSettingsTemplateReplacements = runSettingsTemplateReplacementsFactory.Create(testContainers, userRunSettingsProjectDetailsLookup, ""); + + Assert.That(runSettingsTemplateReplacements.Enabled, Is.EqualTo(expectedEnabled)); + } + private string ModulePathElement(string value) { return $"{value}"; diff --git a/FineCodeCoverageTests/MsCodeCoverage/UserRunSettingsService_AddFCCSettings_Tests.cs b/FineCodeCoverageTests/MsCodeCoverage/UserRunSettingsService_AddFCCSettings_Tests.cs index 3f7ee317..9c24d5ac 100644 --- a/FineCodeCoverageTests/MsCodeCoverage/UserRunSettingsService_AddFCCSettings_Tests.cs +++ b/FineCodeCoverageTests/MsCodeCoverage/UserRunSettingsService_AddFCCSettings_Tests.cs @@ -112,7 +112,7 @@ public void Should_Create_Replacements() projectDetailsLookup, "fccMsTestAdapterPath" ) - ).Returns(new RunSettingsTemplateReplacements()); + ).Returns(new RunSettingsTemplateReplacements() { Enabled = "true"}); userRunSettingsService.AddFCCRunSettings( xPathNavigable, @@ -144,7 +144,8 @@ public void Should_Add_Replaced_RunConfiguration_If_Not_Present() TestAddFCCSettings(runSettings, expectedRunSettings, new RunSettingsTemplateReplacements { ResultsDirectory = resultsDirectory, - TestAdapter = testAdapter + TestAdapter = testAdapter, + Enabled = "true" }); } @@ -167,7 +168,8 @@ public void Should_Add_Replaced_TestAdaptersPath_If_Not_Present() "; TestAddFCCSettings(runSettings, expectedRunSettings, new RunSettingsTemplateReplacements { - TestAdapter = "MsTestAdapter" + TestAdapter = "MsTestAdapter", + Enabled = "true" }); } @@ -192,7 +194,8 @@ public void Should_Replace_TestAdaptersPath_If_Present() "; TestAddFCCSettings(runSettings, expectedRunSettings, new RunSettingsTemplateReplacements { - TestAdapter = "MsTestAdapter" + TestAdapter = "MsTestAdapter", + Enabled = "true" }); } @@ -469,7 +472,7 @@ public void Should_Add_Missing_Configuration_Format_Cobertura_To_Existing_Ms_Dat "; - TestAddFCCSettings(runSettings, expectedRunSettings, new RunSettingsTemplateReplacements()); + TestAddFCCSettings(runSettings, expectedRunSettings, new RunSettingsTemplateReplacements() { Enabled = "true"}); } [Test] @@ -505,7 +508,7 @@ public void Should_Change_Format_To_Cobertura_For_Existing_Ms_Data_Collector() "; - TestAddFCCSettings(runSettings, expectedRunSettings, new RunSettingsTemplateReplacements()); + TestAddFCCSettings(runSettings, expectedRunSettings, new RunSettingsTemplateReplacements() { Enabled = "true"}); } [Test] @@ -559,6 +562,42 @@ public void Should_Add_Replaced_RunConfiguration_And_Add_Replaceable_DataCollect TestAddFCCSettings("", expectedRunSettings, new RunSettingsTemplateReplacements { Enabled = "true"}); } + [Test] + public void Should_Disable_Ms_Data_Collection_When_Not_Enabled() + { + var runSettings = $@" + + {unchangedRunConfiguration} + + + + + Xml + + + + + + "; + + var expectedRunSettings = $@" + + {unchangedRunConfiguration} + + + + + Cobertura + + + + + + "; + + TestAddFCCSettings(runSettings, expectedRunSettings, new RunSettingsTemplateReplacements() { Enabled = "false" }); + } + private void TestAddFCCSettings(string runSettings, string expectedFccRunSettings, IRunSettingsTemplateReplacements runSettingsTemplateReplacements) { var actualRunSettings = AddFCCSettings(runSettings, runSettingsTemplateReplacements);