Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support #484

Merged
merged 1 commit into from
Feb 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions FineCodeCoverage/FineCodeCoverage.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,9 @@
<PackageReference Include="Microsoft.VisualStudio.Composition.Analyzers">
<Version>16.9.20</Version>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.ProjectSystem">
<Version>15.8.243</Version>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.SDK" Version="16.0.206" ExcludeAssets="runtime">
<IncludeAssets>compile; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand Down
3 changes: 3 additions & 0 deletions FineCodeCoverage2022/FineCodeCoverage2022.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,9 @@
<PackageReference Include="Microsoft.VisualStudio.Composition.Analyzers">
<Version>17.10.37</Version>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.ProjectSystem">
<Version>17.9.380</Version>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.SDK" Version="17.10.40171" ExcludeAssets="runtime">
<IncludeAssets>compile; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand Down
152 changes: 152 additions & 0 deletions FineCodeCoverageTests/CoverageProject_Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
using FineCodeCoverage.Engine.Model;
using NUnit.Framework;
using System.IO;

namespace FineCodeCoverageTests
{
public class CoverageProject_Tests
{
private string tempProjectFilePath;
private CoverageProject coverageProject;

[SetUp]
public void SetUp()
{
coverageProject = new CoverageProject(null, null, null, null, null, false);
tempProjectFilePath = Path.Combine(Path.GetTempPath(), "testproject.csproj");
coverageProject.ProjectFile = tempProjectFilePath;
}

[Test]
public void Should_Be_An_Sdk_Project_When_Project_Element_Has_Sdk_Attribute()
{
Test(@"<Project Sdk=""My.Custom.Sdk/1.2.3""/>", true);
}

[Test]
public void Should_Be_An_Sdk_Project_When_Project_Element_Has_Child_Sdk_Element()
{
Test(@"<Project>
<Sdk Name=""My.Custom.Sdk"" Version=""1.2.3"" />
</Project>
", true);
}

[Test]
public void Should_be_An_Sdk_Project_When_Project_Element_Has_Child_Import_With_Sdk_Attribute()
{
Test(@"<Project>
<PropertyGroup>
<MyProperty>Value</MyProperty>
</PropertyGroup>
<Import Project=""Sdk.props"" Sdk=""My.Custom.Sdk"" />
</Project>
", true);
}

[Test]
public void Should_Not_Be_An_Sdk_Project_When_Is_Not()
{
Test(@"<Project ToolsVersion=""15.0"" DefaultTargets=""Build"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
<Import Project=""..\packages\Microsoft.CodeCoverage.17.12.0\build\netstandard2.0\Microsoft.CodeCoverage.props"" Condition=""Exists('..\packages\Microsoft.CodeCoverage.17.12.0\build\netstandard2.0\Microsoft.CodeCoverage.props')"" />
<Import Project=""..\packages\MSTest.TestAdapter.2.2.10\build\net46\MSTest.TestAdapter.props"" Condition=""Exists('..\packages\MSTest.TestAdapter.2.2.10\build\net46\MSTest.TestAdapter.props')"" />
<Import Project=""$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props"" Condition=""Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')"" />
<PropertyGroup>
<Configuration Condition="" '$(Configuration)' == '' "">Debug</Configuration>
<Platform Condition="" '$(Platform)' == '' "">AnyCPU</Platform>
<ProjectGuid>{F4B73E7F-F91D-4C95-A3CE-B8DA3A94BB90}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>NetFrameworkUnitTest</RootNamespace>
<AssemblyName>NetFrameworkUnitTest</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<VisualStudioVersion Condition=""'$(VisualStudioVersion)' == ''"">15.0</VisualStudioVersion>
<VSToolsPath Condition=""'$(VSToolsPath)' == ''"">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
<IsCodedUITest>False</IsCodedUITest>
<TestProjectType>UnitTest</TestProjectType>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<RunSettingsFilePath>
</RunSettingsFilePath>
</PropertyGroup>
<PropertyGroup Condition="" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include=""Microsoft.VisualStudio.CodeCoverage.Shim, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"">
<HintPath>..\packages\Microsoft.CodeCoverage.17.12.0\lib\net462\Microsoft.VisualStudio.CodeCoverage.Shim.dll</HintPath>
</Reference>
<Reference Include=""Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"">
<HintPath>..\packages\MSTest.TestFramework.2.2.10\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
</Reference>
<Reference Include=""Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"">
<HintPath>..\packages\MSTest.TestFramework.2.2.10\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll</HintPath>
</Reference>
<Reference Include=""System"" />
<Reference Include=""System.Core"" />
</ItemGroup>
<ItemGroup>
<Compile Include=""UnitTest1.cs"" />
<Compile Include=""Properties\AssemblyInfo.cs"" />
</ItemGroup>
<ItemGroup>
<None Include=""packages.config"" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include=""..\DemoOpenCover\DemoOpenCover.csproj"">
<Project>{9ef61906-87e7-42ac-b977-058fc55f74d8}</Project>
<Name>DemoOpenCover</Name>
</ProjectReference>
<ProjectReference Include=""..\Exclude\Exclude.csproj"">
<Project>{fa82235f-9590-410b-9840-daa224abb17e}</Project>
<Name>Exclude</Name>
</ProjectReference>
</ItemGroup>
<Import Project=""$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets"" Condition=""Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')"" />
<Import Project=""$(MSBuildToolsPath)\Microsoft.CSharp.targets"" />
<Target Name=""EnsureNuGetPackageBuildImports"" BeforeTargets=""PrepareForBuild"">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition=""!Exists('..\packages\MSTest.TestAdapter.2.2.10\build\net46\MSTest.TestAdapter.props')"" Text=""$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.2.2.10\build\net46\MSTest.TestAdapter.props'))"" />
<Error Condition=""!Exists('..\packages\MSTest.TestAdapter.2.2.10\build\net46\MSTest.TestAdapter.targets')"" Text=""$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.2.2.10\build\net46\MSTest.TestAdapter.targets'))"" />
<Error Condition=""!Exists('..\packages\Microsoft.CodeCoverage.17.12.0\build\netstandard2.0\Microsoft.CodeCoverage.props')"" Text=""$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.CodeCoverage.17.12.0\build\netstandard2.0\Microsoft.CodeCoverage.props'))"" />
<Error Condition=""!Exists('..\packages\Microsoft.CodeCoverage.17.12.0\build\netstandard2.0\Microsoft.CodeCoverage.targets')"" Text=""$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.CodeCoverage.17.12.0\build\netstandard2.0\Microsoft.CodeCoverage.targets'))"" />
</Target>
<Import Project=""..\packages\MSTest.TestAdapter.2.2.10\build\net46\MSTest.TestAdapter.targets"" Condition=""Exists('..\packages\MSTest.TestAdapter.2.2.10\build\net46\MSTest.TestAdapter.targets')"" />
<Import Project=""..\packages\Microsoft.CodeCoverage.17.12.0\build\netstandard2.0\Microsoft.CodeCoverage.targets"" Condition=""Exists('..\packages\Microsoft.CodeCoverage.17.12.0\build\netstandard2.0\Microsoft.CodeCoverage.targets')"" />
</Project>", false);
}

private void Test(string project, bool expectedIsSdkStyle)
{
var xmlDeclaration = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n";
File.WriteAllText(tempProjectFilePath, $"{xmlDeclaration}{project}");
Assert.That(coverageProject.IsDotNetSdkStyle(), Is.EqualTo(expectedIsSdkStyle));
}

[TearDown]
public void Delete_ProjectFile()
{
File.Delete(tempProjectFilePath);
}
}

}
1 change: 1 addition & 0 deletions FineCodeCoverageTests/FineCodeCoverageTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
<ItemGroup>
<Compile Include="CoberturaDeserializer_Tests.cs" />
<Compile Include="CoberturaUtil_Tests.cs" />
<Compile Include="CoverageProject_Tests.cs" />
<Compile Include="CoverageToolOutput_Tests\AppOptionsCoverageToolOutputFolderSolutionProvider_Tests.cs" />
<Compile Include="CoverageToolOutput_Tests\CoverageToolOutputFolderFromSolutionProvider_Tests.cs" />
<Compile Include="CoverageToolOutput_Tests\CoverageToolOutputManager_Tests.cs" />
Expand Down
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,15 @@ or download from [releases](https://github.com/FortuneN/FineCodeCoverage/release

## Prerequisites

For .Net - that the test adapters are nuget packages. For instance, the NUnit Test Adapter extension is not sufficient.
For .Net

FCC supports the new [Microsoft.Testing.Platform]( https://learn.microsoft.com/en-us/dotnet/core/testing/unit-testing-platform-intro).
FCC does not support the associated testing platform server mode for when using microsoft as a coverage provider.
You can disable this feature - "Options / Environment / Preview Features / Use testing platform server mode"
but it is not necessary as FCC adds a global msbuild property, DisableTestingPlatformServerCapability true, that removes
the project capability. ([see Microsoft.Testing.Platform.MSBuild.targets](https://github.com/microsoft/testfx/blob/d141931b99fad0617d8435ce321fca0c45c9eb94/src/Platform/Microsoft.Testing.Platform.MSBuild/buildMultiTargeting/Microsoft.Testing.Platform.MSBuild.targets#L10)).

When not using Microsoft.TestingPlatform you have added test adapters through nuget packages. For instance, the NUnit Test Adapter extension is not sufficient.

---

Expand Down
101 changes: 34 additions & 67 deletions SharedProject/Core/Model/CoverageProject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ internal class CoverageProject : ICoverageProject
private readonly string fccFolderName = "fine-code-coverage";
private readonly string buildOutputFolderName = "build-output";
private string buildOutputPath;
private bool? isDotNetSdkStyle;
private string BuildOutputPath
{
get
Expand Down Expand Up @@ -78,84 +79,50 @@ public CoverageProject(
public string FCCOutputFolder => Path.Combine(ProjectOutputFolder, fccFolderName);
public bool IsDotNetSdkStyle()
{
return ProjectFileXElement
if (isDotNetSdkStyle.HasValue)
{
return isDotNetSdkStyle.Value;
}

isDotNetSdkStyle = ProjectFileXElement
.DescendantsAndSelf()
.Where(x =>
{
//https://docs.microsoft.com/en-us/visualstudio/msbuild/how-to-use-project-sdk?view=vs-2019
return IsRootProjectElementWithSdkAttribute(x) ||
IsRootProjectElementSdkElementChild(x) ||
IsRootImportElementWithSdkAttribute(x);
})
.Any();

/*
<Project Sdk="My.Custom.Sdk">
...
</Project>
<Project Sdk="My.Custom.Sdk/1.2.3">
...
</Project>
*/
if
(
x?.Name?.LocalName?.Equals("Project", StringComparison.OrdinalIgnoreCase) == true &&
x?.Parent == null
)
{
var sdkAttr = x?.Attributes()?.FirstOrDefault(attr => attr?.Name?.LocalName?.Equals("Sdk", StringComparison.OrdinalIgnoreCase) == true);

if (sdkAttr?.Value?.Trim()?.StartsWith("Microsoft.NET.Sdk", StringComparison.OrdinalIgnoreCase) == true)
{
return true;
}
}
return isDotNetSdkStyle.Value;

/*
<Project>
<Sdk Name="My.Custom.Sdk" Version="1.2.3" />
...
</Project>
*/
if
(
x?.Name?.LocalName?.Equals("Sdk", StringComparison.OrdinalIgnoreCase) == true &&
x?.Parent?.Name?.LocalName?.Equals("Project", StringComparison.OrdinalIgnoreCase) == true &&
x?.Parent?.Parent == null
)
{
var nameAttr = x?.Attributes()?.FirstOrDefault(attr => attr?.Name?.LocalName?.Equals("Name", StringComparison.OrdinalIgnoreCase) == true);
bool HasSdkAttribute(XElement x)
{
return x?.Attributes()?.FirstOrDefault(attr => attr?.Name?.LocalName?.Equals("Sdk", StringComparison.OrdinalIgnoreCase) == true) != null;
}

if (nameAttr?.Value?.Trim()?.StartsWith("Microsoft.NET.Sdk", StringComparison.OrdinalIgnoreCase) == true)
{
return true;
}
}
bool IsRootProjectElementWithSdkAttribute(XElement x)
{
return x?.Name?.LocalName?.Equals("Project", StringComparison.OrdinalIgnoreCase) == true &&
x?.Parent == null && HasSdkAttribute(x);
}

/*
<Project>
<PropertyGroup>
<MyProperty>Value</MyProperty>
</PropertyGroup>
<Import Project="Sdk.props" Sdk="My.Custom.Sdk" />
...
<Import Project="Sdk.targets" Sdk="My.Custom.Sdk" />
</Project>
*/
if
(
x?.Name?.LocalName?.Equals("Import", StringComparison.OrdinalIgnoreCase) == true &&
bool IsRootProjectElementSdkElementChild(XElement x)
{
return x?.Name?.LocalName?.Equals("Sdk", StringComparison.OrdinalIgnoreCase) == true &&
x?.Parent?.Name?.LocalName?.Equals("Project", StringComparison.OrdinalIgnoreCase) == true &&
x?.Parent?.Parent == null
)
{
var sdkAttr = x?.Attributes()?.FirstOrDefault(attr => attr?.Name?.LocalName?.Equals("Sdk", StringComparison.OrdinalIgnoreCase) == true);

if (sdkAttr?.Value?.Trim()?.StartsWith("Microsoft.NET.Sdk", StringComparison.OrdinalIgnoreCase) == true)
{
return true;
}
}
x?.Parent?.Parent == null;
}

return false;
})
.Any();
bool IsRootImportElementWithSdkAttribute(XElement x)
{
return x?.Name?.LocalName?.Equals("Import", StringComparison.OrdinalIgnoreCase) == true &&
x?.Parent?.Name?.LocalName?.Equals("Project", StringComparison.OrdinalIgnoreCase) == true &&
x?.Parent?.Parent == null && HasSdkAttribute(x);
}
}

public string TestDllFile { get; set; }
public string ProjectOutputFolder => Path.GetDirectoryName(TestDllFile);
public string FailureDescription { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace FineCodeCoverage.Core.MsTestPlatform.CodeCoverage
{
interface IProjectSaver
{
void SaveProject(IVsHierarchy projectHierarchy);
System.Threading.Tasks.Task SaveProjectAsync(IVsHierarchy projectHierarchy);
}

[Export(typeof(IProjectSaver))]
Expand All @@ -26,9 +26,9 @@ IServiceProvider serviceProvider
this.serviceProvider = serviceProvider;
}

public void SaveProject(IVsHierarchy projectHierarchy)
public async System.Threading.Tasks.Task SaveProjectAsync(IVsHierarchy projectHierarchy)
{
ThreadHelper.ThrowIfNotOnUIThread();
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
var _solution = (IVsSolution)serviceProvider.GetService(typeof(SVsSolution));
Assumes.Present(_solution);
int hr = _solution.SaveSolutionElement((uint)__VSSLNSAVEOPTIONS.SLNSAVEOPT_SaveIfDirty, projectHierarchy, 0);
Expand Down
Loading
Loading