Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
9a57c06
Add source generator for assertion methods and related tests
thomhurst Oct 12, 2025
c230bf6
Refactor assertion method generator to use core assertion classes and…
thomhurst Oct 12, 2025
91647e6
Add custom expectation message support to assertion attributes and ge…
thomhurst Oct 12, 2025
5c55681
Refactor assertions to use source-generated methods
thomhurst Oct 12, 2025
b244e9d
Migrate assertions to source-generated methods and remove legacy code
thomhurst Oct 12, 2025
241ca90
Refactor assertion infrastructure: update CheckAsync methods for asyn…
thomhurst Oct 12, 2025
0e3937d
Implement source-generated assertion extensions for CultureInfo, Enco…
thomhurst Oct 12, 2025
ea841cc
Add source-generated assertion extensions for Assembly and DateTime t…
thomhurst Oct 12, 2025
125ffd6
Implement source-generated assertion extensions for CancellationToken…
thomhurst Oct 12, 2025
456b7b2
Implement source-generated assertion extensions for Assembly and Canc…
thomhurst Oct 12, 2025
5779fba
Add source-generated assertion extensions for Guid, Stream, Task, Thr…
thomhurst Oct 12, 2025
7a17e68
Refactor source-generated assertion extensions for various types to u…
thomhurst Oct 12, 2025
270f6e9
Implement source-generated assertion extensions for CultureInfo, Date…
thomhurst Oct 12, 2025
5241c87
Add source-generated assertion extensions for DateTimeOffset, IPAddre…
thomhurst Oct 12, 2025
3a9f74d
Add source-generated assertion extensions for Array, Index, Range, an…
thomhurst Oct 12, 2025
349c2ad
Add source-generated assertion extensions for DateOnly, DirectoryInfo…
thomhurst Oct 12, 2025
f7488c2
Add source-generated assertion extensions for FileInfo, DirectoryInfo…
thomhurst Oct 12, 2025
06d4aaf
Refactor assertion extension classes to be partial and update project…
thomhurst Oct 12, 2025
f27edee
Add assertion tests for Guid, Lazy, StringBuilder, Task, and TimeSpan
thomhurst Oct 12, 2025
3efb326
Add EditorBrowsable attribute to assertion extension methods for bett…
thomhurst Oct 12, 2025
69507d2
Add EditorBrowsable attribute to source-generated assertion methods a…
thomhurst Oct 12, 2025
cceced9
Add assertion tests for Boolean, Char, DateTime, DateTimeOffset, and …
thomhurst Oct 12, 2025
0fb3319
Add assertion extensions for collection membership checks and update …
thomhurst Oct 12, 2025
6381ecb
Add comprehensive assertion tests for assembly, cancellation token, I…
thomhurst Oct 12, 2025
3e0f0eb
Add comprehensive assertion tests for various types and functionalities
thomhurst Oct 12, 2025
08ef10f
Add missing using directives for TUnit.Assertions.Extensions in vario…
thomhurst Oct 12, 2025
5c4547a
Add assertion generator tests for various types and conditions
thomhurst Oct 12, 2025
6af4911
Refactor assertion generator test classes to remove specific generato…
thomhurst Oct 12, 2025
5a8209c
Rename assertion classes and update method signatures to include type…
thomhurst Oct 12, 2025
4a4adae
Merge branch 'main' into feature/enhance-assertion-source-gen
thomhurst Oct 13, 2025
9621915
Add diagnostic messages to assertion extension generator tests
thomhurst Oct 13, 2025
5987f0a
Refactor assertion generator tests and remove diagnostic source gener…
thomhurst Oct 13, 2025
b11ffd4
Update assertion generator tests to expect zero generated files
thomhurst Oct 13, 2025
5d65398
Enhance assertion messages by adding ExpectationMessage attributes fo…
thomhurst Oct 13, 2025
d10d8f6
Update MethodAssertionGenerator to always generate extension methods …
thomhurst Oct 13, 2025
31b82a6
Refactor assertion namespaces and enhance task assertions
thomhurst Oct 13, 2025
27618ef
Refactor AsyncDelegateAssertion and TaskAssertion to avoid awaiting t…
thomhurst Oct 13, 2025
de89714
Refactor assertion tests to improve clarity and reliability by addres…
thomhurst Oct 13, 2025
8848571
Remove CleanGenerated target from SourceGenerationDebug.props to stre…
thomhurst Oct 13, 2025
3b068f6
Add RunOn attribute for Windows to relevant file and directory tests
thomhurst Oct 13, 2025
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
Prev Previous commit
Next Next commit
Refactor assertion namespaces and enhance task assertions
- Updated namespaces from TUnit.Assertions.Conditions to TUnit.Assertions.Extensions for consistency across assertion tests.
- Added support for task assertions, including IsCompleted, IsNotCompleted, IsCanceled, IsNotCanceled, IsFaulted, and IsNotFaulted.
- Introduced TaskAssertion class to handle assertions for Task<TValue> and IAssertionSource<Task<TValue>>.
- Removed redundant directory and file assertions from FileSystemAssertions.cs, consolidating unique assertions.
- Enhanced ArrayAssertionExtensions to include collection assertions for single-element checks.
- Updated assembly tests to target NET5_0_OR_GREATER for improved compatibility.
  • Loading branch information
