Search Results for

    Show / Hide Table of Contents

    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);
        }
    }
    
    • ShipOrder runs only after CreateOrder has finished. If CreateOrder fails, ShipOrder is skipped instead of failing with a confusing error.
    • CleanUpOrders sets AllowFailure = true, so it runs even if ShipOrder failed. 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);
        }
    }
    
    • SeedDatabaseTests has no dependency, so it runs first and fills the shared CustomerDatabase.
    • CustomerReportTests starts only after all tests in SeedDatabaseTests have finished. If any of them fails, the fixture fails, and every test in CustomerReportTests is skipped, with a message that names the failed dependency.
    • CleanUpDatabaseTests depends on CustomerReportTests with AllowFailure = true. It runs last, even if a report test failed, so the shared data is always removed.
    • Dependencies chain: CleanUpDatabaseTests waits for CustomerReportTests, which waits for SeedDatabaseTests. 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.

    • Edit this page
    In this article
    Back to top Generated by DocFX | Copyright (c) 2018- The NUnit Project - Licensed under CC BY-NC-SA 4.0