Tests That Depend on Other Tests
Most tests should be independent: each one sets up what it needs and can run on its own, in any order. Sometimes, though, tests really do depend on each other. An integration test may need an order to exist before it can ship it, or a cleanup step must run after the tests that use a shared resource.
NUnit 5 lets you say this directly with [DependsOnTest] and
[DependsOnFixture].
Note
Test dependencies were added in NUnit 5.0.
Depending on another test
Put [DependsOnTest] on a test, with the name of the test it depends on. Use nameof, so the dependency still works
when the test is renamed.
A test can only depend on another test in the same fixture, including tests the fixture inherits from a base class.
NUnit looks up the name among the tests of that fixture only, so a test in another fixture is not found. There is no way
to depend on a single test in another fixture. Use [DependsOnFixture], described below, to make a whole fixture wait
for all tests in another fixture. A test has at most one [DependsOnTest], but several tests can depend on the same
test. If the named test is not found, the dependent test fails as invalid.
public class OrderWorkflowTests
{
private static readonly List<string> Orders = [];
[Test]
public void CreateOrder()
{
Orders.Add("order-1");
Assert.That(Orders, Has.Count.EqualTo(1));
}
[Test]
[DependsOnTest(nameof(CreateOrder))]
public void ShipOrder()
{
// Runs only after CreateOrder has passed. If CreateOrder fails, this test is skipped.
Assert.That(Orders, Does.Contain("order-1"));
}
[Test]
[DependsOnTest(nameof(ShipOrder), AllowFailure = true)]
public void CleanUpOrders()
{
// Runs after ShipOrder even if it failed, so the cleanup always happens.
Orders.Clear();
Assert.That(Orders, Is.Empty);
}
}
ShipOrderruns only afterCreateOrderhas finished. IfCreateOrderfails,ShipOrderis skipped instead of failing with a confusing error.CleanUpOrderssetsAllowFailure = true, so it runs even ifShipOrderfailed. This is the pattern for cleanup that must always happen.
Depending on another fixture
When a whole class of tests depends on another class, put [DependsOnFixture] on
the class, with the type of the fixture it depends on. It works the same way: the dependent fixture waits for the other
fixture, and is skipped if that fixture fails, unless AllowFailure is set.
The dependency is always the whole fixture: the dependent fixture waits for all tests in it. A fixture can only depend on
another fixture in the same namespace. NUnit looks up the type among the fixtures directly in that namespace only, so a
fixture in a parent, child or other namespace is not found. A fixture has at most one
[DependsOnFixture], but several fixtures can depend on the same fixture. If the named fixture is not found, the
dependent fixture fails as invalid. A fixture can't depend on its own base class.
// State shared between fixtures. Fixture dependencies make the order safe.
public static class CustomerDatabase
{
public static List<string> Customers { get; } = [];
}
public class SeedDatabaseTests
{
[Test]
public void AddCustomers()
{
CustomerDatabase.Customers.AddRange(["Alice", "Bob"]);
Assert.That(CustomerDatabase.Customers, Has.Count.EqualTo(2));
}
}
[DependsOnFixture(typeof(SeedDatabaseTests))]
public class CustomerReportTests
{
// All tests in this fixture run after every test in SeedDatabaseTests.
// If SeedDatabaseTests fails, this whole fixture is skipped.
[Test]
public void Report_ListsAllCustomers()
{
Assert.That(CustomerDatabase.Customers, Is.EquivalentTo(new[] { "Alice", "Bob" }));
}
[Test]
public void Report_HasNoDuplicates()
{
Assert.That(CustomerDatabase.Customers, Is.Unique);
}
}
[DependsOnFixture(typeof(CustomerReportTests), AllowFailure = true)]
public class CleanUpDatabaseTests
{
// Runs after CustomerReportTests even if it failed, so the cleanup always happens.
[Test]
public void RemoveCustomers()
{
CustomerDatabase.Customers.Clear();
Assert.That(CustomerDatabase.Customers, Is.Empty);
}
}
SeedDatabaseTestshas no dependency, so it runs first and fills the sharedCustomerDatabase.CustomerReportTestsstarts only after all tests inSeedDatabaseTestshave finished. If any of them fails, the fixture fails, and every test inCustomerReportTestsis skipped, with a message that names the failed dependency.CleanUpDatabaseTestsdepends onCustomerReportTestswithAllowFailure = true. It runs last, even if a report test failed, so the shared data is always removed.- Dependencies chain:
CleanUpDatabaseTestswaits forCustomerReportTests, which waits forSeedDatabaseTests. When you run only a dependent fixture, for example from your IDE, NUnit still includes the fixture it depends on.
Things to keep in mind
- Tests in a dependency chain can't run in parallel with each other. Don't mark them
[Parallelizable]. - Don't combine dependencies with
[Order]in the same chain.[DependsOnTest]and[DependsOnFixture]replace[Order]for most uses, and[Order]is deprecated. - A circular dependency, or another invalid setup, marks the affected tests as failed, with a message that explains the problem.
See the DependsOnTest and DependsOnFixture reference pages for all the details.