Benchmarks
These benchmarks compare aweXpect's happy-path overhead (passing assertions, the dominant case in a healthy test suite) against the equivalent FluentAssertions and TUnit calls.
- Suite:
HappyCaseBenchmarksdriven by BenchmarkDotNet. - Job:
MediumRunwith the in-process toolchain. - Runner:
ubuntu-latestGitHub Actions agent, refreshed on every push tomain. - Each tab shows the latest measured time and allocated memory; bars are scaled within the row so length corresponds to magnitude. Lower is better.
- String
- Integer
- Equivalency
- Items count
- Contains
- String array
- Condition
- Exceptions
- Several at once
- Events
Verifies that two string values are equal, ignoring case.
await That(_stringSubject).IsEqualTo(_stringExpectation).IgnoringCase();
_stringSubject.Should().BeEquivalentTo(_stringExpectation);
await Assert.That(_stringSubject).IsEqualTo(_stringExpectation).IgnoringCase();
Verifies that an int subject is greater than a minimum.
await That(_intSubject).IsGreaterThan(_intMinimum);
_intSubject.Should().BeGreaterThan(_intMinimum);
await Assert.That(_intSubject).IsGreaterThan(_intMinimum);
Verifies that two albums are structurally equivalent, including their artist and all 17 tracks.
await That(_albumSubject).IsEquivalentTo(_albumExpectation);
_albumSubject.Should().BeEquivalentTo(_albumExpectation);
await Assert.That(_albumSubject).IsEquivalentTo(_albumExpectation);
Verifies that an int[] has at least the expected number of items (1,000 items in this benchmark).
await That(_enumerableSubject).HasCount().GreaterThanOrEqualTo(_enumerableCount);
_enumerableSubject.Should().HaveCountGreaterThanOrEqualTo(_enumerableCount);
await Assert.That(_enumerableSubject).Count().IsGreaterThanOrEqualTo(_enumerableCount);
Verifies that a List<string> of 17 track titles contains the expected title.
await That(_containsSubject).Contains(_containsExpected);
_containsSubject.Should().Contain(_containsExpected);
await Assert.That(_containsSubject).Contains(_containsExpected);
Verifies that two three-element string arrays are equal in the same order.
In any order
Verifies that two three-element string arrays contain the same values regardless of order.
await That(_stringArraySubject).IsEqualTo(_stringArrayExpectation);
// In any order
await That(_stringArrayAnyOrderSubject)
.IsEqualTo(_stringArrayAnyOrderExpectation).InAnyOrder();
_stringArraySubject.Should().Equal(_stringArrayExpectation);
// In any order
_stringArrayAnyOrderSubject.Should().BeEquivalentTo(_stringArrayAnyOrderExpectation);
await Assert.That(_stringArraySubject)
.IsEquivalentTo(_stringArrayExpectation, CollectionOrdering.Matching);
// In any order
await Assert.That(_stringArrayAnyOrderSubject)
.IsEquivalentTo(_stringArrayAnyOrderExpectation);
Verifies that an int subject satisfies a predicate.
FluentAssertions' Match takes an expression tree and compiles it on every call, which is where most of its time and memory goes.
await That(_satisfiesSubject).Satisfies(x => x > 0);
_satisfiesSubject.Should().Match(x => x > 0);
await Assert.That(_satisfiesSubject).Satisfies(x => x > 0);
Verifies that a delegate throws an InvalidOperationException with the expected message.
Throwing the exception is part of every measurement and is the same work for all three libraries.
Asynchronous Verifies the same for an asynchronous delegate.
await That(_throwsSubject).Throws<InvalidOperationException>().WithMessage(_throwsMessage);
// Asynchronous
await That(_throwsAsyncSubject).Throws<InvalidOperationException>().WithMessage(_throwsMessage);
_throwsSubject.Should().Throw<InvalidOperationException>().WithMessage(_throwsMessage);
// Asynchronous
await _throwsAsyncSubject.Should().ThrowAsync<InvalidOperationException>().WithMessage(_throwsMessage);
await Assert.That(_throwsSubject).Throws<InvalidOperationException>().WithMessage(_throwsMessage);
// Asynchronous
await Assert.That(_throwsAsyncSubject).Throws<InvalidOperationException>().WithMessage(_throwsMessage);
Verifies three properties of an album at once, so that all failures would be reported together.
await Expect.ThatAll(
That(_multipleSubject.Title).IsEqualTo("Abbey Road"),
That(_multipleSubject.Artist.Name).IsEqualTo("The Beatles"),
That(_multipleSubject.Genre).IsEqualTo(Genre.Rock));
using (new AssertionScope())
{
_multipleSubject.Title.Should().Be("Abbey Road");
_multipleSubject.Artist.Name.Should().Be("The Beatles");
_multipleSubject.Genre.Should().Be(Genre.Rock);
}
using (Assert.Multiple())
{
await Assert.That(_multipleSubject.Title).IsEqualTo("Abbey Road");
await Assert.That(_multipleSubject.Artist.Name).IsEqualTo("The Beatles");
await Assert.That(_multipleSubject.Genre).IsEqualTo(Genre.Rock);
}
Verifies that an event was raised, including starting the recording and raising the event.
TUnit has no event recording to compare against, so it is not part of this benchmark.
FluentAssertions' Monitor() emits a handler for each event of the object at runtime, which is where most of its time goes.
using aweXpect.Recording;
Player player = new();
IEventRecording<Player> recording = player.Record().Events();
player.Play();
await That(recording).Triggered(nameof(Player.Started));
Player player = new();
using IMonitor<Player> monitor = player.Monitor();
player.Play();
monitor.Should().Raise(nameof(Player.Started));
Extension packages
The extension packages compare their main features with FluentAssertions on their own benchmark pages:
aweXpect.Snapshots has no benchmarks: its time goes into file access, and FluentAssertions has no snapshots to compare with.