-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* TUnit Support * Update TUnit --------- Co-authored-by: Tom Longhurst <[email protected]> Co-authored-by: PascalSenn <[email protected]>
- Loading branch information
1 parent
5fa1367
commit 72cf492
Showing
37 changed files
with
2,236 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
using System.Runtime.CompilerServices; | ||
[assembly: InternalsVisibleTo("Snapshooter.TUnit.Tests")] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
<Import Project="$(CCResourceProjectProps)" Condition="Exists('$(CCResourceProjectProps)')" /> | ||
|
||
<PropertyGroup> | ||
<TargetFrameworks>net8.0</TargetFrameworks> | ||
<AssemblyName>Snapshooter.TUnit</AssemblyName> | ||
<RootNamespace>Snapshooter.TUnit</RootNamespace> | ||
<PackageId>Snapshooter.TUnit</PackageId> | ||
<Description> | ||
TUnit Snapshooter is a flexible snapshot testing tool for .Net unit tests with TUnit. | ||
It creates and asserts snapshots (json format) within TUnit unit tests. | ||
</Description> | ||
<IsTestProject>false</IsTestProject> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\Snapshooter\Snapshooter.csproj" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="TUnit.Assertions" Version="0.3.20" /> | ||
<PackageReference Include="TUnit.Core" Version="0.3.20" /> | ||
</ItemGroup> | ||
|
||
</Project> |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
using System; | ||
|
||
namespace Snapshooter.TUnit | ||
{ | ||
public static class SnapshotExtension | ||
{ | ||
/// <summary> | ||
/// Creates a json snapshot of the given object and compares it with the | ||
/// already existing snapshot of the test. | ||
/// If no snapshot exists, a new snapshot will be created from the current result | ||
/// and saved under a certain file path, which will shown within the test message. | ||
/// </summary> | ||
/// <param name="currentResult">The object to match.</param> | ||
/// <param name="matchOptions"> | ||
/// Additional compare actions, which can be applied during the snapshot comparison | ||
/// </param> | ||
public static void MatchSnapshot( | ||
this object currentResult, | ||
Func<MatchOptions, MatchOptions> matchOptions = null) | ||
{ | ||
var cleanedObject = currentResult.RemoveUnwantedWrappers(); | ||
Snapshot.Match(cleanedObject, matchOptions); | ||
} | ||
|
||
/// <summary> | ||
/// Creates a json snapshot of the given object and compares it with the | ||
/// already existing snapshot of the test. | ||
/// If no snapshot exists, a new snapshot will be created from the current result | ||
/// and saved under a certain file path, which will shown within the test message. | ||
/// </summary> | ||
/// <param name="currentResult">The object to match.</param> | ||
/// <param name="snapshotNameExtension"> | ||
/// The snapshot name extension will extend the generated snapshot name with | ||
/// this given extensions. It can be used to make a snapshot name even more | ||
/// specific. | ||
/// Example: | ||
/// Generated Snapshotname = 'NumberAdditionTest' | ||
/// Snapshot name extension = '5', '6', 'Result', '11' | ||
/// Result: 'NumberAdditionTest_5_6_Result_11' | ||
/// </param> | ||
/// <param name="matchOptions"> | ||
/// Additional compare actions, which can be applied during the snapshot comparison | ||
/// </param> | ||
public static void MatchSnapshot( | ||
this object currentResult, | ||
SnapshotNameExtension snapshotNameExtension, | ||
Func<MatchOptions, MatchOptions> matchOptions = null) | ||
{ | ||
var cleanedObject = currentResult.RemoveUnwantedWrappers(); | ||
Snapshot.Match(cleanedObject, snapshotNameExtension, matchOptions); | ||
} | ||
|
||
/// <summary> | ||
/// Creates a json snapshot of the given object and compares it with the | ||
/// already existing snapshot of the test. | ||
/// If no snapshot exists, a new snapshot will be created from the current result | ||
/// and saved under a certain file path, which will shown within the test message. | ||
/// </summary> | ||
/// <param name="currentResult">The object to match.</param> | ||
/// <param name="snapshotName"> | ||
/// The name of the snapshot. If not set, then the snapshotname | ||
/// will be evaluated automatically from the TUnit test name. | ||
/// </param> | ||
/// <param name="matchOptions"> | ||
/// Additional compare actions, which can be applied during the snapshot comparison | ||
/// </param> | ||
public static void MatchSnapshot( | ||
this object currentResult, | ||
string snapshotName, | ||
Func<MatchOptions, MatchOptions> matchOptions = null) | ||
{ | ||
var cleanedObject = currentResult.RemoveUnwantedWrappers(); | ||
Snapshot.Match(cleanedObject, snapshotName, matchOptions); | ||
} | ||
|
||
/// <summary> | ||
/// Creates a json snapshot of the given object and compares it with the | ||
/// already existing snapshot of the test. | ||
/// If no snapshot exists, a new snapshot will be created from the current result | ||
/// and saved under a certain file path, which will shown within the test message. | ||
/// </summary> | ||
/// <param name="currentResult">The object to match.</param> | ||
/// <param name="snapshotName"> | ||
/// The name of the snapshot. If not set, then the snapshotname | ||
/// will be evaluated automatically from the TUnit test name. | ||
/// </param> | ||
/// <param name="snapshotNameExtension"> | ||
/// The snapshot name extension will extend the generated snapshot name with | ||
/// this given extensions. It can be used to make a snapshot name even more | ||
/// specific. | ||
/// Example: | ||
/// Generated Snapshotname = 'NumberAdditionTest' | ||
/// Snapshot name extension = '5', '6', 'Result', '11' | ||
/// Result: 'NumberAdditionTest_5_6_Result_11' | ||
/// </param> | ||
/// <param name="matchOptions"> | ||
/// Additional compare actions, which can be applied during the snapshot comparison. | ||
/// </param> | ||
public static void MatchSnapshot( | ||
this object currentResult, | ||
string snapshotName, | ||
SnapshotNameExtension snapshotNameExtension, | ||
Func<MatchOptions, MatchOptions> matchOptions = null) | ||
{ | ||
var cleanedObject = currentResult.RemoveUnwantedWrappers(); | ||
Snapshot.Match(cleanedObject, snapshotName, snapshotNameExtension, matchOptions); | ||
} | ||
|
||
/// <summary> | ||
/// Creates a json snapshot of the given object and compares it with the | ||
/// already existing snapshot of the test. | ||
/// If no snapshot exists, a new snapshot will be created from the current result | ||
/// and saved under a certain file path, which will shown within the test message. | ||
/// </summary> | ||
/// <param name="currentResult">The object to match.</param> | ||
/// <param name="snapshotFullName"> | ||
/// The full name of a snapshot with folder and file name. | ||
/// To get a SnapshotFullName use Snapshot.FullName(). </param> | ||
/// <param name="matchOptions"> | ||
/// Additional compare actions, which can be applied during the snapshot comparison. | ||
/// </param> | ||
public static void MatchSnapshot( | ||
this object currentResult, | ||
SnapshotFullName snapshotFullName, | ||
Func<MatchOptions, MatchOptions> matchOptions = null) | ||
{ | ||
var cleanedObject = currentResult.RemoveUnwantedWrappers(); | ||
Snapshot.Match(cleanedObject, snapshotFullName, matchOptions); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
using Snapshooter.Core; | ||
using TUnit.Assertions.Extensions; | ||
using TAssert = TUnit.Assertions.Assert; | ||
|
||
namespace Snapshooter.TUnit | ||
{ | ||
/// <summary> | ||
/// The NunitAssert instance compares two strings with the TUnit assert utility. | ||
/// </summary> | ||
public class TUnitAssert : IAssert | ||
{ | ||
/// <summary> | ||
/// Asserts the expected snapshot and the actual snapshot | ||
/// with the TUnit assert utility. | ||
/// </summary> | ||
/// <param name="expectedSnapshot">The expected snapshot.</param> | ||
/// <param name="actualSnapshot">The actual snapshot.</param> | ||
public void Assert(string expectedSnapshot, string actualSnapshot) | ||
{ | ||
// TUnit assertions use an async syntax but this interface is restricted to synchronous calls | ||
#pragma warning disable TUnitAssertions0002 | ||
TAssert.That(actualSnapshot).IsEqualTo(expectedSnapshot).GetAwaiter().GetResult(); | ||
#pragma warning restore TUnitAssertions0002 | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using System.Linq; | ||
using System.Reflection; | ||
using System.Runtime.CompilerServices; | ||
using Snapshooter.Core; | ||
using Snapshooter.Exceptions; | ||
using Snapshooter.Extensions; | ||
using TUnit.Core; | ||
|
||
namespace Snapshooter.TUnit | ||
{ | ||
/// <summary> | ||
/// A TUnit snapshot full name reader is responsible to get the information | ||
/// for the snapshot file from a TUnit test. | ||
/// </summary> | ||
public class TUnitSnapshotFullNameReader : ISnapshotFullNameReader | ||
{ | ||
/// <summary> | ||
/// Evaluates the snapshot full name information. | ||
/// </summary> | ||
/// <returns>The full name of the snapshot.</returns> | ||
public SnapshotFullName ReadSnapshotFullName() | ||
{ | ||
SnapshotFullName snapshotFullName = null; | ||
StackFrame[] stackFrames = new StackTrace(true).GetFrames(); | ||
foreach (StackFrame stackFrame in stackFrames) | ||
{ | ||
MethodBase method = stackFrame.GetMethod(); | ||
if (IsTUnitTestMethod(method)) | ||
{ | ||
snapshotFullName = new SnapshotFullName( | ||
GetCurrentSnapshotName(), | ||
stackFrame.GetFileName().GetDirectoryName()); | ||
|
||
break; | ||
} | ||
|
||
MethodBase asyncMethod = EvaluateAsynchronousMethodBase(method); | ||
if (IsTUnitTestMethod(asyncMethod)) | ||
{ | ||
snapshotFullName = new SnapshotFullName( | ||
GetCurrentSnapshotName(), | ||
stackFrame.GetFileName().GetDirectoryName()); | ||
|
||
break; | ||
} | ||
} | ||
|
||
if (snapshotFullName == null) | ||
{ | ||
throw new SnapshotTestException( | ||
"The snapshot full name could not be evaluated. " + | ||
"This error can 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 " + | ||
"Snapshot.Match method."); | ||
} | ||
|
||
snapshotFullName = LiveUnitTestingDirectoryResolver | ||
.CheckForSession(snapshotFullName); | ||
|
||
return snapshotFullName; | ||
} | ||
|
||
private static bool IsTUnitTestMethod(MemberInfo method) | ||
{ | ||
return method?.GetCustomAttributes(typeof(TestAttribute)).Any() ?? false; | ||
} | ||
|
||
private static MethodBase EvaluateAsynchronousMethodBase(MemberInfo method) | ||
{ | ||
Type methodDeclaringType = method?.DeclaringType; | ||
Type classDeclaringType = methodDeclaringType?.DeclaringType; | ||
|
||
MethodInfo actualMethodInfo = null; | ||
if (classDeclaringType != null) | ||
{ | ||
IEnumerable<MethodInfo> selectedMethodInfos = | ||
from methodInfo in classDeclaringType.GetMethods() | ||
let stateMachineAttribute = methodInfo | ||
.GetCustomAttribute<AsyncStateMachineAttribute>() | ||
where stateMachineAttribute != null && | ||
stateMachineAttribute.StateMachineType == methodDeclaringType | ||
select methodInfo; | ||
|
||
actualMethodInfo = selectedMethodInfos.SingleOrDefault(); | ||
} | ||
|
||
return actualMethodInfo; | ||
|
||
} | ||
|
||
private static string GetCurrentSnapshotName() | ||
{ | ||
TestContext currentTestContext = TestContext.Current!; | ||
|
||
var typeName = currentTestContext.TestDetails.ClassType.Name; | ||
var methodName = currentTestContext.TestDetails.TestName; | ||
var parameters = SnapshotNameExtension.Create(currentTestContext.TestDetails.TestMethodArguments).ToParamsString(); | ||
|
||
return $"{typeName}.{methodName}{parameters}"; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 21 additions & 0 deletions
21
test/Snapshooter.TUnit.Tests/Snapshooter.TUnit.Tests.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
<Import Project="$(CCTestProjectProps)" Condition="Exists('$(CCTestProjectProps)')" /> | ||
|
||
<PropertyGroup> | ||
<TargetFrameworks>net8.0</TargetFrameworks> | ||
<AssemblyName>Snapshooter.TUnit.Tests</AssemblyName> | ||
<RootNamespace>Snapshooter.TUnit.Tests</RootNamespace> | ||
<IsTestProject>true</IsTestProject> | ||
<LangVersion>latest</LangVersion> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\..\src\Snapshooter.TUnit\Snapshooter.TUnit.csproj" /> | ||
<ProjectReference Include="..\Snapshooter.Tests.Data\Snapshooter.Tests.Data.csproj" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="TUnit" Version="0.3.20" /> | ||
</ItemGroup> | ||
|
||
</Project> |
Oops, something went wrong.