diff --git a/docs/articles/nunit/writing-tests/attributes/dependsonfixture.md b/docs/articles/nunit/writing-tests/attributes/dependsonfixture.md index c145283b5..c84b45bd9 100644 --- a/docs/articles/nunit/writing-tests/attributes/dependsonfixture.md +++ b/docs/articles/nunit/writing-tests/attributes/dependsonfixture.md @@ -11,6 +11,14 @@ fixture. By default, the referenced fixture must run and pass before the dependent fixture can run. This can be overridden by setting `AllowFailure` to `true`. +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. + ## Constructor ```csharp diff --git a/docs/articles/nunit/writing-tests/attributes/dependsontest.md b/docs/articles/nunit/writing-tests/attributes/dependsontest.md index 5e64975f1..4ef3ab474 100644 --- a/docs/articles/nunit/writing-tests/attributes/dependsontest.md +++ b/docs/articles/nunit/writing-tests/attributes/dependsontest.md @@ -10,6 +10,15 @@ Added in **NUnit 5.0**. default, the referenced test must run and pass before the dependent test can run. This can be overridden by setting `AllowFailure` to `true`. +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]`](xref:attribute-dependsonfixture) 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. + ## Constructor ```csharp diff --git a/docs/articles/nunit/writing-tests/dependent-tests.md b/docs/articles/nunit/writing-tests/dependent-tests.md index 7029992f6..199b3bbee 100644 --- a/docs/articles/nunit/writing-tests/dependent-tests.md +++ b/docs/articles/nunit/writing-tests/dependent-tests.md @@ -19,6 +19,12 @@ NUnit 5 lets you say this directly with [`[DependsOnTest]`](xref:attribute-depen 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. + [!code-csharp[DependentTests](~/snippets/Snippets.NUnit/WritingTestsGuideExamples.cs#DependentTests)] - `ShipOrder` runs only after `CreateOrder` has finished. If `CreateOrder` fails, `ShipOrder` is **skipped** instead of @@ -32,6 +38,23 @@ When a whole class of tests depends on another class, put [`[DependsOnFixture]`] 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. + +[!code-csharp[DependentFixtures](~/snippets/Snippets.NUnit/DependentFixtureExamples.cs#DependentFixtures)] + +- `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 diff --git a/docs/snippets/Snippets.NUnit/DependentFixtureExamples.cs b/docs/snippets/Snippets.NUnit/DependentFixtureExamples.cs new file mode 100644 index 000000000..b230f7572 --- /dev/null +++ b/docs/snippets/Snippets.NUnit/DependentFixtureExamples.cs @@ -0,0 +1,53 @@ +using NUnit.Framework; + +// Fixture dependencies are resolved between fixtures in the same namespace, +// so these examples have their own namespace. +namespace Snippets.NUnit.DependentFixtures; + +#region DependentFixtures +// State shared between fixtures. Fixture dependencies make the order safe. +public static class CustomerDatabase +{ + public static List 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); + } +} +#endregion diff --git a/docs/snippets/Snippets.NUnit/Snippets.NUnit.csproj b/docs/snippets/Snippets.NUnit/Snippets.NUnit.csproj index 2e7bad256..c5c9ac6fa 100644 --- a/docs/snippets/Snippets.NUnit/Snippets.NUnit.csproj +++ b/docs/snippets/Snippets.NUnit/Snippets.NUnit.csproj @@ -10,7 +10,7 @@ - + all diff --git a/docs/snippets/Snippets.NUnitLite/Snippets.NUnitLite.csproj b/docs/snippets/Snippets.NUnitLite/Snippets.NUnitLite.csproj index b2396bf8b..1c647958a 100644 --- a/docs/snippets/Snippets.NUnitLite/Snippets.NUnitLite.csproj +++ b/docs/snippets/Snippets.NUnitLite/Snippets.NUnitLite.csproj @@ -13,7 +13,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive @@ -23,7 +23,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - +