Skip to content

working tunit #501

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

Merged
merged 1 commit into from
Mar 29, 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
19 changes: 19 additions & 0 deletions FineCodeCoverage/FineCodeCoverage.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@
<Link>ZippedTools\coverlet.console.6.0.4.zip</Link>
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="..\Shared Files\ZippedTools\dotnet-coverage.17.14.2.zip">
<Link>ZippedTools\dotnet-coverage.17.14.2.zip</Link>
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<!--
<None Include="Key.snk" />
-->
Expand Down Expand Up @@ -165,6 +169,9 @@
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.MSBuild">
<Version>3.11.0</Version>
</PackageReference>
<PackageReference Include="Microsoft.ServiceHub.Framework">
<Version>3.1.4097</Version>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Composition.Analyzers">
<Version>16.9.20</Version>
</PackageReference>
Expand All @@ -179,6 +186,9 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Utilities">
<Version>16.10.31321.278</Version>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.VCProjectEngine">
<Version>16.10.31320.204</Version>
</PackageReference>
Expand All @@ -189,6 +199,12 @@
<PackageReference Include="Newtonsoft.Json">
<Version>13.0.3</Version>
</PackageReference>
<PackageReference Include="NuGet.VisualStudio">
<Version>5.11.6</Version>
</PackageReference>
<PackageReference Include="NuGet.VisualStudio.Contracts">
<Version>5.11.6</Version>
</PackageReference>
<PackageReference Include="NUnit">
<Version>3.13.1</Version>
</PackageReference>
Expand All @@ -201,6 +217,9 @@
<PackageReference Include="Svg">
<Version>3.3.0</Version>
</PackageReference>
<PackageReference Include="System.CommandLine">
<Version>2.0.0-beta4.22272.1</Version>
</PackageReference>
<PackageReference Include="System.Composition">
<Version>7.0.0</Version>
</PackageReference>
Expand Down
13 changes: 13 additions & 0 deletions FineCodeCoverage2022/FineCodeCoverage2022.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@
<Link>ZippedTools\coverlet.console.6.0.4.zip</Link>
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="..\Shared Files\ZippedTools\dotnet-coverage.17.14.2.zip">
<Link>ZippedTools\dotnet-coverage.17.14.2.zip</Link>
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<None Include="source.extension.vsixmanifest">
<SubType>Designer</SubType>
<Generator>VsixManifestGenerator</Generator>
Expand Down Expand Up @@ -188,6 +192,12 @@
<PackageReference Include="Newtonsoft.Json">
<Version>13.0.3</Version>
</PackageReference>
<PackageReference Include="NuGet.VisualStudio">
<Version>17.13.2</Version>
</PackageReference>
<PackageReference Include="NuGet.VisualStudio.Contracts">
<Version>17.13.2</Version>
</PackageReference>
<PackageReference Include="ReflectObject">
<Version>1.0.0</Version>
</PackageReference>
Expand All @@ -200,6 +210,9 @@
<PackageReference Include="Svg">
<Version>3.3.0</Version>
</PackageReference>
<PackageReference Include="System.CommandLine">
<Version>2.0.0-beta4.22272.1</Version>
</PackageReference>
<PackageReference Include="System.Composition">
<Version>8.0.0</Version>
</PackageReference>
Expand Down
3 changes: 3 additions & 0 deletions FineCodeCoverageTests/TestContainerDiscovery_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using FineCodeCoverage.Engine.Model;
using FineCodeCoverage.Engine.MsTestPlatform.CodeCoverage;
using FineCodeCoverage.Impl;
using FineCodeCoverage.Impl.TestContainerDiscovery;
using FineCodeCoverage.Options;
using Microsoft.VisualStudio.TestWindow.Extensibility;
using Moq;
Expand Down Expand Up @@ -120,6 +121,8 @@ private void SetUpOptions(Action<Mock<IAppOptions>> setupAppOptions)
public void SetUp()
{
mocker = new AutoMoqer();
var mockCoverageCollectableFromTestExplorer = mocker.GetMock<ICoverageCollectableFromTestExplorer>();
mockCoverageCollectableFromTestExplorer.Setup(coverageCollectableFromTestExplorer => coverageCollectableFromTestExplorer.IsCollectableAsync()).ReturnsAsync(true);
testContainerDiscoverer = mocker.Create<TestContainerDiscoverer>();
testContainerDiscoverer.RunAsync = (taskProvider) =>
{
Expand Down
17 changes: 13 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,17 @@ or download from [releases](https://github.com/FortuneN/FineCodeCoverage/release
For .Net

FCC supports the new [Microsoft.Testing.Platform](https://learn.microsoft.com/en-us/dotnet/core/testing/unit-testing-platform-intro) for MsTest, NUnit and xUnit.
Support for TUnit will be available shortly but will require running tests differently.

Unfortunately the workaround FCC uses for MSTest, NUnit and xUnit does not apply to TUnit.
TUnit has its own dedicated button on the FCC tool window toolbar and cannot be driven from the test explorer window.
As the test explorer window is not used FCC cannot intercept your runsettings ( see later).
Microsoft.Testing.Platform has the [Microsoft code coverage extension](https://learn.microsoft.com/en-us/dotnet/core/testing/microsoft-testing-platform-extensions-code-coverage#microsoft-code-coverage). If you add the package it will be used, otherwise FCC will run dotnet-coverage.
The Microsoft code coverage extension accepts runsettings or [configuration](https://learn.microsoft.com/en-us/dotnet/core/additional-tools/dotnet-coverage#settings) and dotnet-coverage only accepts configuration.
FCC will supply the necessary settings using FCC's settings system ( below ) but if you want to supply your own, FCC will read the test project file.
If either the FCCTestingPlatformCommandLineArguments or TestingPlatformCommandLineArguments property is present FCC will use these [arguments](https://learn.microsoft.com/en-us/dotnet/core/testing/microsoft-testing-platform-intro?tabs=dotnetcli#options) except ones pertaining to coverage other than --coverage-settings ( or --settings) as long as the
path specified exists.

Note that TUnit blocks coverage of your tests in the GlobalSetup.cs file if using the project template.

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

Expand All @@ -23,16 +33,15 @@ When not using Microsoft.Testing.Platform you have added test adapters through n
## Introduction

Fine Code Coverage provides code coverage using one of 3 different coverage tools. In previous releases there were two coverage tools being utilised, OpenCover and Coverlet that will be referred to as 'old coverage'.
Microsoft now provides a free coverage solution that you can choose to use by setting the Visual Studio Fine Code Coverage enumeration option RunMsCodeCoverage. This will probably be the preferred coverage
tool for most developers.
Microsoft now provides a free coverage solution that you can choose to use by setting the Visual Studio Fine Code Coverage enumeration option RunMsCodeCoverage. This will probably be the preferred coverage tool for most developers. This is not necessary for TUnit.

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.
Thus you will find that there are separate configuration options for Ms coverage vs old coverage and options that are common to the two.
Assembly level exclusions and inclusions can be achieved - see ExcludeAssemblies and IncludeAssemblies.
Configuration is ( mostly ) determined from Visual Studio options, finecodecoverage-settings.xml files and project msbuild properties. All of these settings are optional.
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.

Regardless of the coverage tool employed the process begins with FCC reacting to the test explorer in visual studio. One of the 3 coverage tools provides the coverage results and the results can be opened from buttons on the Fine Code Coverage Tool Window.
Aside from TUnit projects, the process begins with FCC reacting to the test explorer in visual studio. One of the 3 coverage tools provides the coverage results and the results can be opened from buttons on the Fine Code Coverage Tool Window.
This coverage is not dynamic and represents the coverage obtained from the last time you executed tests. When the coverage becomes outdated, you can click the 'FCC Clear UI' button in Tools or run coverage again.

Details of how FCC is progressing with code coverage can be found in the Coverage Log tab in the Fine Code Coverage Tool Window with more detailed logs in the FCC Output Window Pane. If you experience issues then providing the logs from the output window will help to understand the nature of the problem.
Expand Down
10 changes: 7 additions & 3 deletions Shared Files/OutputToolWindowPackage.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
// ------------------------------------------------------------------------------
// <auto-generated>
// This file was generated by VSIX Synchronizer
// This file was generated by VSIX Synchronizer 1.0.44
// Available from https://marketplace.visualstudio.com/items?itemName=MadsKristensen.VsixSynchronizer64
// </auto-generated>
// ------------------------------------------------------------------------------
namespace FineCodeCoverage
{
using System;

/// <summary>
/// Helper class that exposes all GUIDs used across VS Package.
/// </summary>
Expand All @@ -24,6 +25,7 @@ internal sealed partial class PackageGuids
public const string guidClearUICommandImageString = "8252a6d7-bcf3-4518-ae22-ad20ef8d4b63";
public static Guid guidClearUICommandImage = new Guid(guidClearUICommandImageString);
}

/// <summary>
/// Helper class that encapsulates all CommandIDs uses across VS Package.
/// </summary>
Expand All @@ -37,7 +39,9 @@ internal sealed partial class PackageIds
public const int cmdidOpenCoberturaCommand = 0x0101;
public const int cmdidOpenHotspotsCommand = 0x0102;
public const int cmdidToggleCoverageIndicatorsCommand = 0x0103;
public const int cmdidCollectTUnitCommand = 0x010C;
public const int cmdidCancelCollectTUnitCommand = 0x010D;
public const int outputToolWindowCommandImageIndex = 0x0001;
public const int clearUICommandImageIndex = 0x0001;
}
}
}
26 changes: 26 additions & 0 deletions Shared Files/OutputToolWindowPackage.vsct
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,30 @@
<LocCanonicalName>FCC.OpenHotspots</LocCanonicalName>
</Strings>
</Button>
<Button guid="guidOutputToolWindowPackageCmdSet" id="cmdidCollectTUnitCommand" priority="0x0100" type="Button">
<Parent guid="guidOutputToolWindowPackageCmdSet" id="ToolWindowToolbarGroup" />
<Icon guid="ImageCatalogGuid" id="RunTest" />
<CommandFlag>IconIsMoniker</CommandFlag>
<CommandFlag>DynamicVisibility</CommandFlag>
<Strings>
<ButtonText>Collect TUnit</ButtonText>
<CommandName>Collect TUnit</CommandName>
<CanonicalName>FCC.CollectTUnit</CanonicalName>
<LocCanonicalName>FCC.CollectTUnit</LocCanonicalName>
</Strings>
</Button>
<Button guid="guidOutputToolWindowPackageCmdSet" id="cmdidCancelCollectTUnitCommand" priority="0x0100" type="Button">
<Parent guid="guidOutputToolWindowPackageCmdSet" id="ToolWindowToolbarGroup" />
<Icon guid="ImageCatalogGuid" id="CancelTest" />
<CommandFlag>IconIsMoniker</CommandFlag>
<CommandFlag>DynamicVisibility</CommandFlag>
<Strings>
<ButtonText>Cancel Collect TUnit</ButtonText>
<CommandName>Cancel Collect TUnit</CommandName>
<CanonicalName>FCC.CancelCollectTUnit</CanonicalName>
<LocCanonicalName>FCC.CancelCollectTUnit</LocCanonicalName>
</Strings>
</Button>
</Buttons>

<Menus>
Expand Down Expand Up @@ -134,6 +158,8 @@
<IDSymbol value="257" name="cmdidOpenCoberturaCommand" />
<IDSymbol value="258" name="cmdidOpenHotspotsCommand" />
<IDSymbol value="259" name="cmdidToggleCoverageIndicatorsCommand" />
<IDSymbol value="268" name="cmdidCollectTUnitCommand" />
<IDSymbol value="269" name="cmdidCancelCollectTUnitCommand" />
</GuidSymbol>

<!-- images -->
Expand Down
Binary file not shown.
7 changes: 6 additions & 1 deletion SharedProject/Core/FCCEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.ComponentModel.Composition;
using System.Linq;
using System.Threading;
using FineCodeCoverage.Core.MsTestPlatform.TestingPlatform;
using FineCodeCoverage.Core.Utilities;
using FineCodeCoverage.Engine.Cobertura;
using FineCodeCoverage.Engine.Model;
Expand Down Expand Up @@ -67,6 +68,7 @@ internal class FCCEngine : IFCCEngine,IDisposable
#pragma warning restore IDE0052 // Remove unread private members
private readonly IEventAggregator eventAggregator;
private readonly IDisposeAwareTaskRunner disposeAwareTaskRunner;
private readonly ITUnitCoverageRunner tUnitCoverageRunner;
private bool disposed = false;

[ImportingConstructor]
Expand All @@ -82,12 +84,14 @@ public FCCEngine(
ISolutionEvents solutionEvents,
IAppOptionsProvider appOptionsProvider,
IEventAggregator eventAggregator,
IDisposeAwareTaskRunner disposeAwareTaskRunner
IDisposeAwareTaskRunner disposeAwareTaskRunner,
ITUnitCoverageRunner tUnitCoverageRunner
)
{
this.solutionEvents = solutionEvents;
this.eventAggregator = eventAggregator;
this.disposeAwareTaskRunner = disposeAwareTaskRunner;
this.tUnitCoverageRunner = tUnitCoverageRunner;
solutionEvents.AfterClosing += (s,args) => ClearUI(false);
appOptionsProvider.OptionsChanged += (appOptions) =>
{
Expand Down Expand Up @@ -121,6 +125,7 @@ public void Initialize(CancellationToken cancellationToken)
msTestPlatformUtil.Initialize(AppDataFolderPath, cancellationToken);
coverageUtilManager.Initialize(AppDataFolderPath, cancellationToken);
msCodeCoverageRunSettingsService.Initialize(AppDataFolderPath, this,cancellationToken);
tUnitCoverageRunner.Initialize(AppDataFolderPath, cancellationToken);
}

public void ClearUI(bool clearOutputWindowHistory = true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,23 @@ internal interface IProjectRunSettingsFromTemplateResult
List<ICoverageProject> CoverageProjectsWithFCCMsTestAdapter { get; }
}

internal class TemplatedCoverageProjectRunSettingsResult : ICoverageProjectRunSettings
{
public ICoverageProject CoverageProject { get; set; }
public string RunSettings { get; set; }
public string CustomTemplatePath { get; internal set; }
public bool ReplacedTestAdapter { get; internal set; }
}

internal interface ITemplatedRunSettingsService
{
Task<IProjectRunSettingsFromTemplateResult> GenerateAsync(IEnumerable<ICoverageProject> coverageProjectsWithoutRunSettings, string solutionDirectory, string fccMsTestAdapterPath);
Task CleanUpAsync(List<ICoverageProject> coverageProjects);
List<TemplatedCoverageProjectRunSettingsResult> CreateProjectsRunSettings(
IEnumerable<ICoverageProject> coverageProjects,
string solutionDirectory,
string fccMsTestAdapterPath
);

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,6 @@ internal class TemplatedRunSettingsService : ITemplatedRunSettingsService
private readonly IRunSettingsTemplateReplacementsFactory runSettingsTemplateReplacementsFactory;
private readonly IProjectRunSettingsGenerator projectRunSettingsGenerator;

private class TemplatedCoverageProjectRunSettingsResult : ICoverageProjectRunSettings
{
public ICoverageProject CoverageProject { get; set; }
public string RunSettings { get; set; }
public string CustomTemplatePath { get; internal set; }
public bool ReplacedTestAdapter { get; internal set; }
}

private class ProjectRunSettingsFromTemplateResult : IProjectRunSettingsFromTemplateResult
{
private class ExceptionReasonImpl : IExceptionReason
Expand Down Expand Up @@ -120,7 +112,7 @@ private IProjectRunSettingsFromTemplateResult CreateSuccessResult(IEnumerable<Te
};
}

private List<TemplatedCoverageProjectRunSettingsResult> CreateProjectsRunSettings(
public List<TemplatedCoverageProjectRunSettingsResult> CreateProjectsRunSettings(
IEnumerable<ICoverageProject> coverageProjects,
string solutionDirectory,
string fccMsTestAdapterPath
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using FineCodeCoverage.Engine.Model;
using FineCodeCoverage.Options;
using Microsoft.CodeAnalysis;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.ProjectSystem;
using Microsoft.VisualStudio.ProjectSystem.Build;
Expand Down Expand Up @@ -61,18 +62,12 @@ private async Task<bool> IsTUnitAsync()

private async Task<bool> ProjectEnabledAsync()
{
var coverageProject = await GetCoverageProjectAsync();
if (coverageProject != null)
{
var isTUnit = await IsTUnitAsync();
if (isTUnit)
{
return false;
}
var projectSettings = await coverageProjectSettingsManager.GetSettingsAsync(coverageProject);
return projectSettings.Enabled;
}
return true;
var projectGuid = await GetProjectGuidAsync();
if (!projectGuid.HasValue) return false;

var coverageProject = GetCoverageProject(projectGuid.Value);
var projectSettings = await coverageProjectSettingsManager.GetSettingsAsync(coverageProject);
return projectSettings.Enabled;
}

private async Task<Guid?> GetProjectGuidAsync()
Expand All @@ -93,23 +88,18 @@ private async Task<bool> ProjectEnabledAsync()
return null;
}

private async Task<CoverageProject> GetCoverageProjectAsync()
private CoverageProject GetCoverageProject(Guid projectGuid)
{
var projectGuid = await GetProjectGuidAsync();
if (projectGuid.HasValue)
return new CoverageProject(appOptionsProvider, null, coverageProjectSettingsManager, null)
{
return new CoverageProject(appOptionsProvider, null, coverageProjectSettingsManager, null)
{
Id = projectGuid.Value,
ProjectFile = unconfiguredProject.FullPath
};
}
return null;
Id = projectGuid,
ProjectFile = unconfiguredProject.FullPath
};
}

public override async Task<IImmutableDictionary<string, string>> GetGlobalPropertiesAsync(CancellationToken cancellationToken)
{
if (!AllProjectsDisabled() && await ProjectEnabledAsync())
if (!await IsTUnitAsync() && !AllProjectsDisabled() && await ProjectEnabledAsync())
{
return Empty.PropertiesMap.Add("DisableTestingPlatformServerCapability", "true");
}
Expand Down
Loading
Loading