v1.2.0
What's New
Custom Expectations
Create reusable, composable expectations by inheriting from Expectation:
sealed class IsEvenExpectation(int value) : Expectation
{
public override EvaluationResult Evaluate(ExpectationContext context) =>
value % 2 == 0
? ExpectationResults.Pass(context.Expression)
: ExpectationResults.Fail(context.Expression, $"Expected even, got {value}");
}
// Use with static factories or extension methods
Assert(IsEven(4));
Assert(4.IsEven() & !5.IsEven());String Pattern Matching
Wildcard patterns with * (any sequence) and ? (single character):
using SharpAssert.Features.Strings;
Assert("hello world".Matches("hello *"));
Assert("test.txt".Matches("*.txt"));
Assert("HELLO".MatchesIgnoringCase("hello"));Occurrence counting for substrings and regex:
Assert("error, error".Contains("error", Occur.Exactly(2)));
Assert("warn, warn".Contains("warn", Occur.AtLeast(1)));
Assert("test123 test456".MatchesRegex(@"test\d+", Occur.Exactly(2)));Collection Ordering
Validate collections are sorted:
using SharpAssert.Features.Collections;
Assert(numbers.IsInAscendingOrder());
Assert(scores.IsInDescendingOrder());
Assert(names.IsInAscendingOrder(StringComparer.OrdinalIgnoreCase));Collection Uniqueness
Validate collections contain no duplicates:
Assert(items.AllUnique());
Assert(users.AllUnique(u => u.Email)); // By keyObject Equivalency
Structural comparison with fluent configuration:
Assert(actual.IsEquivalentTo(expected));
Assert(actual.IsEquivalentTo(expected, c => c.Excluding(p => p.Id)));
Assert(actual.IsEquivalentTo(expected, c => c.Including(p => p.Name)));
Assert(team1.IsEquivalentTo(team2, c => c.WithoutStrictOrdering()));Improvements
- Programmatic access to results -
SharpAssertionException.Resultproperty provides structured access to assertion evaluation results - Hardened expression evaluation - Better fallbacks and sentinels for edge cases in expression compilation
- Improved expression display - Fixed display for complex nested binary operations and nullable unwrapping
Internal
- Feature-based code organization
- Decoupled evaluation from formatting
- Structured comparison results with rendering pushed into record types
- Simplified rendering without visitors
Full Changelog: v1.1.0...v1.2.0