Skip to content

Conversation

@thomhurst
Copy link
Owner

@thomhurst thomhurst commented Jun 5, 2025

This PR contains the following updates:

Package Type Update Change
TUnit nuget minor 0.24.0 -> 0.50.0
TUnit.Assertions nuget minor 0.24.0 -> 0.50.0
TUnit.Assertions.FSharp nuget minor 0.24.0 -> 0.50.0
TUnit.Core nuget minor 0.24.0 -> 0.50.0
TUnit.Playwright nuget minor 0.24.0 -> 0.50.0

Release Notes

thomhurst/TUnit (TUnit)

v0.50.0: 0.50.0

Apologies for the delay. This PR has taken a lot longer than anticipated.

It involves a lot of refactoring and rewriting of some core logic. So if I've knocked anything out, apologies, and raise an issue with a reproduceable example please!

There are a bunch of breaking changes in this release, so apologies in advance!
These include:

  • Needing to amend signatures for custom data source attributes
  • The SourceGenerated[Type]Information types have been renamed to [Type]Metadata.

This change does include some new features for any advanced users.

  • Improved automatic object lifecycle tracking.

  • A new Priority attribute, to prioritise running certain tests first. This can be combined with --fail-fast to terminate test runs quicker on failures.

  • One is Asynchronous data sources! I'd advise to be careful with these, as they could dramatically slow down discovery. But you can now use asynchronous APIs to generate data sources for your tests.

  • And the one I'm excited about most, is nested property injection (with initialization). This can allow for some advanced test orchestration with relatively simple code, and TUnit will handle all the advanced bits for you like initialization and object lifetimes!

Here's some pseudo-code:

public class InMemorySql : IAsyncInitializer, IAsyncDisposable
{
    public async Task InitializeAsync()
    {
        await Container.StartAsync();
    }

    public async ValueTask DisposeAsync()
    {
        await Container.DisposeAsync();
    }
}

public class InMemoryRedis : IAsyncInitializer, IAsyncDisposable
{
    public async Task InitializeAsync()
    {
        await Container.StartAsync();
    }

    public async ValueTask DisposeAsync()
    {
        await Container.DisposeAsync();
    }
}

public class InMemoryMessageBus : IAsyncInitializer, IAsyncDisposable
{
    public async Task InitializeAsync()
    {
        await Container.StartAsync();
    }

    public async ValueTask DisposeAsync()
    {
        await Container.DisposeAsync();
    }
}

public class MessageBusUserInterface : IAsyncInitializer, IAsyncDisposable
{
    [ClassData<InMemoryMessageBus>(Shared = SharedType.PerTestSession)]
    public required InMemoryMessageBus MessageBus { get; init; }

    public async Task InitializeAsync()
    {
        Container = new MessageBusUIContainerBuilder()
                        .WithConnectionString(MessageBus.Container.GetConnectionString())
                        .Build();

        await Container.StartAsync();
    }

    public async ValueTask DisposeAsync()
    {
        await Container.DisposeAsync();
    }
}

public class InMemoryWebApplicationFactory : WebApplicationFactory<Program>, IAsyncInitializer
{
    [ClassData<InMemorySql>(Shared = SharedType.PerTestSession)]
    public required InMemorySql Sql { get; init; }

    [ClassData<InMemoryRedis>(Shared = SharedType.PerTestSession)]
    public required InMemoryRedis Redis { get; init; }

    [ClassData<InMemoryMessageBus>(Shared = SharedType.PerTestSession)]
    public required InMemoryMessageBus MessageBus { get; init; }

    public Task InitializeAsync()
    {
        _ = Server;

        return Task.CompletedTask;
    }

    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder.ConfigureAppConfiguration((context, configBuilder) =>
        {
            configBuilder.AddInMemoryCollection(new Dictionary<string, string?>
            {
                { "MessageBus:ConnectionString", MessageBus.Container.GetConnectionString() },
                { "Redis:ConnectionString", Redis.Container.GetConnectionString() },
                { "PostgreSql:ConnectionString", Sql.Container.GetConnectionString() }
            });
        });
    }
}

public class Tests
{
    [ClassData<InMemoryWebApplicationFactory>]
    public required InMemoryWebApplicationFactory WebApplicationFactory { get; init; }

}

As you can see, you can inject objects into other objects created via data sources. Such as injecting in the message bus into the message bus UI class. And then all the third-party test infrastructure into our WebApplicationFactory. And TUnit manages doing this just before your test starts, initialising anything in order, and disposing of objects when they're finished with.
As you can see, this makes orchestration a lot simpler. This means less time fiddling about with set ups, and more time for writing tests!

Enjoy!

What's Changed
🏕 Changes
👒 Dependencies
New Contributors

Full Changelog: v0.25.21...v0.50.0

v0.25.21: 0.25.21

What's Changed
🏕 Changes
👒 Dependencies

Full Changelog: v0.25.6...v0.25.21

v0.25.6: 0.25.6

What's Changed
🏕 Changes
👒 Dependencies

Full Changelog: v0.25.0...v0.25.6

v0.25.0: 0.25.0

What's Changed
Breaking Changes 🛠
🏕 Changes
👒 Dependencies

Full Changelog: v0.24.0...v0.25.0


Configuration

📅 Schedule: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 Automerge: Enabled.

Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about these updates again.


  • If you want to rebase/retry this PR, check this box

This PR has been generated by Renovate Bot.

@thomhurst thomhurst added dependencies Pull requests that update a dependency file MINOR renovate-bot labels Jun 5, 2025
@thomhurst thomhurst enabled auto-merge (squash) June 5, 2025 01:44
@thomhurst thomhurst added dependencies Pull requests that update a dependency file renovate-bot MINOR labels Jun 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file MINOR renovate-bot Stale

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants