Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
2 changes: 1 addition & 1 deletion .github/workflows/publish-log4brains.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
- name: Install and Build Log4brains
run: |
npm install -g log4brains
log4brains build
log4brains build --basePath /${GITHUB_REPOSITORY#*/}

- name: Deploy
uses: JamesIves/[email protected]
Expand Down
2 changes: 1 addition & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<PackageVersion Include="Aspire.Hosting.AppHost" Version="9.1.0" />
<PackageVersion Include="Aspire.Hosting.SqlServer" Version="9.1.0" />
<PackageVersion Include="Aspire.Microsoft.EntityFrameworkCore.SqlServer" Version="9.1.0" />
<PackageVersion Include="AwesomeAssertions" Version="8.0.2"/>
<PackageVersion Include="Azure.Identity" Version="1.13.0" />
<PackageVersion Include="Bogus" Version="35.6.1" />
<PackageVersion Include="coverlet.collector" Version="6.0.2">
Expand All @@ -20,7 +21,6 @@
</PackageVersion>
<PackageVersion Include="EntityFrameworkCore.Exceptions.SqlServer" Version="8.1.3" />
<PackageVersion Include="ErrorOr" Version="2.0.1" />
<PackageVersion Include="FluentAssertions" Version="6.12.2" />
<PackageVersion Include="FluentValidation.DependencyInjectionExtensions" Version="11.11.0" />
<PackageVersion Include="JunitXml.TestLogger" Version="4.1.0" />
<PackageVersion Include="MediatR" Version="12.4.1" />
Expand Down
76 changes: 76 additions & 0 deletions docs/adr/20250326-migrate-to-awesome-assertions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Migrate to Awesome Assertions

- Status: accepted
- Deciders: Daniel Mackay, Luke Cooke, Matt Wicks, Anton Polkanov, Matt Parker
- Date: 2025-03-26
- Tags: testing, unit-tests, assertions, awesome-assertions, fluent-assertions

Technical Story: https://github.com/SSWConsulting/SSW.CleanArchitecture/pull/497

## Context and Problem Statement

We have been using FluentAssertions for our unit tests.

This library is great however, the project has now switched to a paid model. Versions 8 and beyond are free for open-source projects and non-commercial use, but commercial use requires a paid licence.

Version 7 will remain fully open-source indefinitely and receive bugfixes and other important corrections.

## Decision Drivers

- Free for commercial use
- Concise and readable assertions

## Considered Options

1. Shouldly
2. Fluent Assertions (free version)
3. Fluent Assertions (paid version)
4. Native test framework assertions (e.g. xUnit/NUnit/TUnit)
5. Awesome Assertions

## Decision Outcome

Chosen option: "Option 5 - Awesome Assertions", because we get the same experience as FluentAssertions, but it is free for commercial use. It is also easy to migrate from FluentAssertions to Awesome Assertions.

## Pros and Cons of the Options <!-- optional -->

### Option 1 - Shouldly

https://docs.shouldly.org/

- ✅ Good assertion library
- ✅ Free for commercial use
- ❌ Would require a lot of work to migrate from FluentAssertions
- ❌ Custom extensions would need to be rewritten

### Option 2 - Fluent Assertions (free version)

https://xceed.com/products/unit-testing/fluent-assertions/

- ✅ Great assertion library
- ✅ Version 7 is Free for open-source projects and non-commercial use
- ❌ Easy to upgrade to version 8, resulting in substantial licence fees

### Option 3 - Fluent Assertions (paid version)

https://xceed.com/products/unit-testing/fluent-assertions/

- ✅ Great assertion library
- ❌ Substantial licence fees for commercial use. ($130 per developer per year. For SSW this would cost $7,410 per year for 57 developers)

### Option 4 - Native test framework assertions (e.g. xUnit/NUnit/TUnit)

- ✅ Free for commercial use
- ✅ No additional dependencies
- ❌ Assertions are not as readable as FluentAssertions
- ❌ Would require a lot of work to migrate from FluentAssertions
- ❌ Custom extensions would need to be rewritten

### Option 5 - Awesome Assertions

https://awesomeassertions.org/

- ✅ Great assertion library
- ✅ Free for commercial use
- ✅ Easy to migrate from FluentAssertions
- ✅ Custom extensions will continue to work (with minor modifications)
2 changes: 1 addition & 1 deletion tests/Architecture.Tests/Architecture.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="AwesomeAssertions"/>
<PackageReference Include="coverlet.collector">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="FluentAssertions" />
<PackageReference Include="JunitXml.TestLogger" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="NetArchTest.Rules" />
Expand Down
8 changes: 6 additions & 2 deletions tests/Architecture.Tests/Common/TestResultAssertions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,19 @@ namespace SSW.CleanArchitecture.Architecture.UnitTests.Common;

public class TestResultAssertions : ReferenceTypeAssertions<TestResult, TestResultAssertions>
{
public TestResultAssertions(TestResult instance) : base(instance)
private readonly AssertionChain _chain;

public TestResultAssertions(TestResult instance, AssertionChain chain) : base(instance, chain)
{
_chain = chain;
}

protected override string Identifier => "TestResult";

[CustomAssertion]
public AndConstraint<TestResultAssertions> BeSuccessful(string because = "", params object[] becauseArgs)
{
Execute.Assertion
_chain
.BecauseOf(because, becauseArgs)
.Given(() => Subject)
.ForCondition(s => s.IsSuccessful)
Expand Down
5 changes: 3 additions & 2 deletions tests/Architecture.Tests/Common/TestResultExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Xunit.Abstractions;
using FluentAssertions.Execution;
using Xunit.Abstractions;

namespace SSW.CleanArchitecture.Architecture.UnitTests.Common;

Expand All @@ -15,5 +16,5 @@ public static void DumpFailingTypes(this TestResult result, ITestOutputHelper ou
outputHelper.WriteLine(type.FullName);
}

public static TestResultAssertions Should(this TestResult result) => new(result);
public static TestResultAssertions Should(this TestResult result) => new(result, AssertionChain.GetOrCreate());
}
2 changes: 1 addition & 1 deletion tests/Domain.UnitTests/Domain.UnitTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="AwesomeAssertions"/>
<PackageReference Include="coverlet.collector">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="FluentAssertions" />
<PackageReference Include="JunitXml.TestLogger" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="xunit" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="AwesomeAssertions"/>
<PackageReference Include="Bogus" />
<PackageReference Include="coverlet.collector">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="FluentAssertions" />
<PackageReference Include="JunitXml.TestLogger" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
Expand Down