thomhurst committed Oct 13, 2025
commit 31b82a65c153b6a877b46854d0bcedeeb4374b57
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using TUnit.Assertions.Core;
using TUnit.Assertions.Conditions;

namespace TUnit.Assertions.Conditions;
namespace TUnit.Assertions.Extensions;

/// <summary>
/// Generated assertion for IsEmpty
Expand Down Expand Up @@ -160,6 +161,82 @@ public sealed class _IsNotSingleElement_Assertion<T> : Assertion<T[]>
}
}

/// <summary>
/// Generated assertion for IsSingleElement
/// </summary>
[System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2091", Justification = "Generic type parameter is only used for property access, not instantiation")]
public sealed class IEnumerableT_IsSingleElement_Assertion<T> : Assertion<System.Collections.Generic.IEnumerable<T>>
{
public IEnumerableT_IsSingleElement_Assertion(AssertionContext<System.Collections.Generic.IEnumerable<T>> context)
: base(context)
{
}

protected override Task<AssertionResult> CheckAsync(EvaluationMetadata<System.Collections.Generic.IEnumerable<T>> metadata)
{
var value = metadata.Value;
var exception = metadata.Exception;

if (exception != null)
{
return Task.FromResult(AssertionResult.Failed($"threw {exception.GetType().FullName}"));
}

if (value is null)
{
return Task.FromResult(AssertionResult.Failed("Actual value is null"));
}

var result = value.IsSingleElement();
return Task.FromResult(result
? AssertionResult.Passed
: AssertionResult.Failed($"found {value}"));
}

protected override string GetExpectation()
{
return "to be a single-element collection";
}
}

/// <summary>
/// Generated assertion for IsNotSingleElement
/// </summary>
[System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2091", Justification = "Generic type parameter is only used for property access, not instantiation")]
public sealed class IEnumerableT_IsNotSingleElement_Assertion<T> : Assertion<System.Collections.Generic.IEnumerable<T>>
{
public IEnumerableT_IsNotSingleElement_Assertion(AssertionContext<System.Collections.Generic.IEnumerable<T>> context)
: base(context)
{
}

protected override Task<AssertionResult> CheckAsync(EvaluationMetadata<System.Collections.Generic.IEnumerable<T>> metadata)
{
var value = metadata.Value;
var exception = metadata.Exception;

if (exception != null)
{
return Task.FromResult(AssertionResult.Failed($"threw {exception.GetType().FullName}"));
}

if (value is null)
{
return Task.FromResult(AssertionResult.Failed("Actual value is null"));
}

var result = value.IsNotSingleElement();
return Task.FromResult(result
? AssertionResult.Passed
: AssertionResult.Failed($"found {value}"));
}

protected override string GetExpectation()
{
return "to not be a single-element collection";
}
}

public static partial class ArrayAssertionExtensions
{
/// <summary>
Expand Down Expand Up @@ -202,6 +279,26 @@ public static partial class ArrayAssertionExtensions
return new _IsNotSingleElement_Assertion<T>(source.Context);
}

/// <summary>
/// Generated extension method for IsSingleElement
/// </summary>
[System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2091", Justification = "Generic type parameter is only used for property access, not instantiation")]
public static IEnumerableT_IsSingleElement_Assertion<T> IsSingleElement<T>(this IAssertionSource<System.Collections.Generic.IEnumerable<T>> source)
{
source.Context.ExpressionBuilder.Append(".IsSingleElement()");
return new IEnumerableT_IsSingleElement_Assertion<T>(source.Context);
}

/// <summary>
/// Generated extension method for IsNotSingleElement
/// </summary>
[System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2091", Justification = "Generic type parameter is only used for property access, not instantiation")]
public static IEnumerableT_IsNotSingleElement_Assertion<T> IsNotSingleElement<T>(this IAssertionSource<System.Collections.Generic.IEnumerable<T>> source)
{
source.Context.ExpressionBuilder.Append(".IsNotSingleElement()");
return new IEnumerableT_IsNotSingleElement_Assertion<T>(source.Context);
}

}

]
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using TUnit.Assertions.Core;
using TUnit.Assertions.Conditions;

namespace TUnit.Assertions.Conditions;
namespace TUnit.Assertions.Extensions;

/// <summary>
/// Generated assertion for IsEmpty
Expand Down Expand Up @@ -160,6 +161,82 @@ public sealed class _IsNotSingleElement_Assertion<T> : Assertion<T[]>
}
}

/// <summary>
/// Generated assertion for IsSingleElement
/// </summary>
[System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2091", Justification = "Generic type parameter is only used for property access, not instantiation")]
public sealed class IEnumerableT_IsSingleElement_Assertion<T> : Assertion<System.Collections.Generic.IEnumerable<T>>
{
public IEnumerableT_IsSingleElement_Assertion(AssertionContext<System.Collections.Generic.IEnumerable<T>> context)
: base(context)
{
}

protected override Task<AssertionResult> CheckAsync(EvaluationMetadata<System.Collections.Generic.IEnumerable<T>> metadata)
{
var value = metadata.Value;
var exception = metadata.Exception;

if (exception != null)
{
return Task.FromResult(AssertionResult.Failed($"threw {exception.GetType().FullName}"));
}

if (value is null)
{
return Task.FromResult(AssertionResult.Failed("Actual value is null"));
}

var result = value.IsSingleElement();
return Task.FromResult(result
? AssertionResult.Passed
: AssertionResult.Failed($"found {value}"));
}

protected override string GetExpectation()
{
return "to be a single-element collection";
}
}

/// <summary>
/// Generated assertion for IsNotSingleElement
/// </summary>
[System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2091", Justification = "Generic type parameter is only used for property access, not instantiation")]
public sealed class IEnumerableT_IsNotSingleElement_Assertion<T> : Assertion<System.Collections.Generic.IEnumerable<T>>
{
public IEnumerableT_IsNotSingleElement_Assertion(AssertionContext<System.Collections.Generic.IEnumerable<T>> context)
: base(context)
{
}

protected override Task<AssertionResult> CheckAsync(EvaluationMetadata<System.Collections.Generic.IEnumerable<T>> metadata)
{
var value = metadata.Value;
var exception = metadata.Exception;

if (exception != null)
{
return Task.FromResult(AssertionResult.Failed($"threw {exception.GetType().FullName}"));
}

if (value is null)
{
return Task.FromResult(AssertionResult.Failed("Actual value is null"));
}

var result = value.IsNotSingleElement();
return Task.FromResult(result
? AssertionResult.Passed
: AssertionResult.Failed($"found {value}"));
}

protected override string GetExpectation()
{
return "to not be a single-element collection";
}
}

public static partial class ArrayAssertionExtensions
{
/// <summary>
Expand Down Expand Up @@ -202,6 +279,26 @@ public static partial class ArrayAssertionExtensions
return new _IsNotSingleElement_Assertion<T>(source.Context);
}

/// <summary>
/// Generated extension method for IsSingleElement
/// </summary>
[System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2091", Justification = "Generic type parameter is only used for property access, not instantiation")]
public static IEnumerableT_IsSingleElement_Assertion<T> IsSingleElement<T>(this IAssertionSource<System.Collections.Generic.IEnumerable<T>> source)
{
source.Context.ExpressionBuilder.Append(".IsSingleElement()");
return new IEnumerableT_IsSingleElement_Assertion<T>(source.Context);
}

/// <summary>
/// Generated extension method for IsNotSingleElement
/// </summary>
[System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2091", Justification = "Generic type parameter is only used for property access, not instantiation")]
public static IEnumerableT_IsNotSingleElement_Assertion<T> IsNotSingleElement<T>(this IAssertionSource<System.Collections.Generic.IEnumerable<T>> source)
{
source.Context.ExpressionBuilder.Append(".IsNotSingleElement()");
return new IEnumerableT_IsNotSingleElement_Assertion<T>(source.Context);
}

}

]
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using TUnit.Assertions.Core;
using TUnit.Assertions.Conditions;

namespace TUnit.Assertions.Conditions;
namespace TUnit.Assertions.Extensions;

/// <summary>
/// Generated assertion for IsEmpty
Expand Down Expand Up @@ -160,6 +161,82 @@ public sealed class _IsNotSingleElement_Assertion<T> : Assertion<T[]>
}
}

