Skip to content

Repository files navigation

ProtoTest

CI NuGet Downloads All NuGet packages License

ProtoTest is a foundation for integration testing on .NET 8, 9 and 10.

What is ProtoTest?

Hard to describe it. You could call it a foundation, a large test framework or something else. I have a preference for "foundation", since that best describes what I personally want ProtoTest to be.

It's something you can build upon to do integration testing without having to build all of the supporting infrastructure yourself.

Documentation

What does it bring me?

Core gives you the foundation of ProtoTest.

It provides a lifecycle independent of the test runner you choose, so ProtoTest itself doesn't lock you into one runner. Adapters are available for NUnit, xUnit, TUnit and MSTest.

Each test gets its own ProtoExecutionContext. That context can share state between hooks, attributes and the test itself, while also giving you access to configured clients and integrations, observations, tracing and other shared functionality.

The idea is that integrations don't each live in their own little world. They participate in the same test execution and can make use of the same lifecycle, context and tracing.

ProtoTest currently integrates with REST, GraphQL, gRPC, SQL, Entity Framework Core, Playwright, Selenium, RabbitMQ, ASP.NET Core, Testcontainers, OpenTelemetry and more.

This definitely is a large list. I picked these because they're commonly used, but if something is missing, you can easily create an integration yourself, extend an existing one or open a discussion and I'll check it out.

Use only what your test suite needs. You're not obligated to use everything.

Learn more about Core

Explore the integrations

Extend ProtoTest yourself

What if it breaks?

I admit, ProtoTest hides a lot of setup for you, or puts it behind abstract layers.

That makes tests cleaner, but it can also make figuring out what went wrong harder.

To help with that, I took inspiration from Playwright traces.

The built-in integrations hook into the tracing provided by Core. At the end of a run, ProtoTest writes a .prototrace file containing the execution trace, including setup and teardown, observations, state, attachments and additional reports when configured.

That brings us to ProtoTrace. The place where you can hopefully find what went wrong with your test.

ProtoTrace showing a failed integration test, its execution story, response mismatch and cleanup

ProtoTrace · Open an interactive trace

Why did I build this?

I love programming, but especially building tools and solving abstract problems.

Integration testing can get rough, especially for bigger applications such as SaaS applications. There's so much infrastructure, setup and so on.

My focus is and always has been clean and readable code. ProtoTest is my response to how messy that setup gets.

It's built from scratch, but on what I learned from a testing framework I wrote by hand years ago. I had already been thinking about building ProtoTest since March, but was in a bit of a coding slump and never really got started. Once I did, it moved very quickly.

Read more about why I built ProtoTest.

What does that look like?

[ProtoTest]
[SignedInAs]
public async Task RestWritesAreVisibleThroughGraphQL()
{
    using var created = await Proto.Context.Rest()
        .Body(new CreateProjectRequest("atlas"))
        .PostAsync("/api/v1/projects");

    created.Should.HaveHttpStatus(HttpStatusCode.Created);

    using var projects = await Proto.Context.GraphQL()
        .Query("projects", new { first = 10 })
        .ExpectAsync(new
        {
            totalCount = 1,
            nodes = new[] { new { name = "atlas", status = ProjectStatuses.Active } }
        });

    projects.ShouldHaveNoErrors();
}

This is a simple example combining the REST and GraphQL integrations. The focus lies on a clean test with most of the infrastructure moved out of the test once it has been configured.

The test can focus on the behavior. If something goes wrong, its lifecycle, operations and checks are written to the same .prototrace file.

Is it just wrappers?

In essence, you could call it that. They wrap around proven frameworks that do certain jobs really well.

If they already do their job well, why wrap them?

I'm a huge fan of AAA since discovering that principle. Tests should simply be that readable: Arrange-Act-Assert. Straight to the point.

That's why the wrappers exist. They integrate with the Core and they're my opinionated view on how I want to test with them.

Common application setup can stay outside the test. Setup that matters to the scenario should still be visible.

Is it the best for everyone? Probably not. But it might just help someone do integration testing.

Try it

dotnet new install ProtoTest.Templates
dotnet new prototest -n Shop
cd Shop
dotnet test

Additional demo suite

Bonus: Behind the name

A little bonus since ProtoTest might seem like a weird name. I tend to use Proto for projects that match my vision. As a student, I created ProtoEngine (a C++ 2D game engine, also available on GitHub).

Why Proto? Is it short for Prototype?

Yes, you'd be correct. Prototype in the sense of looking simple and straight to the point.

That's always my goal, even if I don't succeed in every step or implementation. It has to look readable and simple while still being extendable.

That's where the name ProtoTest comes from: Proto, from Prototype, combined with Testing. Bringing some of that simplicity and directness to integration testing.

AI usage?

Yes, extensively. This is the first personal project where I have used AI this much.

I had already built a similar testing framework by hand before the AI boom. ProtoTest was built from scratch, but the vision for most of it already existed.

AI helped me work through ideas, alternatives and implementations much faster. I know what it can produce without enough direction, so I used different models, compared their suggestions, said no often and kept control over what ProtoTest became.

Do I regret using it? I don't know yet.

ProtoTest is still what I wanted to build.

Read the longer explanation in the documentation.

License

ProtoTest is available under the MIT license. Issues and contributions are welcome.

About

Making .NET integration testing as simple, readable, and frictionless as writing a prototype.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages