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

Refactor CookieCrumble to abstract test frameworks #6537

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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
21 changes: 21 additions & 0 deletions src/CookieCrumble/CookieCrumble.sln
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{EB8F1D90-6
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CookieCrumble.Tests", "test\CookieCrumble.Tests\CookieCrumble.Tests.csproj", "{844E7501-7ED6-4548-8E99-D8E50D4F39A4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CookieCrumble.MSTest", "src\CookieCrumble.MSTest\CookieCrumble.MSTest.csproj", "{A7F12BB5-F71C-484D-BABA-2980FE873B59}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CookieCrumble.Xunit", "src\CookieCrumble.Xunit\CookieCrumble.Xunit.csproj", "{CEE25A68-69B5-4CFD-9C35-E82736B1E205}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CookieCrumble.MSTests", "test\CookieCrumble.MSTests\CookieCrumble.MSTests.csproj", "{F83B1337-9535-4121-8B78-89EC970CA705}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -28,9 +34,24 @@ Global
{844E7501-7ED6-4548-8E99-D8E50D4F39A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{844E7501-7ED6-4548-8E99-D8E50D4F39A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{844E7501-7ED6-4548-8E99-D8E50D4F39A4}.Release|Any CPU.Build.0 = Release|Any CPU
{A7F12BB5-F71C-484D-BABA-2980FE873B59}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A7F12BB5-F71C-484D-BABA-2980FE873B59}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A7F12BB5-F71C-484D-BABA-2980FE873B59}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A7F12BB5-F71C-484D-BABA-2980FE873B59}.Release|Any CPU.Build.0 = Release|Any CPU
{CEE25A68-69B5-4CFD-9C35-E82736B1E205}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CEE25A68-69B5-4CFD-9C35-E82736B1E205}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CEE25A68-69B5-4CFD-9C35-E82736B1E205}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CEE25A68-69B5-4CFD-9C35-E82736B1E205}.Release|Any CPU.Build.0 = Release|Any CPU
{F83B1337-9535-4121-8B78-89EC970CA705}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F83B1337-9535-4121-8B78-89EC970CA705}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F83B1337-9535-4121-8B78-89EC970CA705}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F83B1337-9535-4121-8B78-89EC970CA705}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{8E71FA9B-8352-4675-A9B4-A934E40AF9E0} = {2465C122-714C-4D0A-A24D-D9C22A25D73A}
{844E7501-7ED6-4548-8E99-D8E50D4F39A4} = {EB8F1D90-60D6-48FA-9744-D4180A0E4AC0}
{A7F12BB5-F71C-484D-BABA-2980FE873B59} = {2465C122-714C-4D0A-A24D-D9C22A25D73A}
{CEE25A68-69B5-4CFD-9C35-E82736B1E205} = {2465C122-714C-4D0A-A24D-D9C22A25D73A}
{F83B1337-9535-4121-8B78-89EC970CA705} = {EB8F1D90-60D6-48FA-9744-D4180A0E4AC0}
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>$(Library2TargetFrameworks)</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="MSTest.TestFramework" Version="3.0.4" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="../CookieCrumble/CookieCrumble.csproj" />
</ItemGroup>

</Project>
15 changes: 15 additions & 0 deletions src/CookieCrumble/src/CookieCrumble.MSTest/MSTestFramework.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using CookieCrumble;
using System.Reflection;

namespace CookieCrumble.MSTest;

public class MSTestFramework : ITestFramework
{
public bool IsValidTestMethod(MemberInfo? method)
=> method?.GetCustomAttributes(typeof(Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute)).Any() ?? false;

public void ThrowTestException(string message)
{
throw new Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>$(Library2TargetFrameworks)</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Xunit" Version="2.4.1" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="../CookieCrumble/CookieCrumble.csproj" />
</ItemGroup>

</Project>
23 changes: 23 additions & 0 deletions src/CookieCrumble/src/CookieCrumble.Xunit/XunitFramework.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using CookieCrumble;
using System.Reflection;
using Xunit;
using Xunit.Sdk;

namespace CookieCrumble.Xunit;

public class XunitFramework : ITestFramework
{
public bool IsValidTestMethod(MemberInfo? method)
=> IsFactTestMethod(method) || IsTheoryTestMethod(method);

private static bool IsFactTestMethod(MemberInfo? method)
=> method?.GetCustomAttributes(typeof(FactAttribute)).Any() ?? false;

private static bool IsTheoryTestMethod(MemberInfo? method)
=> method?.GetCustomAttributes(typeof(TheoryAttribute)).Any() ?? false;

public void ThrowTestException(string message)
{
throw new XunitException(message);
}
}
1 change: 0 additions & 1 deletion src/CookieCrumble/src/CookieCrumble/CookieCrumble.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
<ItemGroup>
<PackageReference Include="DiffPlex" Version="1.7.1" />
<PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="2.2.0" />
<PackageReference Include="Xunit" Version="2.4.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
</ItemGroup>

Expand Down
9 changes: 9 additions & 0 deletions src/CookieCrumble/src/CookieCrumble/ITestFramework.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System.Reflection;

namespace CookieCrumble;

public interface ITestFramework
{
bool IsValidTestMethod(MemberInfo? method);
void ThrowTestException(string message);
}
60 changes: 32 additions & 28 deletions src/CookieCrumble/src/CookieCrumble/Snapshot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
using CookieCrumble.Formatters;
using DiffPlex.DiffBuilder;
using DiffPlex.DiffBuilder.Model;
using Xunit;
using static System.Collections.Immutable.ImmutableStack;
using static System.IO.Path;

Expand All @@ -34,15 +33,20 @@ public sealed class Snapshot
#endif
});
private static readonly JsonSnapshotValueFormatter _defaultFormatter = new();

private static ITestFramework _testFramework;
private readonly List<SnapshotSegment> _segments = new();
private readonly string _fileName;
private string _extension;
private string? _postFix;
private string? _fileName;

public Snapshot(string? postFix = null, string? extension = null)
{
_fileName = CreateFileName();
if (_testFramework is null)
{
throw new Exception("Please initialise a test framework before using Snapshot");
}

_fileName = GetFilename();
_postFix = postFix;
_extension = extension ?? ".snap";
}
Expand Down Expand Up @@ -89,6 +93,19 @@ public static Snapshot Create(string? postFix = null, string? extension = null)
snapshot.Match();
}

public static void RegisterTestFramework(ITestFramework testFramework)
{
if (testFramework is null)
{
throw new ArgumentNullException(nameof(testFramework));
}

lock (_sync)
{
_testFramework = testFramework;
}
}

public static void RegisterFormatter(
ISnapshotValueFormatter formatter)
{
Expand Down Expand Up @@ -209,7 +226,7 @@ public async ValueTask MatchAsync(CancellationToken cancellationToken = default)
EnsureDirectoryExists(mismatchFile);
await using var stream = File.Create(mismatchFile);
await stream.WriteAsync(writer.WrittenMemory, cancellationToken);
throw new Xunit.Sdk.XunitException(diff);
_testFramework.ThrowTestException(diff);
}
}
}
Expand Down Expand Up @@ -239,7 +256,7 @@ public void Match()
EnsureDirectoryExists(mismatchFile);
using var stream = File.Create(mismatchFile);
stream.Write(writer.WrittenSpan);
throw new Xunit.Sdk.XunitException(diff);
_testFramework.ThrowTestException(diff);
}
}
}
Expand All @@ -253,7 +270,7 @@ public void MatchInline(string expected)

if (!MatchSnapshot(expected, after, true, out var diff))
{
throw new Xunit.Sdk.XunitException(diff);
_testFramework.ThrowTestException(diff);
}
}

Expand Down Expand Up @@ -388,7 +405,7 @@ private string CreateSnapshotFileName()
: string.Concat(fileName, "_", _postFix, _extension);
}

private static string CreateFileName()
private static string GetFilename()
{
foreach (var stackFrame in new StackTrace(true).GetFrames())
{
Expand All @@ -397,24 +414,25 @@ private static string CreateFileName()

if (method is not null &&
!string.IsNullOrEmpty(fileName) &&
IsXunitTestMethod(method))
_testFramework.IsValidTestMethod(method))
{
return Combine(GetDirectoryName(fileName)!, method.ToName());
}

var asyncMethod = EvaluateAsynchronousMethodBase(method);
method = EvaluateAsynchronousMethodBase(method);

if (asyncMethod is not null &&
if (method is not null &&
!string.IsNullOrEmpty(fileName) &&
IsXunitTestMethod(asyncMethod))
_testFramework.IsValidTestMethod(method))
{
return Combine(GetDirectoryName(fileName)!, asyncMethod.ToName());
return Combine(GetDirectoryName(fileName)!, method.ToName());
}
}

throw new Exception(
"The snapshot full name could not be evaluated. " +
"This error can occur, if you use the snapshot match " +
"Only XUnit or MSTest test suites are supported. " +
"This error can also occur, if you use the snapshot match " +
"within a async test helper child method. To solve this issue, " +
"use the Snapshot.FullName directly in the unit test to " +
"get the snapshot name, then reach this name to your " +
Expand Down Expand Up @@ -444,20 +462,6 @@ private static string CreateFileName()
return actualMethodInfo;
}

private static bool IsXunitTestMethod(MemberInfo? method)
{
var isFactTest = IsFactTestMethod(method);
var isTheoryTest = IsTheoryTestMethod(method);

return isFactTest || isTheoryTest;
}

private static bool IsFactTestMethod(MemberInfo? method)
=> method?.GetCustomAttributes(typeof(FactAttribute)).Any() ?? false;

private static bool IsTheoryTestMethod(MemberInfo? method)
=> method?.GetCustomAttributes(typeof(TheoryAttribute)).Any() ?? false;

private struct SnapshotSegment
{
public SnapshotSegment(string? name, object? value, ISnapshotValueFormatter formatter)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>$(Library2TargetFrameworks)</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>

<AssemblyName>CookieCrumble.MSTests</AssemblyName>
<RootNamespace>CookieCrumble</RootNamespace>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
<PackageReference Include="MSTest.TestAdapter" Version="3.0.4" />
<PackageReference Include="MSTest.TestFramework" Version="3.0.4" />
<PackageReference Include="coverlet.collector" Version="3.1.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\CookieCrumble.MSTest\CookieCrumble.MSTest.csproj" />
<ProjectReference Include="..\..\src\CookieCrumble\CookieCrumble.csproj" />
</ItemGroup>

</Project>
Loading
Loading