Build Part of a Solution and Limit Test Runs With the .NET 11 SDK

dotnettestingtooling
Build Part of a Solution and Limit Test Runs With the .NET 11 SDK

The .NET 11 SDK can create an xUnit v3 test project and apply a timeout or failure limit across a Microsoft.Testing.Platform run. In a solution with a pricing library and a separate dashboard, a solution filter lets you build the pricing tests and their dependencies while leaving the dashboard out.

What Is New in the .NET 11 SDK?

The built-in xUnit template now lets you select xUnit v3 with --xunit-version v3. Selecting v3 gives you a test executable that uses Microsoft.Testing.Platform (MTP) by default. With the MTP version of dotnet test, the CLI can now enforce one timeout and one failure limit across multiple test applications.

The CLI commands for solution filters also work on SDK 10.0.403. You can keep every project in the same solution and give the pricing tests their own .slnf file.

Build a Filter That Includes Project Dependencies

Start in an empty directory where dotnet --version reports 11.0.100. Create a solution containing a pricing library, a dashboard, and pricing tests.

dotnet new sln -n Store
dotnet new classlib -n Pricing --no-restore
dotnet new console -n Dashboard --no-restore
dotnet new xunit -n Pricing.Tests --xunit-version v3 --no-restore
dotnet reference add Pricing/Pricing.csproj --project Pricing.Tests/Pricing.Tests.csproj
dotnet sln Store.slnx add Pricing/Pricing.csproj Dashboard/Dashboard.csproj Pricing.Tests/Pricing.Tests.csproj

The test project now references Pricing. The v3 template sets the test runner in global.json, which is how dotnet test knows to use MTP here.

Create a filter beside the parent solution and add only the test project.

dotnet new slnf -n PricingOnly --parent-solution Store.slnx
dotnet sln PricingOnly.slnf add Pricing.Tests/Pricing.Tests.csproj
dotnet sln PricingOnly.slnf list
dotnet build PricingOnly.slnf

The filter lists just one project.

Project(s)
----------
Pricing.Tests/Pricing.Tests.csproj

The build compiles both Pricing.Tests.dll and Pricing.dll, because the test project references the library. It skips Dashboard. If the dashboard later references Pricing, that dependency points the other way and still doesn't make the dashboard necessary to build the tests.

To expand a filter, run dotnet sln PricingOnly.slnf add Dashboard/Dashboard.csproj. The corresponding remove command takes the dashboard back out of the filter. Run dotnet sln Store.slnx list afterward and you'll still see all three projects.

Give the Test Run a Failure Limit

Add a small pricing rule to Pricing/PricingRules.cs. Shipping is free when the subtotal reaches 5,000 cents.

namespace Pricing;

public static class PricingRules
{
    public static bool ShipsFree(int subtotal) => subtotal >= 5_000;
}

Replace the generated Pricing.Tests/UnitTest1.cs with a data-driven xUnit test. One order is a cent short. The other just qualifies.

using Pricing;

public class ShippingTests
{
    [Theory]
    [InlineData(4_999, false)]
    [InlineData(5_000, true)]
    public void FreeShippingStartsAtThreshold(int subtotal, bool expected)
    {
        Assert.Equal(expected, PricingRules.ShipsFree(subtotal));
    }
}

Run the filter with a 30-second test budget and a limit of two failures. The command rebuilds the changed projects before running the tests.

dotnet test --solution PricingOnly.slnf --timeout 30s --maximum-failed-tests 2

Both cases pass. Now change >= to > in PricingRules.cs and try the one-failure limit.

dotnet test --solution PricingOnly.slnf --maximum-failed-tests 1

The 5,000-cent order now fails. With --maximum-failed-tests 1, that failure hits the limit and the runner returns exit code 13.

failed ShippingTests.FreeShippingStartsAtThreshold(subtotal: 5000, expected: True) (0ms)
  Assert.Equal() Failure: Values differ
Expected: True
Actual:   False

In a larger .NET CI pipeline, put --maximum-failed-tests and --timeout before the -- separator to apply the limits to the whole run. Arguments after the separator go to each test application. With a limit of one, the placement determines whether the first failing project can stop the run or the other projects keep going under their own limits.

The timeout counts time while at least one test application is running. If it expires, the CLI reports an aborted run and returns exit code 3. Keep a separate CI job timeout if restoring packages, compiling, or waiting for a test process to finish also needs a hard deadline.

Summary

Use PricingOnly.slnf for the pricing pull request and keep Store.slnx for the full CI build. If a change touches a shared library and you need to test its consumers, run the full solution. The filter follows references from Pricing.Tests. It won't look for other applications that use Pricing.

Frequently Asked Questions

How do I build only part of a .NET solution?

Create a solution filter with dotnet new slnf, add the projects you want to the filter, and pass the .slnf file to dotnet build. The build also follows project references. The parent solution keeps its full project list.

Does dotnet new xunit use xUnit v3 by default in .NET 11?

No. Specify --xunit-version v3 to use the built-in v3 template. For that version, the template selects Microsoft.Testing.Platform by default.

Does the .NET 11 dotnet test timeout include the build?

The Microsoft.Testing.Platform run-level timeout counts time while at least one test application is running. It does not set a wall-clock deadline for restoring, compiling, and running the entire CI job.

Can I use solution filters with the .NET 10 SDK?

Yes. The .NET 10.0.403 SDK can create a .slnf and add, list, or remove its projects. The .NET 11 SDK also provides the xUnit v3 template option and the run-level test controls used here.

Browse all .NET guides →
Loading comments...

Whenever you're ready, there are 5 ways I can help you:

  1. Pragmatic Self-Hosting: Learn to deploy and run your apps on a VPS with Dokploy and Tailscale. Keep administration private, automate releases, and practice restoring backups, with source code and a runbook you can reuse.
  2. Pragmatic Clean Architecture: Join 5,000+ students in this comprehensive course that will teach you the system I use to ship production-ready applications using Clean Architecture. Learn how to apply the best practices of modern software architecture.
  3. Modular Monolith Architecture: Join 2,800+ engineers in this in-depth course that will transform the way you build modern systems. You will learn the best practices for applying the Modular Monolith architecture in a real-world scenario.
  4. Pragmatic REST APIs: Join 1,900+ students in this course that will teach you how to build production-ready REST APIs using the latest ASP.NET Core features and best practices. It includes a fully functional UI application that we'll integrate with the REST API.
  5. Patreon Community: Join a community of 5,000+ engineers and software architects. You will also unlock access to the source code I use in my YouTube videos, early access to future videos, and exclusive discounts for my courses.

The .NET Weekly

One practical .NET tip, every Saturday.

Join 66,000+ engineers who read it. Free, and you can unsubscribe any time.