/// <summary>
/// Generated assertion for IsSingleElement
/// </summary>
[System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2091", Justification = "Generic type parameter is only used for property access, not instantiation")]
public sealed class IEnumerableT_IsSingleElement_Assertion<T> : Assertion<System.Collections.Generic.IEnumerable<T>>
{
public IEnumerableT_IsSingleElement_Assertion(AssertionContext<System.Collections.Generic.IEnumerable<T>> context)
: base(context)
{
}

protected override Task<AssertionResult> CheckAsync(EvaluationMetadata<System.Collections.Generic.IEnumerable<T>> metadata)
{
var value = metadata.Value;
var exception = metadata.Exception;

if (exception != null)
{
return Task.FromResult(AssertionResult.Failed($"threw {exception.GetType().FullName}"));
}

if (value is null)
{
return Task.FromResult(AssertionResult.Failed("Actual value is null"));
}

var result = value.IsSingleElement();
return Task.FromResult(result
? AssertionResult.Passed
: AssertionResult.Failed($"found {value}"));
}

protected override string GetExpectation()
{
return "to be a single-element collection";
}
}

/// <summary>
/// Generated assertion for IsNotSingleElement
/// </summary>
[System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2091", Justification = "Generic type parameter is only used for property access, not instantiation")]
public sealed class IEnumerableT_IsNotSingleElement_Assertion<T> : Assertion<System.Collections.Generic.IEnumerable<T>>
{
public IEnumerableT_IsNotSingleElement_Assertion(AssertionContext<System.Collections.Generic.IEnumerable<T>> context)
: base(context)
{
}

protected override Task<AssertionResult> CheckAsync(EvaluationMetadata<System.Collections.Generic.IEnumerable<T>> metadata)
{
var value = metadata.Value;
var exception = metadata.Exception;

if (exception != null)
{
return Task.FromResult(AssertionResult.Failed($"threw {exception.GetType().FullName}"));
}

if (value is null)
{
return Task.FromResult(AssertionResult.Failed("Actual value is null"));
}

var result = value.IsNotSingleElement();
return Task.FromResult(result
? AssertionResult.Passed
: AssertionResult.Failed($"found {value}"));
}

protected override string GetExpectation()
{
return "to not be a single-element collection";
}
}

public static partial class ArrayAssertionExtensions
{
/// <summary>
Expand Down Expand Up @@ -202,6 +279,26 @@ public static partial class ArrayAssertionExtensions
return new _IsNotSingleElement_Assertion<T>(source.Context);
}

/// <summary>
/// Generated extension method for IsSingleElement
/// </summary>
[System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2091", Justification = "Generic type parameter is only used for property access, not instantiation")]
public static IEnumerableT_IsSingleElement_Assertion<T> IsSingleElement<T>(this IAssertionSource<System.Collections.Generic.IEnumerable<T>> source)
{
source.Context.ExpressionBuilder.Append(".IsSingleElement()");
return new IEnumerableT_IsSingleElement_Assertion<T>(source.Context);
}

/// <summary>
/// Generated extension method for IsNotSingleElement
/// </summary>
[System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2091", Justification = "Generic type parameter is only used for property access, not instantiation")]
public static IEnumerableT_IsNotSingleElement_Assertion<T> IsNotSingleElement<T>(this IAssertionSource<System.Collections.Generic.IEnumerable<T>> source)
{
source.Context.ExpressionBuilder.Append(".IsNotSingleElement()");
return new IEnumerableT_IsNotSingleElement_Assertion<T>(source.Context);
}

}

]
Loading
Loading