From 107e59e8cd5a1ad84dcf58faa8f49e0335f80856 Mon Sep 17 00:00:00 2001 From: Terje Sandstrom Date: Sat, 26 Sep 2026 00:02:53 +0200 Subject: [PATCH 01/11] Add preview of a new card-based landing page Revisits the idea from #1026 with a task-oriented, card-based home page (home.md) that lives next to the classic index.md. Readers can switch between the two; the choice is remembered per browser. No existing documents are moved, so all current URLs keep working. Co-Authored-By: Claude Opus 5.5 --- docs/custom_template/styles/main.css | 136 +++++++++++++++++++- docs/home.md | 186 +++++++++++++++++++++++++++ docs/index.md | 6 + docs/styles/main.js | 19 +++ 4 files changed, 346 insertions(+), 1 deletion(-) create mode 100644 docs/home.md diff --git a/docs/custom_template/styles/main.css b/docs/custom_template/styles/main.css index 92ddd9c42..5c39e15ba 100644 --- a/docs/custom_template/styles/main.css +++ b/docs/custom_template/styles/main.css @@ -9,4 +9,138 @@ div.across ul li float:left; display:block; width:9em -} \ No newline at end of file +} +/* ------------------------------------------------------------------ + New landing page (home.md). Everything is scoped under .nh so the + rest of the site is unaffected. + ------------------------------------------------------------------ */ +.nh { + --nh-green: #005b0c; + --nh-green-dark: #003d08; + --nh-green-soft: #e8f3ea; + --nh-ink: #1b1f23; + --nh-muted: #57606a; + --nh-border: #d8dee4; + --nh-surface: #ffffff; + --nh-radius: 12px; + color: var(--nh-ink); + font-size: 15px; + line-height: 1.55; + margin-bottom: 48px; +} +.nh a { text-decoration: none; } +.nh h1, .nh h2, .nh h3 { font-weight: 600; letter-spacing: -0.01em; } +.nh code { background: var(--nh-green-soft); color: var(--nh-green-dark); padding: 1px 5px; border-radius: 4px; } + +/* Preview banner / layout switch */ +.nh-switch { + display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; + margin: 8px 0 20px; padding: 10px 16px; + border: 1px dashed var(--nh-border); border-radius: var(--nh-radius); + color: var(--nh-muted); font-size: 14px; +} +.nh-switch a { margin-left: auto; font-weight: 600; color: var(--nh-green); } +.nh-badge { + background: var(--nh-green); color: #fff; font-size: 11px; font-weight: 700; + text-transform: uppercase; letter-spacing: .06em; padding: 2px 8px; border-radius: 999px; +} + +/* Hero */ +.nh-hero { + display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); gap: 32px; align-items: center; + padding: 40px; border-radius: 16px; color: #fff; + background: + radial-gradient(circle at 85% 15%, rgba(255, 255, 255, .12), transparent 45%), + linear-gradient(135deg, var(--nh-green-dark) 0%, var(--nh-green) 55%, #0a7a3b 100%); +} +.nh-eyebrow { margin: 0 0 8px; font-size: 13px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; opacity: .8; } +.nh-hero h1 { margin: 0 0 16px; font-size: 40px; line-height: 1.15; color: #fff; } +.nh-lead { font-size: 17px; margin: 0 0 24px; opacity: .92; max-width: 36em; } +.nh-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 24px; } +.nh-btn { + display: inline-block; padding: 9px 18px; border-radius: 8px; font-weight: 600; + color: #fff !important; border: 1px solid rgba(255, 255, 255, .45); transition: background .15s; +} +.nh-btn:hover, .nh-btn:focus { background: rgba(255, 255, 255, .12); } +.nh-btn-primary { background: #fff; border-color: #fff; color: var(--nh-green-dark) !important; } +.nh-btn-primary:hover, .nh-btn-primary:focus { background: var(--nh-green-soft); } +.nh-popular { margin: 0; font-size: 13px; display: flex; flex-wrap: wrap; gap: 6px; align-items: center; } +.nh-popular span { opacity: .75; margin-right: 2px; } +.nh-popular a { + color: #fff; background: rgba(255, 255, 255, .12); padding: 3px 10px; border-radius: 999px; + border: 1px solid rgba(255, 255, 255, .2); +} +.nh-popular a:hover, .nh-popular a:focus { background: rgba(255, 255, 255, .22); } +.nh-hero-code { + background: #fff; border-radius: 10px; overflow: hidden; + box-shadow: 0 18px 40px rgba(0, 0, 0, .25); +} +.nh-code-title { + display: flex; align-items: center; gap: 6px; padding: 8px 12px; + background: #f3f5f7; border-bottom: 1px solid var(--nh-border); color: var(--nh-muted); font-size: 12px; +} +.nh-code-title span { width: 10px; height: 10px; border-radius: 50%; background: #d0d7de; } +.nh-code-title span:nth-child(3) { margin-right: 6px; } +.nh-hero-code { min-width: 0; } +.nh-hero-code pre { overflow-x: auto; word-wrap: normal; white-space: pre; margin: 0; border: 0; border-radius: 0; background: #fff; font-size: 13px; } +.nh-hero-code pre code { white-space: pre; word-wrap: normal; background: none; color: inherit; padding: 0; } + +/* Sections */ +.nh-section { margin-top: 48px; } +.nh-section > h2 { font-size: 24px; margin: 0 0 4px; } +.nh-section-lead { color: var(--nh-muted); margin: 0 0 20px; } +.nh-grid { display: grid; gap: 16px; } +.nh-grid-4 { grid-template-columns: repeat(auto-fill, minmax(min(230px, 100%), 1fr)); } +.nh-grid-3 { grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr)); } +.nh-grid-links { grid-template-columns: repeat(auto-fill, minmax(min(250px, 100%), 1fr)); gap: 12px; } + +/* Cards */ +.nh-card, .nh-panel { + background: var(--nh-surface); border: 1px solid var(--nh-border); border-radius: var(--nh-radius); + padding: 20px; transition: border-color .15s, box-shadow .15s, transform .15s; +} +.nh-card:hover, .nh-card-link:focus { + border-color: var(--nh-green); box-shadow: 0 6px 20px rgba(0, 91, 12, .12); +} +.nh-card-link { display: block; color: inherit !important; } +.nh-card-link:hover { transform: translateY(-2px); } +.nh-card h3 { font-size: 17px; margin: 12px 0 6px; } +.nh-card h3 a, .nh-card-link h3 { color: var(--nh-ink); } +.nh-card p { color: var(--nh-muted); margin: 0 0 12px; } +.nh-card-link p { margin: 0; } +.nh-card ul, .nh-panel ul { list-style: none; padding: 0; margin: 0; } +.nh-card li, .nh-panel li { padding: 3px 0; } +.nh-card li a, .nh-panel li a { color: var(--nh-green); } +.nh-card li a::before, .nh-panel li a::before { content: "\203A"; margin-right: 8px; opacity: .6; } +.nh-card li a:hover, .nh-panel li a:hover { text-decoration: underline; } +.nh-icon { + display: inline-flex; align-items: center; justify-content: center; + width: 40px; height: 40px; border-radius: 10px; background: var(--nh-green-soft); +} +.nh-icon svg { + width: 22px; height: 22px; fill: none; stroke: var(--nh-green); + stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; +} + +/* Reference quick links */ +.nh-link { + display: flex; flex-direction: column; padding: 14px 16px; + border: 1px solid var(--nh-border); border-left: 4px solid var(--nh-green); border-radius: 8px; + color: var(--nh-ink) !important; transition: background .15s; +} +.nh-link:hover, .nh-link:focus { background: var(--nh-green-soft); } +.nh-link span { color: var(--nh-muted); font-size: 13px; } + +/* Bottom panels */ +.nh-split { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr)); gap: 16px; } +.nh-panel { background: #f6f8fa; } +.nh-panel h2 { font-size: 18px; margin: 12px 0 8px; } + +@media (max-width: 991px) { + .nh-hero { grid-template-columns: minmax(0, 1fr); padding: 28px 20px; } + .nh-hero h1 { font-size: 30px; } +} +@media (prefers-reduced-motion: reduce) { + .nh-card, .nh-card-link, .nh-link, .nh-btn { transition: none; } + .nh-card-link:hover { transform: none; } +} diff --git a/docs/home.md b/docs/home.md new file mode 100644 index 000000000..41ca95d24 --- /dev/null +++ b/docs/home.md @@ -0,0 +1,186 @@ +--- +title: NUnit Documentation +_disableAffix: true +_disableContribution: true +_description: Documentation for NUnit, the open-source unit-testing framework for all .NET languages. +--- + + +
+
+Preview +You are looking at the new documentation home page, which is still taking shape. +Switch to the classic home page +
+
+
+

NUnit documentation

+

Unit testing for all .NET languages

+

NUnit is the open-source unit-testing framework for .NET. Here you will find guides and reference documentation for the framework, the test runners, the Visual Studio adapter and the analyzers.

+ + +
+
+
CalculatorTests.cs
+
using NUnit.Framework;
+[TestFixture]
+public class CalculatorTests
+{
+    [TestCase(2, 3, 5)]
+    [TestCase(-1, 1, 0)]
+    public void Add_ReturnsSum(int a, int b, int expected)
+    {
+        var result = new Calculator().Add(a, b);
+        Assert.That(result, Is.EqualTo(expected));
+    }
+}
+
+
+
+

Start here

+

Task-oriented entry points, from your first test to upgrading an existing test suite.

+
+
+ +

Get started

+

Add NUnit to a project and run your first test.

+ +
+
+ +

Write tests

+

Fixtures, attributes, assertions and data-driven tests.

+ +
+
+ +

Run tests

+

In Visual Studio, with dotnet test, or from the console.

+ +
+
+ +

Upgrade

+

Move to a newer NUnit version with confidence.

+ +
+
+
+
+

Reference

+

Look things up quickly.

+ +
+
+

The NUnit family

+

NUnit is more than a framework. Pick the tool you are working with.

+ +
+
+ + + +
+
diff --git a/docs/index.md b/docs/index.md index 95e51e032..9d2f0f704 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,5 +1,11 @@ # NUnit Documentation Site + +> [!TIP] +> We are working on a new home page for these docs. Try the preview, and +> share your feedback in [this discussion](https://github.com/nunit/docs/discussions/1023). + + This web site contains the documentation for all active NUnit projects as well as developer documentation for those working on NUnit or wishing to do so. diff --git a/docs/styles/main.js b/docs/styles/main.js index 6dc4abafd..15ecb0d46 100644 --- a/docs/styles/main.js +++ b/docs/styles/main.js @@ -1,2 +1,21 @@ var currentYear= new Date().getFullYear(); document.getElementById("currentYear").innerHTML = currentYear; + +// Switching between the classic (index.md) and the new (home.md) home page. +// The choice is remembered per browser, so the site root opens the layout the reader picked last. +(function () { + var key = "nunit-docs-home-layout"; + function read() { try { return localStorage.getItem(key); } catch (e) { return null; } } + function write(value) { try { localStorage.setItem(key, value); } catch (e) { } } + + document.addEventListener("click", function (e) { + var link = e.target.closest ? e.target.closest("a[data-nh-layout]") : null; + if (link) write(link.getAttribute("data-nh-layout")); + }); + + var rel = document.querySelector('meta[name="docfx:rel"]'); + var atRoot = rel && rel.getAttribute("content") === "" && /\/(index\.html)?$/.test(location.pathname); + if (atRoot && read() === "new" && !/[?&]classic\b/.test(location.search)) { + location.replace("home.html" + location.hash); + } +})(); From 6cefb638f60ab80890c2d8e1f45c63e15e30094c Mon Sep 17 00:00:00 2001 From: Terje Sandstrom Date: Sat, 26 Sep 2026 00:17:44 +0200 Subject: [PATCH 02/11] Use the #1026 card set and add user-oriented writing-tests guides The landing page now follows the nine cards proposed in #1026, written from the user's point of view: Writing tests (featured), Getting started, News, Run anywhere, NUnit Tech, Articles, Developer info, Advanced and Archive. Contributor material is collected under Developer info. Ports the Writing tests guide pages from #1026 into the existing articles/nunit/writing-tests folder instead of a new folder structure: Ordinary tests, Data driven tests and Automating tests (the last one was empty in #1026 and is new). Code samples live in the tested snippets project. The Writing Tests menu entry now opens the Ordinary tests guide. Co-Authored-By: Claude Opus 5.5 --- docs/articles/nunit/toc.yml | 2 +- .../nunit/writing-tests/automating-tests.md | 58 +++++ .../nunit/writing-tests/data-driven-tests.md | 55 +++++ .../nunit/writing-tests/ordinary-tests.md | 41 ++++ docs/articles/nunit/writing-tests/toc.yml | 6 + docs/custom_template/styles/main.css | 74 +++--- docs/home.md | 210 +++++++++--------- .../WritingTestsGuideExamples.cs | 186 ++++++++++++++++ 8 files changed, 486 insertions(+), 146 deletions(-) create mode 100644 docs/articles/nunit/writing-tests/automating-tests.md create mode 100644 docs/articles/nunit/writing-tests/data-driven-tests.md create mode 100644 docs/articles/nunit/writing-tests/ordinary-tests.md create mode 100644 docs/snippets/Snippets.NUnit/WritingTestsGuideExamples.cs diff --git a/docs/articles/nunit/toc.yml b/docs/articles/nunit/toc.yml index b8131b2fa..1d3cc1742 100644 --- a/docs/articles/nunit/toc.yml +++ b/docs/articles/nunit/toc.yml @@ -14,7 +14,7 @@ topicHref: getting-started/installation.md - name: Writing Tests href: writing-tests/toc.yml - topicHref: writing-tests/attributes.md + topicHref: writing-tests/ordinary-tests.md - name: Running Tests href: running-tests/toc.yml topicHref: running-tests/Index.md diff --git a/docs/articles/nunit/writing-tests/automating-tests.md b/docs/articles/nunit/writing-tests/automating-tests.md new file mode 100644 index 000000000..617dee4b9 --- /dev/null +++ b/docs/articles/nunit/writing-tests/automating-tests.md @@ -0,0 +1,58 @@ +--- +uid: automatingtests +--- + +# Automating Tests + +With [data driven tests](xref:datadriventests) you write out every test case yourself. NUnit can also do that work for +you: you describe the possible values for each parameter, and NUnit generates the test cases. This is a good way to +cover many inputs with very little code. + +## Every combination with [Values] + +Put [`[Values]`](xref:attribute-values) on each parameter. By default NUnit runs the test once for every combination +of the values, so the example below produces 3 × 2 = 6 test cases. + +[!code-csharp[AutomatingCombinatorial](~/snippets/Snippets.NUnit/WritingTestsGuideExamples.cs#AutomatingCombinatorial)] + +For `bool` and `enum` parameters you can leave out the values: `[Values] bool flag` gives you both `true` and +`false`. + +## A range of numbers with [Range] + +Use [`[Range]`](xref:attribute-range) to generate numbers from a start value to an end value, with an optional step. +This example runs with -10, -5, 0, 5 and 10. + +[!code-csharp[AutomatingRange](~/snippets/Snippets.NUnit/WritingTestsGuideExamples.cs#AutomatingRange)] + +## Random numbers with [Random] + +Use [`[Random]`](xref:attribute-random) to have NUnit pick values for you. This is useful for checking rules that must +hold for *any* input, such as `a + b == b + a`. NUnit records the random seed it used in the test results, so a failing run can be reproduced. + +[!code-csharp[AutomatingRandom](~/snippets/Snippets.NUnit/WritingTestsGuideExamples.cs#AutomatingRandom)] + +## Keeping the number of tests down + +Combinations grow fast: three parameters with ten values each give a thousand test cases. NUnit has two attributes that +change how the values are combined: + +- [`[Pairwise]`](xref:attribute-pairwise) generates just enough cases so that every *pair* of values is tested + together at least once. Most bugs are caused by one value or by two values together, so this finds most of them + with far fewer tests. +- [`[Sequential]`](xref:attribute-sequential) uses the first value of each parameter together, then the second values, + and so on, instead of all combinations. + +[!code-csharp[AutomatingPairwise](~/snippets/Snippets.NUnit/WritingTestsGuideExamples.cs#AutomatingPairwise)] + +## Theories + +A [`[Theory]`](xref:attribute-theory) goes one step further: you state something that must be true for all data +points, and NUnit tries it with every suitable value you have marked with [`[Datapoint]`](xref:attribute-datapoint) +or [`[DatapointSource]`](xref:attribute-datapointsource). + +## Next steps + +- [Combinatorial](xref:attribute-combinatorial), [Pairwise](xref:attribute-pairwise) and + [Sequential](xref:attribute-sequential) describe the combining strategies in detail. +- [Parameterized tests](xref:parameterizedtests) describes all the details of how parameterized tests work. diff --git a/docs/articles/nunit/writing-tests/data-driven-tests.md b/docs/articles/nunit/writing-tests/data-driven-tests.md new file mode 100644 index 000000000..481f4dffc --- /dev/null +++ b/docs/articles/nunit/writing-tests/data-driven-tests.md @@ -0,0 +1,55 @@ +--- +uid: datadriventests +--- + +# Data Driven Tests + +A data driven test runs the same test code several times, with different input data each time. Instead of copying a +test to try another value, you write the test once and give NUnit the list of values. Each set of values shows up as +its own test in the test explorer, so you can see exactly which case failed. + +NUnit calls these *parameterized tests*: the test method takes parameters, and the data is supplied from outside. + +## Inline data with [TestCase] + +Use [`[TestCase]`](xref:attribute-testcase) when you have a handful of cases that are easy to write out. Each +attribute is one test case, and its arguments are passed to the method parameters in order. + +[!code-csharp[DataDrivenTestCase](~/snippets/Snippets.NUnit/WritingTestsGuideExamples.cs#DataDrivenTestCase)] + +If the test simply computes a value, you can let the method return it and put the expected value in the attribute +with `ExpectedResult`: + +[!code-csharp[DataDrivenExpectedResult](~/snippets/Snippets.NUnit/WritingTestsGuideExamples.cs#DataDrivenExpectedResult)] + +## Data from code with [TestCaseSource] + +Use [`[TestCaseSource]`](xref:attribute-testcasesource) when the data is larger, needs code to build, or comes from +somewhere else, such as a file. Point the attribute at a static method, property or field that returns the cases. + +[!code-csharp[DataDrivenTestCaseSource](~/snippets/Snippets.NUnit/WritingTestsGuideExamples.cs#DataDrivenTestCaseSource)] + +Returning [`TestCaseData`](xref:testcasedata) objects is optional, but it lets you give each case a readable name, a +description, categories and more. + +## Data for a single parameter with [ValueSource] + +Use [`[ValueSource]`](xref:attribute-valuesource) when you want to supply the values for one parameter from a +reusable list. + +[!code-csharp[DataDrivenValueSource](~/snippets/Snippets.NUnit/WritingTestsGuideExamples.cs#DataDrivenValueSource)] + +## Running a whole class with different data + +You can also pass data to the test class itself. Every test in the class then runs once for each set of arguments given +with [`[TestFixture]`](xref:attribute-testfixture). + +[!code-csharp[DataDrivenFixture](~/snippets/Snippets.NUnit/WritingTestsGuideExamples.cs#DataDrivenFixture)] + +For data built in code, use [`[TestFixtureSource]`](xref:attribute-testfixturesource) and +[`TestFixtureData`](xref:testfixturedata). + +## Next steps + +- [Automating tests](xref:automatingtests) lets NUnit generate combinations of values for you. +- [Parameterized tests](xref:parameterizedtests) describes all the details of how parameterized tests work. diff --git a/docs/articles/nunit/writing-tests/ordinary-tests.md b/docs/articles/nunit/writing-tests/ordinary-tests.md new file mode 100644 index 000000000..bacdc7893 --- /dev/null +++ b/docs/articles/nunit/writing-tests/ordinary-tests.md @@ -0,0 +1,41 @@ +--- +uid: ordinarytests +--- + +# Ordinary Tests + +Most of the tests you write will be *ordinary* tests: a method that sets something up, does one thing and checks the +result. This page shows what such a test looks like in NUnit, and where to go from there. + +## Your first test + +A test is a public method marked with the [`[Test]`](xref:attribute-test) attribute, inside a public class. The class +is called a *test fixture*. + +[!code-csharp[OrdinaryTest](~/snippets/Snippets.NUnit/WritingTestsGuideExamples.cs#OrdinaryTest)] + +The test follows the common **Arrange, Act, Assert** pattern: + +- **Arrange** creates the object you want to test, often called the *system under test*. +- **Act** calls the method you want to test. +- **Assert** checks that the result is what you expected. `Assert.That` takes the actual value and a *constraint* + that describes the expected value, such as `Is.EqualTo(5)`. + +If the assertion fails, NUnit reports the test as failed and shows both the expected and the actual value. + +## Sharing setup between tests + +When several tests need the same starting point, move the common code into a method marked with +[`[SetUp]`](xref:attribute-setup). NUnit runs it before each test in the class, so every test gets a fresh object. + +[!code-csharp[OrdinarySetUp](~/snippets/Snippets.NUnit/WritingTestsGuideExamples.cs#OrdinarySetUp)] + +Use [`[TearDown]`](xref:attribute-teardown) for cleanup after each test, and +[`[OneTimeSetUp]`](xref:attribute-onetimesetup) for expensive setup that should run only once for the whole class. + +## Next steps + +- [Data driven tests](xref:datadriventests) run the same test with different inputs. +- [Automating tests](xref:automatingtests) lets NUnit generate the inputs for you. +- [Constraints](xref:constraints) lists everything you can check with `Assert.That`. +- [Attributes](attributes.md) describes all the ways you can mark and control tests. diff --git a/docs/articles/nunit/writing-tests/toc.yml b/docs/articles/nunit/writing-tests/toc.yml index cfc1cf8bb..92ddb1db8 100644 --- a/docs/articles/nunit/writing-tests/toc.yml +++ b/docs/articles/nunit/writing-tests/toc.yml @@ -1,3 +1,9 @@ +- name: Ordinary Tests + href: ordinary-tests.md +- name: Data Driven Tests + href: data-driven-tests.md +- name: Automating Tests + href: automating-tests.md - name: Attributes href: attributes.md - name: Attribute Descriptions diff --git a/docs/custom_template/styles/main.css b/docs/custom_template/styles/main.css index 5c39e15ba..a1f4ada14 100644 --- a/docs/custom_template/styles/main.css +++ b/docs/custom_template/styles/main.css @@ -86,61 +86,67 @@ div.across ul li .nh-hero-code pre code { white-space: pre; word-wrap: normal; background: none; color: inherit; padding: 0; } /* Sections */ -.nh-section { margin-top: 48px; } -.nh-section > h2 { font-size: 24px; margin: 0 0 4px; } -.nh-section-lead { color: var(--nh-muted); margin: 0 0 20px; } +.nh-section { margin-top: 40px; } .nh-grid { display: grid; gap: 16px; } -.nh-grid-4 { grid-template-columns: repeat(auto-fill, minmax(min(230px, 100%), 1fr)); } -.nh-grid-3 { grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr)); } -.nh-grid-links { grid-template-columns: repeat(auto-fill, minmax(min(250px, 100%), 1fr)); gap: 12px; } +.nh-grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); grid-auto-flow: row dense; } /* Cards */ -.nh-card, .nh-panel { +.nh-card { background: var(--nh-surface); border: 1px solid var(--nh-border); border-radius: var(--nh-radius); - padding: 20px; transition: border-color .15s, box-shadow .15s, transform .15s; + padding: 20px; transition: border-color .15s, box-shadow .15s; } -.nh-card:hover, .nh-card-link:focus { +.nh-card:hover, .nh-card:focus-within { border-color: var(--nh-green); box-shadow: 0 6px 20px rgba(0, 91, 12, .12); } -.nh-card-link { display: block; color: inherit !important; } -.nh-card-link:hover { transform: translateY(-2px); } -.nh-card h3 { font-size: 17px; margin: 12px 0 6px; } -.nh-card h3 a, .nh-card-link h3 { color: var(--nh-ink); } +.nh-card h2 { font-size: 18px; margin: 12px 0 4px; } +.nh-card h2 a { color: var(--nh-ink); } +.nh-card h2 a:hover { color: var(--nh-green); } +.nh-card h3 { + font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; + color: var(--nh-muted); margin: 16px 0 6px; +} .nh-card p { color: var(--nh-muted); margin: 0 0 12px; } -.nh-card-link p { margin: 0; } -.nh-card ul, .nh-panel ul { list-style: none; padding: 0; margin: 0; } -.nh-card li, .nh-panel li { padding: 3px 0; } -.nh-card li a, .nh-panel li a { color: var(--nh-green); } -.nh-card li a::before, .nh-panel li a::before { content: "\203A"; margin-right: 8px; opacity: .6; } -.nh-card li a:hover, .nh-panel li a:hover { text-decoration: underline; } +.nh-card ul { list-style: none; padding: 0; margin: 0; } +.nh-card li { padding: 3px 0; } +.nh-card li a { color: var(--nh-green); } +.nh-card li a::before { content: "\203A"; margin-right: 8px; opacity: .6; } +.nh-card li a:hover { text-decoration: underline; } + +/* Writing tests is the main message, so it gets the tall, highlighted card */ +.nh-card-featured { + grid-row: span 2; border: 2px solid var(--nh-green); + background: linear-gradient(180deg, var(--nh-green-soft) 0%, var(--nh-surface) 55%); +} +.nh-card-featured h2 { font-size: 22px; } +.nh-card-featured > ul:first-of-type li { padding: 5px 0; font-size: 16px; font-weight: 600; } + .nh-icon { display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px; border-radius: 10px; background: var(--nh-green-soft); } +.nh-card-featured .nh-icon { background: var(--nh-green); } +.nh-card-featured .nh-icon svg { stroke: #fff; } .nh-icon svg { width: 22px; height: 22px; fill: none; stroke: var(--nh-green); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; } -/* Reference quick links */ -.nh-link { - display: flex; flex-direction: column; padding: 14px 16px; - border: 1px solid var(--nh-border); border-left: 4px solid var(--nh-green); border-radius: 8px; - color: var(--nh-ink) !important; transition: background .15s; -} -.nh-link:hover, .nh-link:focus { background: var(--nh-green-soft); } -.nh-link span { color: var(--nh-muted); font-size: 13px; } - -/* Bottom panels */ -.nh-split { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr)); gap: 16px; } -.nh-panel { background: #f6f8fa; } -.nh-panel h2 { font-size: 18px; margin: 12px 0 8px; } +.nh-community { margin-top: 32px; text-align: center; color: var(--nh-muted); } +.nh-community a { color: var(--nh-green); font-weight: 600; } @media (max-width: 991px) { .nh-hero { grid-template-columns: minmax(0, 1fr); padding: 28px 20px; } .nh-hero h1 { font-size: 30px; } + .nh-grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); } +} +@media (max-width: 600px) { + .nh-grid-3 { grid-template-columns: minmax(0, 1fr); } + .nh-card-featured { grid-row: auto; } } @media (prefers-reduced-motion: reduce) { - .nh-card, .nh-card-link, .nh-link, .nh-btn { transition: none; } - .nh-card-link:hover { transform: none; } + .nh-card, .nh-btn { transition: none; } } + +/* Archive: a low-key, full-width strip at the bottom */ +.nh-card-wide { grid-column: 1 / -1; background: #f6f8fa; } +.nh-card-wide ul { columns: 3 220px; column-gap: 24px; } diff --git a/docs/home.md b/docs/home.md index 41ca95d24..3bc15cbaa 100644 --- a/docs/home.md +++ b/docs/home.md @@ -8,8 +8,10 @@ _description: Documentation for NUnit, the open-source unit-testing framework fo
@@ -20,25 +22,24 @@ _description: Documentation for NUnit, the open-source unit-testing framework fo

NUnit documentation

-

Unit testing for all .NET languages

-

NUnit is the open-source unit-testing framework for .NET. Here you will find guides and reference documentation for the framework, the test runners, the Visual Studio adapter and the analyzers.

+

Write tests you can trust, for any .NET code

+

NUnit is the open-source unit-testing framework for .NET. Write a test in a few lines, run it with many sets of data, and run it anywhere: in Visual Studio, Rider, VS Code, on the command line or in your build pipeline.

CalculatorTests.cs
using NUnit.Framework;
-[TestFixture]
 public class CalculatorTests
 {
     [TestCase(2, 3, 5)]
@@ -51,136 +52,123 @@ public class CalculatorTests
 }
-
-

Start here

-

Task-oriented entry points, from your first test to upgrading an existing test suite.

-
+
+
+
-

Get started

-

Add NUnit to a project and run your first test.

+

Getting started

+

Add NUnit to your project, or move to a newer version.

- -

Write tests

-

Fixtures, attributes, assertions and data-driven tests.

+ +

News

+

What is new in NUnit and its tools.

- -

Run tests

-

In Visual Studio, with dotnet test, or from the console.

+ +

Run anywhere

+

Run your tests in the IDE, on the command line or in your build.

- -

Upgrade

-

Move to a newer NUnit version with confidence.

+ +

NUnit Tech

+

How NUnit and its tools work under the hood.

+ -
-
-

Reference

-

Look things up quickly.

- -
-
-

The NUnit family

-

NUnit is more than a framework. Pick the tool you are working with.

- -
-
-
+

Questions? Ask in GitHub Discussions · NUnit on GitHub · Help improve these docs

diff --git a/docs/snippets/Snippets.NUnit/WritingTestsGuideExamples.cs b/docs/snippets/Snippets.NUnit/WritingTestsGuideExamples.cs new file mode 100644 index 000000000..f051c4f87 --- /dev/null +++ b/docs/snippets/Snippets.NUnit/WritingTestsGuideExamples.cs @@ -0,0 +1,186 @@ +using NUnit.Framework; + +#pragma warning disable CA1822 + +namespace Snippets.NUnit; + +public class WritingTestsGuideExamples +{ + public class Calculator + { + public int Add(int a, int b) => a + b; + public int Multiply(int a, int b) => a * b; + } + + #region OrdinaryTest + public class CalculatorTests + { + [Test] + public void Add_TwoNumbers_ReturnsSum() + { + // Arrange + var calculator = new Calculator(); + + // Act + var result = calculator.Add(2, 3); + + // Assert + Assert.That(result, Is.EqualTo(5)); + } + } + #endregion + + #region OrdinarySetUp + public class CalculatorTestsWithSetUp + { + private Calculator _calculator = null!; + + [SetUp] + public void CreateCalculator() + { + _calculator = new Calculator(); + } + + [Test] + public void Add_ReturnsSum() + { + Assert.That(_calculator.Add(2, 3), Is.EqualTo(5)); + } + + [Test] + public void Multiply_ReturnsProduct() + { + Assert.That(_calculator.Multiply(2, 3), Is.EqualTo(6)); + } + } + #endregion + + #region DataDrivenTestCase + public class AddTests + { + [TestCase(1, 2, 3)] + [TestCase(2, 3, 5)] + [TestCase(-1, 1, 0)] + public void Add_ReturnsSum(int a, int b, int expected) + { + var result = new Calculator().Add(a, b); + Assert.That(result, Is.EqualTo(expected)); + } + } + #endregion + + #region DataDrivenExpectedResult + public class AddTestsWithExpectedResult + { + [TestCase(1, 2, ExpectedResult = 3)] + [TestCase(2, 3, ExpectedResult = 5)] + public int Add_ReturnsSum(int a, int b) + { + return new Calculator().Add(a, b); + } + } + #endregion + + #region DataDrivenTestCaseSource + public class AddTestsFromSource + { + private static IEnumerable AddCases() + { + yield return new TestCaseData(1, 2, 3).SetName("Small numbers"); + yield return new TestCaseData(1000, 2000, 3000).SetName("Large numbers"); + yield return new TestCaseData(-5, 5, 0).SetDescription("Opposites cancel out"); + } + + [TestCaseSource(nameof(AddCases))] + public void Add_ReturnsSum(int a, int b, int expected) + { + Assert.That(new Calculator().Add(a, b), Is.EqualTo(expected)); + } + } + #endregion + + #region DataDrivenValueSource + public class MultiplyByOneTests + { + private static readonly int[] Numbers = [0, 1, 42, -7]; + + [Test] + public void Multiply_ByOne_ReturnsSameNumber([ValueSource(nameof(Numbers))] int number) + { + Assert.That(new Calculator().Multiply(number, 1), Is.EqualTo(number)); + } + } + #endregion + + #region DataDrivenFixture + [TestFixture(2)] + [TestFixture(10)] + public class MultiplierTests(int multiplier) + { + [Test] + public void Multiply_ByZero_ReturnsZero() + { + Assert.That(new Calculator().Multiply(multiplier, 0), Is.Zero); + } + + [Test] + public void Multiply_ByOne_ReturnsMultiplier() + { + Assert.That(new Calculator().Multiply(multiplier, 1), Is.EqualTo(multiplier)); + } + } + #endregion + + #region AutomatingCombinatorial + public class AddIsCommutativeTests + { + [Test] + public void Add_IsCommutative([Values(-1, 0, 1)] int a, [Values(2, 3)] int b) + { + var calculator = new Calculator(); + Assert.That(calculator.Add(a, b), Is.EqualTo(calculator.Add(b, a))); + } + } + #endregion + + #region AutomatingRange + public class AddZeroTests + { + [Test] + public void Add_Zero_ReturnsSameNumber([Range(-10, 10, 5)] int number) + { + Assert.That(new Calculator().Add(number, 0), Is.EqualTo(number)); + } + } + #endregion + + #region AutomatingRandom + public class AddRandomTests + { + [Test] + public void Add_IsCommutative_ForRandomNumbers( + [Random(-1000, 1000, 5)] int a, + [Random(-1000, 1000, 5)] int b) + { + var calculator = new Calculator(); + Assert.That(calculator.Add(a, b), Is.EqualTo(calculator.Add(b, a))); + } + } + #endregion + + #region AutomatingPairwise + public class FormattingTests + { + [Test, Pairwise] + public void Format_HandlesAllOptions( + [Values("en-US", "nb-NO", "ja-JP")] string culture, + [Values(0, 1, -1)] int number, + [Values(true, false)] bool useGrouping) + { + var format = useGrouping ? "N0" : "D"; + var text = number.ToString(format, new System.Globalization.CultureInfo(culture)); + Assert.That(text, Is.Not.Empty); + } + } + #endregion +} From 57171bfa6beabce262477d69aa2be2ec0e2fe2a6 Mon Sep 17 00:00:00 2001 From: Terje Sandstrom Date: Sat, 26 Sep 2026 14:05:30 +0200 Subject: [PATCH 03/11] Clarify the Fluent assertions label on the new home page Co-Authored-By: Claude Opus 5.5 --- docs/home.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/home.md b/docs/home.md index 3bc15cbaa..b6f275399 100644 --- a/docs/home.md +++ b/docs/home.md @@ -66,7 +66,7 @@ public class CalculatorTests

Reference

From 22eb244a9490d8f1f3f4b8eb5a9dad43f4db5cf1 Mon Sep 17 00:00:00 2001 From: Terje Sandstrom Date: Sat, 26 Sep 2026 22:17:32 +0200 Subject: [PATCH 04/11] Prepare the home page for the NUnit 5 launch and add the analyzers - News links the release notes of every component, starting with what's new in NUnit 5; the NUnit Analyzers and the console/engine link to their GitHub release notes. - Getting started lists each way to start: Visual Studio, VS Code, Rider, the command line or an existing project, plus upgrading to NUnit 5. - The NUnit Analyzers are part of the message, the popular topics and the writing-tests reference. - Breaking changes up to 4.0, the NUnit 4 migration guide and the old upgrade guide move to the Archive. Co-Authored-By: Claude Opus 5.5 --- docs/home.md | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/docs/home.md b/docs/home.md index b6f275399..24a3821d1 100644 --- a/docs/home.md +++ b/docs/home.md @@ -23,18 +23,19 @@ _description: Documentation for NUnit, the open-source unit-testing framework fo

NUnit documentation

Write tests you can trust, for any .NET code

-

NUnit is the open-source unit-testing framework for .NET. Write a test in a few lines, run it with many sets of data, and run it anywhere: in Visual Studio, Rider, VS Code, on the command line or in your build pipeline.

+

NUnit is the open-source unit-testing framework for .NET. Write a test in a few lines, get warnings about mistakes as you type from the NUnit Analyzers, run it with many sets of data, and run it anywhere: in Visual Studio, Rider, VS Code, on the command line or in your build pipeline.

@@ -69,28 +70,34 @@ public class CalculatorTests
  • Fluent assertions (Assert.That)
  • Classic assertions
  • Special assertions
  • +
  • Analyzer rules
  • Getting started

    -

    Add NUnit to your project, or move to a newer version.

    +

    Create a test project in the tool you already use, or add NUnit to an existing one.

    @@ -163,6 +170,9 @@ public class CalculatorTests
    • NUnit 2.x documentation
    • Release notes before 3.5
    • +
    • Breaking changes up to NUnit 4.0
    • +
    • Migrating to NUnit 4
    • +
    • Upgrading from NUnit 2 and 3
    • .NET Core and .NET Standard
    • Test adapter V3 release notes
    • Test adapter V2 release notes
    • From e1ab6f17465ff87503a1b57525523b9b1bc48b6c Mon Sep 17 00:00:00 2001 From: Terje Sandstrom Date: Sat, 26 Sep 2026 22:24:38 +0200 Subject: [PATCH 05/11] Point console and engine release notes to GitHub, archive Xamarin runners - New page for the console and engine release notes, pointing to the GitHub releases, which have the notes from 3.18.0 on. The notes up to 3.17 stay at their URL but are only linked from the new page. - The home page News card links the new page. - The Xamarin runners (archived on GitHub in 2022) move from Run anywhere to the Archive. Co-Authored-By: Claude Opus 5.5 --- docs/articles/nunit-engine/github-release-notes.md | 14 ++++++++++++++ docs/articles/nunit-engine/release-notes.md | 4 ++++ docs/articles/nunit-engine/toc.yml | 4 ++-- docs/articles/nunit/release-notes/toc.yml | 2 +- docs/home.md | 4 ++-- 5 files changed, 23 insertions(+), 5 deletions(-) create mode 100644 docs/articles/nunit-engine/github-release-notes.md diff --git a/docs/articles/nunit-engine/github-release-notes.md b/docs/articles/nunit-engine/github-release-notes.md new file mode 100644 index 000000000..9f5302dbf --- /dev/null +++ b/docs/articles/nunit-engine/github-release-notes.md @@ -0,0 +1,14 @@ +--- +uid: consoleenginegithubreleasenotes +--- + +# Console and Engine Release Notes + +From version 3.18.0, the release notes for the NUnit Console and Engine are published with each release on GitHub: + +**[NUnit Console and Engine releases on GitHub](https://github.com/nunit/nunit-console/releases)** + +Each release there lists the issues that were fixed and links to the downloads, including the NUnit Console and +Engine 4.0 pre-releases. + +For version 3.17.0 and earlier, see the [release notes up to 3.17](xref:consoleenginereleasenotes). diff --git a/docs/articles/nunit-engine/release-notes.md b/docs/articles/nunit-engine/release-notes.md index 0bbc806e9..16d96cd7c 100644 --- a/docs/articles/nunit-engine/release-notes.md +++ b/docs/articles/nunit-engine/release-notes.md @@ -6,6 +6,10 @@ uid: consoleenginereleasenotes # Console and Engine Release Notes +> [!NOTE] +> This page covers version 3.17.0 and earlier. The release notes for later versions are published on GitHub, see +> [Console and Engine Release Notes](xref:consoleenginegithubreleasenotes). + ## NUnit Console & Engine 3.17.0 - January 4, 2024 This release adds support for .net 8 by adding a missing agent. diff --git a/docs/articles/nunit-engine/toc.yml b/docs/articles/nunit-engine/toc.yml index 98d7a3938..9a40f64f6 100644 --- a/docs/articles/nunit-engine/toc.yml +++ b/docs/articles/nunit-engine/toc.yml @@ -7,5 +7,5 @@ - name: Engine Extensions href: extensions/toc.yml topicHref: extensions/Index.md -- name: Release Notes - href: release-notes.md +- name: Release Notes + href: github-release-notes.md diff --git a/docs/articles/nunit/release-notes/toc.yml b/docs/articles/nunit/release-notes/toc.yml index b5f1190ef..263be9839 100644 --- a/docs/articles/nunit/release-notes/toc.yml +++ b/docs/articles/nunit/release-notes/toc.yml @@ -1,7 +1,7 @@ - name: Framework href: framework.md - name: Console and Engine - topicUid: consoleenginereleasenotes + topicUid: consoleenginegithubreleasenotes - name: Migration Guidance topicUid: migrationguidance - name: Breaking Changes diff --git a/docs/home.md b/docs/home.md index 24a3821d1..49a3d45b0 100644 --- a/docs/home.md +++ b/docs/home.md @@ -96,7 +96,7 @@ public class CalculatorTests
    • NUnit framework
    • Test adapter
    • NUnit Analyzers
    • -
    • Console and engine
    • +
    • Console and engine
    • VS Test Generator
    @@ -108,7 +108,6 @@ public class CalculatorTests
  • Visual Studio, Rider and dotnet test
  • Command line console
  • Self-running test programs
  • -
  • Mobile devices
  • Choosing which tests to run
  • @@ -174,6 +173,7 @@ public class CalculatorTests
  • Migrating to NUnit 4
  • Upgrading from NUnit 2 and 3
  • .NET Core and .NET Standard
  • +
  • Xamarin runners for mobile devices
  • Test adapter V3 release notes
  • Test adapter V2 release notes
  • From d28886d0d656003ec4dc4f2b0d94879c7789e9c4 Mon Sep 17 00:00:00 2001 From: Terje Sandstrom Date: Sun, 27 Sep 2026 14:36:42 +0200 Subject: [PATCH 06/11] Place the remaining documentation on the new landing page Implements the decision-free parts of the plan posted on #1246. - Three new user guides under Writing Tests, with tested snippets: tests that depend on other tests, flaky and slow tests, and organizing and selecting tests. - Landing page cards link Microsoft.Testing.Platform, .runsettings, multiple asserts, assumptions, warnings, TestContext, supported .NET versions, known problems, execution hooks, specifications, NUnit internals and a new Packaging index. The Articles link to the adapter debugging page is relabelled "Troubleshooting the test adapter". - New Archive page and a single Archive menu section. Deprecated and historical pages move there from their menus; no files are moved. - Cross-links so each page is one click from a card. - NUnit license copyright line synced with the nunit repository. Co-Authored-By: Claude Opus 5.5 --- docs/articles/archive.md | 46 ++++++ docs/articles/developer-info/Packaging.md | 14 ++ docs/articles/developer-info/toc.yml | 8 +- docs/articles/nunit-engine/Index.md | 3 +- docs/articles/nunit/getting-started/toc.yml | 7 +- docs/articles/nunit/license.md | 2 +- docs/articles/nunit/release-notes/toc.yml | 6 - .../nunit/running-tests/Console-Runner.md | 2 + .../nunit/running-tests/NUnitLite-Runner.md | 2 + .../technical-notes/nunit-internals/toc.yml | 2 - .../usage/Trace-and-Debug-Output.md | 3 + .../technical-notes/usage/Usage-Notes.md | 3 +- .../nunit/technical-notes/usage/toc.yml | 4 - docs/articles/nunit/toc.yml | 4 - .../nunit/writing-tests/automating-tests.md | 3 + .../nunit/writing-tests/data-driven-tests.md | 3 +- .../nunit/writing-tests/dependent-tests.md | 45 ++++++ .../writing-tests/flaky-and-slow-tests.md | 63 ++++++++ .../nunit/writing-tests/ordinary-tests.md | 1 + .../nunit/writing-tests/organizing-tests.md | 62 ++++++++ docs/articles/nunit/writing-tests/toc.yml | 10 +- docs/articles/toc.yml | 61 +++++++- docs/articles/vs-test-adapter/Debugging.md | 3 + docs/articles/vs-test-adapter/Index.md | 4 +- docs/articles/vs-test-adapter/toc.yml | 4 - docs/articles/vs-test-generator/toc.yml | 6 +- docs/home.md | 46 ++++-- .../WritingTestsGuideExamples.cs | 142 ++++++++++++++++++ 28 files changed, 490 insertions(+), 69 deletions(-) create mode 100644 docs/articles/archive.md create mode 100644 docs/articles/developer-info/Packaging.md create mode 100644 docs/articles/nunit/writing-tests/dependent-tests.md create mode 100644 docs/articles/nunit/writing-tests/flaky-and-slow-tests.md create mode 100644 docs/articles/nunit/writing-tests/organizing-tests.md diff --git a/docs/articles/archive.md b/docs/articles/archive.md new file mode 100644 index 000000000..d5c479bc8 --- /dev/null +++ b/docs/articles/archive.md @@ -0,0 +1,46 @@ +--- +uid: archive +--- + +# Archive + +These pages describe older versions of NUnit, features that were removed or deprecated, and tools that are no longer +maintained. They are kept for reference, and for anyone still working with older versions. + +For the current version, start at the [documentation home page](../home.md). + +## Older versions of NUnit + +* [NUnit 2.x documentation](xref:legacydocs) +* [Release notes before NUnit 3.5](xref:pre35releasenotes) +* [Breaking changes up to NUnit 4.0](xref:breakingchanges) +* [Migrating to NUnit 4](xref:migrationguidance) +* [Upgrading from NUnit 2 and 3](nunit/getting-started/upgrading.md) +* [Towards NUnit 4](xref:towardsnunit4) +* [.NET Core and .NET Standard](nunit/getting-started/dotnet-core-and-dotnet-standard.md) + +## Deprecated and removed features + +* [AssertionHelper](nunit/writing-tests/AssertionHelper.md), deprecated in NUnit 3.7 +* [ListMapper](nunit/writing-tests/ListMapper.md), removed in NUnit 4.0 +* [Addin Replacement in the Framework](xref:addinreplacementintheframework), the move away from NUnit 2 add-ins +* [Visual Studio Support](xref:visualstudiosupport), for Visual Studio 2003 and 2005 and the NUnit 2 GUI + +## Tools that are no longer maintained + +* [NUnit Xamarin Runners](xref:xamarinrunners) +* [NUnit Project Editor](https://github.com/nunit-legacy/nunit-project-editor/wiki/Project-Editor) + +## Older release notes + +* [Test Adapter V3 release notes](vs-test-adapter/AdapterV3-Release-Notes.md) +* [Test Adapter V2 release notes](vs-test-adapter/AdapterV2-Release-Notes.md) +* [Test Generator release notes for Visual Studio 2017 and 2019](vs-test-generator/TestGenerator-Release-Notes-VS2017-VS2019.md) +* [Test Generator release notes for Visual Studio 2015](vs-test-generator/TestGenerator-Release-Notes-VS2015.md) + +## Developer history + +* [Notes Toward NUnit 4.0](developer-info/Notes-Toward-NUnit-4.0.md) +* [NUnit 3.0 Architecture (2009)](xref:nunit3architecture2009) +* [Packaging the V2 Adapter](developer-info/Packaging-the-V2-Adapter.md) +* [Packaging the Installer](developer-info/Packaging-the-Installer.md), for the MSI installer that is no longer produced diff --git a/docs/articles/developer-info/Packaging.md b/docs/articles/developer-info/Packaging.md new file mode 100644 index 000000000..99c73977f --- /dev/null +++ b/docs/articles/developer-info/Packaging.md @@ -0,0 +1,14 @@ +--- +uid: packaging +--- + +# Packaging + +These pages describe how the NUnit team packages and releases each component. + +* [Packaging the Framework](Packaging-the-Framework.md) +* [Packaging the Console and Engine](Packaging-the-Console-and-Engine.md) +* [Packaging the V3/V4 Adapter](Packaging-the-V3-and-V4-Adapter.md) +* [Packaging Extensions](Packaging-Extensions.md) + +Instructions for packaging the V2 adapter and the MSI installer are in the [Archive](xref:archive). diff --git a/docs/articles/developer-info/toc.yml b/docs/articles/developer-info/toc.yml index 2f6f42703..f578cc680 100644 --- a/docs/articles/developer-info/toc.yml +++ b/docs/articles/developer-info/toc.yml @@ -4,8 +4,6 @@ href: Team-Practices.md - name: Specifications topicUid: specifications -- name: Notes Toward NUnit 4.0 - href: Notes-Toward-NUnit-4.0.md - name: Best Practices for XML Documentation href: Best-practices-for-XML-documentation.md - name: Coding Standards @@ -14,15 +12,13 @@ href: Contributions.md - name: Issue Tracking href: Issue-Tracking.md +- name: Packaging + href: Packaging.md - name: Packaging Extensions href: Packaging-Extensions.md - name: Packaging the Console and Engine href: Packaging-the-Console-and-Engine.md - name: Packaging the Framework href: Packaging-the-Framework.md -- name: Packaging the Installer - href: Packaging-the-Installer.md -- name: Packaging the V2 Adapter - href: Packaging-the-V2-Adapter.md - name: Packaging the V3/V4 Adapter href: Packaging-the-V3-and-V4-Adapter.md diff --git a/docs/articles/nunit-engine/Index.md b/docs/articles/nunit-engine/Index.md index bfba78136..13b625bc4 100644 --- a/docs/articles/nunit-engine/Index.md +++ b/docs/articles/nunit-engine/Index.md @@ -13,6 +13,7 @@ engine and run tests as required. > rather than using one of the many existing test runners in the ecosystem. If you are looking to simply run tests that > you have written, see the [running tests](xref:runningtests) section. -The engine exposes [an API](xref:testengineapi) designed to be used by test runners, which will be maintained in a +To start using the engine in your own runner, see [Getting Started](xref:gettingstartedengine). The engine exposes +[an API](xref:testengineapi) designed to be used by test runners, which will be maintained in a backwards-compatible fashion wherever possible. The engine also hosts various extension points, to allow further customization. diff --git a/docs/articles/nunit/getting-started/toc.yml b/docs/articles/nunit/getting-started/toc.yml index 8836c4b41..0f3e9d0e6 100644 --- a/docs/articles/nunit/getting-started/toc.yml +++ b/docs/articles/nunit/getting-started/toc.yml @@ -2,11 +2,6 @@ href: installation.md - name: Downloading href: downloading.md -- name: Upgrading - href: upgrading.md - name: Samples href: samples.md -- name: Breaking Changes - topicUid: breakingchanges -- name: .NET Core and .NET Standard - href: dotnet-core-and-dotnet-standard.md + diff --git a/docs/articles/nunit/license.md b/docs/articles/nunit/license.md index f6f03d4a6..80f673251 100644 --- a/docs/articles/nunit/license.md +++ b/docs/articles/nunit/license.md @@ -1,6 +1,6 @@ # NUnit License -## Copyright (c) 2004-2021 Charlie Poole, Rob Prouse and Contributors. +## Copyright (c) 2009-2019 Charlie Poole, 2014-2025 Rob Prouse, 2026 Terje Sandstrom and Contributors. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/docs/articles/nunit/release-notes/toc.yml b/docs/articles/nunit/release-notes/toc.yml index 263be9839..3cd8a39b7 100644 --- a/docs/articles/nunit/release-notes/toc.yml +++ b/docs/articles/nunit/release-notes/toc.yml @@ -2,9 +2,3 @@ href: framework.md - name: Console and Engine topicUid: consoleenginegithubreleasenotes -- name: Migration Guidance - topicUid: migrationguidance -- name: Breaking Changes - topicUid: breakingchanges -- name: Pre-3.5 Release notes - href: Pre-3.5-Release-Notes.md \ No newline at end of file diff --git a/docs/articles/nunit/running-tests/Console-Runner.md b/docs/articles/nunit/running-tests/Console-Runner.md index aa8bc5bf8..e93169475 100644 --- a/docs/articles/nunit/running-tests/Console-Runner.md +++ b/docs/articles/nunit/running-tests/Console-Runner.md @@ -3,6 +3,8 @@ The nunit3-console.exe program is a text-based runner for listing and running our tests from the command-line. It is able to run all NUnit 3.0 or higher tests natively and can run NUnit 2.x tests if the v2 driver is installed. +All the options are described in [Console Command Line](xref:consolecommandline). + This runner is useful for automation of tests and integration into other systems. It automatically saves its results in XML format, allowing you to produce reports or otherwise process the results. The following is a screenshot of the console program output. diff --git a/docs/articles/nunit/running-tests/NUnitLite-Runner.md b/docs/articles/nunit/running-tests/NUnitLite-Runner.md index 28b5f76b6..45c56536d 100644 --- a/docs/articles/nunit/running-tests/NUnitLite-Runner.md +++ b/docs/articles/nunit/running-tests/NUnitLite-Runner.md @@ -52,6 +52,8 @@ dotnet run If you install the NUnitLite runner via the NuGet package, steps 2 is handled automatically. Both assemblies are installed and referenced for you. +All the options are described in [NUnitLite Options](NUnitLite-Options.md). + ## NUnitLite Output As seen in the following screen shot, the output from an NUnitLite run is quite similar to that from the console runner. diff --git a/docs/articles/nunit/technical-notes/nunit-internals/toc.yml b/docs/articles/nunit/technical-notes/nunit-internals/toc.yml index 0a3255cf4..1750a1284 100644 --- a/docs/articles/nunit/technical-notes/nunit-internals/toc.yml +++ b/docs/articles/nunit/technical-notes/nunit-internals/toc.yml @@ -19,8 +19,6 @@ href: Attribute-Hierarchy.md - name: Test Discovery And Execution href: Test-Discovery-And-Execution.md -- name: NUnit 3.0 Architecture (2009) - href: NUnit-3.0-Architecture-(2009).md - name: Specifications href: specs/toc.yml topicHref: specs/Specifications.md \ No newline at end of file diff --git a/docs/articles/nunit/technical-notes/usage/Trace-and-Debug-Output.md b/docs/articles/nunit/technical-notes/usage/Trace-and-Debug-Output.md index 2a5138e50..a4f6ca61f 100644 --- a/docs/articles/nunit/technical-notes/usage/Trace-and-Debug-Output.md +++ b/docs/articles/nunit/technical-notes/usage/Trace-and-Debug-Output.md @@ -100,6 +100,9 @@ test fixture/class. If you like you can change that to another kind of listener. +For how the test adapter shows this output in Visual Studio and `dotnet test`, see +[Trace and Debug Output in the adapter](../../../vs-test-adapter/Trace-and-Debug.md). + ## Discussion and source This issue has been discussed at [Issue 718](https://github.com/nunit/nunit3-vs-adapter/issues/718) and diff --git a/docs/articles/nunit/technical-notes/usage/Usage-Notes.md b/docs/articles/nunit/technical-notes/usage/Usage-Notes.md index 1e38e050f..b3f65d4e9 100644 --- a/docs/articles/nunit/technical-notes/usage/Usage-Notes.md +++ b/docs/articles/nunit/technical-notes/usage/Usage-Notes.md @@ -5,10 +5,9 @@ * [Assembly Isolation](Assembly-Isolation.md) * [Configuration Files](Configuration-Files.md) * [XML Formats](XML-Formats.md) -* [Visual Studio Support](Visual-Studio-Support.md) +* [NUnit Test Projects](xref:nunittestprojects) * [SetUp and TearDown](SetUp-and-TearDown.md) * [Parameterized Tests](Parameterized-Tests.md) -* [Addin Replacement in the Framework](Addin-Replacement-in-the-Framework.md) * [Counting Tests](Counting-Tests.md) * [Framework Parallel Test Execution](Framework-Parallel-Test-Execution.md) * [Engine Parallel Test Execution](Engine-Parallel-Test-Execution.md) diff --git a/docs/articles/nunit/technical-notes/usage/toc.yml b/docs/articles/nunit/technical-notes/usage/toc.yml index 0ebb37923..82fe0dd40 100644 --- a/docs/articles/nunit/technical-notes/usage/toc.yml +++ b/docs/articles/nunit/technical-notes/usage/toc.yml @@ -1,7 +1,5 @@ - name: Usage Notes href: Usage-Notes.md -- name: Addin Replacement in the Framework - href: Addin-Replacement-in-the-Framework.md - name: Assembly Isolation href: Assembly-Isolation.md - name: Configuration Files @@ -30,7 +28,5 @@ href: Test-Result-XML-Format.md - name: Trace and Debug Output href: Trace-and-Debug-Output.md -- name: Visual Studio Support - href: Visual-Studio-Support.md - name: XML Formats href: XML-Formats.md \ No newline at end of file diff --git a/docs/articles/nunit/toc.yml b/docs/articles/nunit/toc.yml index f7bba6b87..8e52dd761 100644 --- a/docs/articles/nunit/toc.yml +++ b/docs/articles/nunit/toc.yml @@ -4,10 +4,6 @@ href: V5NewFeatures.md - name: NUnit 5 Breaking Changes href: V5BreakingChanges.md -- name: NUnit 4 plans - href: Towards-NUnit4.md -- name: Migration Guidance - uid: migrationguidance - name: Release Notes href: release-notes/toc.yml topicHref: release-notes/framework.md diff --git a/docs/articles/nunit/writing-tests/automating-tests.md b/docs/articles/nunit/writing-tests/automating-tests.md index 617dee4b9..df421f0fd 100644 --- a/docs/articles/nunit/writing-tests/automating-tests.md +++ b/docs/articles/nunit/writing-tests/automating-tests.md @@ -32,6 +32,9 @@ hold for *any* input, such as `a + b == b + a`. NUnit records the random seed it [!code-csharp[AutomatingRandom](~/snippets/Snippets.NUnit/WritingTestsGuideExamples.cs#AutomatingRandom)] +To create random values in the test code itself, use the [Randomizer](xref:randomizermethods) from +`TestContext.CurrentContext.Random`. It uses the same seed, so these values can be reproduced too. + ## Keeping the number of tests down Combinations grow fast: three parameters with ten values each give a thousand test cases. NUnit has two attributes that diff --git a/docs/articles/nunit/writing-tests/data-driven-tests.md b/docs/articles/nunit/writing-tests/data-driven-tests.md index 481f4dffc..08dbe8b31 100644 --- a/docs/articles/nunit/writing-tests/data-driven-tests.md +++ b/docs/articles/nunit/writing-tests/data-driven-tests.md @@ -30,7 +30,8 @@ somewhere else, such as a file. Point the attribute at a static method, property [!code-csharp[DataDrivenTestCaseSource](~/snippets/Snippets.NUnit/WritingTestsGuideExamples.cs#DataDrivenTestCaseSource)] Returning [`TestCaseData`](xref:testcasedata) objects is optional, but it lets you give each case a readable name, a -description, categories and more. +description, categories and more. To name many test cases with one pattern, see +[Template Based Test Naming](xref:templatebasedtestnaming). ## Data for a single parameter with [ValueSource] diff --git a/docs/articles/nunit/writing-tests/dependent-tests.md b/docs/articles/nunit/writing-tests/dependent-tests.md new file mode 100644 index 000000000..7029992f6 --- /dev/null +++ b/docs/articles/nunit/writing-tests/dependent-tests.md @@ -0,0 +1,45 @@ +--- +uid: dependenttests +--- + +# 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]`](xref:attribute-dependsontest) and +[`[DependsOnFixture]`](xref:attribute-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. + +[!code-csharp[DependentTests](~/snippets/Snippets.NUnit/WritingTestsGuideExamples.cs#DependentTests)] + +- `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]`](xref:attribute-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. + +## Things to keep in mind + +- Tests in a dependency chain can't run in parallel with each other. Don't mark them + [`[Parallelizable]`](xref:attribute-parallelizable). +- Don't combine dependencies with [`[Order]`](xref:attribute-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](xref:attribute-dependsontest) and [DependsOnFixture](xref:attribute-dependsonfixture) reference +pages for all the details. diff --git a/docs/articles/nunit/writing-tests/flaky-and-slow-tests.md b/docs/articles/nunit/writing-tests/flaky-and-slow-tests.md new file mode 100644 index 000000000..737b7c98b --- /dev/null +++ b/docs/articles/nunit/writing-tests/flaky-and-slow-tests.md @@ -0,0 +1,63 @@ +--- +uid: flakyandslowtests +--- + +# Flaky and Slow Tests + +Some tests don't give the same result every time. They call a service that sometimes times out, test something that is +non-deterministic by nature, or now and then take far too long. NUnit has attributes for each of these cases. + +> [!TIP] +> A flaky test is often a sign of a real problem, such as a race condition or state shared between tests. Use these +> attributes to keep your build reliable while you investigate, not to hide bugs. + +## Retrying a test that sometimes fails + +[`[Retry]`](xref:attribute-retry) runs the test again when an assertion fails, up to the number of attempts you give. +The test passes as soon as one attempt passes. + +[!code-csharp[FlakyRetry](~/snippets/Snippets.NUnit/WritingTestsGuideExamples.cs#FlakyRetry)] + +The count is the total number of attempts, so `[Retry(3)]` means one run and up to two retries. By default, only +assertion failures cause a retry. List the exceptions that should also cause a retry in `RetryExceptions`. + +## Allowing some failures + +For systems that are non-deterministic by design, such as tests of AI-based features, you can accept that a test +sometimes fails. [`[Repeat]`](xref:attribute-repeat) with `RequiredPassPercentage` runs the test several times and +passes when enough of the runs pass. + +[!code-csharp[FlakyRepeatThreshold](~/snippets/Snippets.NUnit/WritingTestsGuideExamples.cs#FlakyRepeatThreshold)] + +Set `StopWhenOverallResultDetermined = true` to stop repeating as soon as the outcome is certain. `[Repeat]` without a +percentage is also a good way to *find* a flaky test: repeat it a hundred times and see whether it ever fails. + +> [!NOTE] +> `RequiredPassPercentage` and `StopWhenOverallResultDetermined` were added in NUnit 5.0. + +## Tests that take too long + +[`[MaxTime]`](xref:attribute-maxtime) fails a test that takes longer than the time you give, in milliseconds. With +`WarningTime`, a test that is slower than expected, but still within the limit, gives a warning instead. The test is +never interrupted: NUnit measures the time when it finishes. + +[!code-csharp[SlowMaxTime](~/snippets/Snippets.NUnit/WritingTestsGuideExamples.cs#SlowMaxTime)] + +## Tests that hang + +To stop a test that runs too long, use [`[CancelAfter]`](xref:attribute-cancelafter). NUnit passes a +`CancellationToken` to the test and cancels it when the time is up. The test must pass the token on to the code it +calls, so that the work actually stops. + +[!code-csharp[SlowCancelAfter](~/snippets/Snippets.NUnit/WritingTestsGuideExamples.cs#SlowCancelAfter)] + +> [!NOTE] +> The older [`[Timeout]`](xref:attribute-timeout) attribute only works on .NET Framework, and is reported as a test +> failure on .NET 5 and later. For code that can't be cancelled, `dotnet test --blame-hang-timeout` stops the whole +> test run when a test hangs. + +## See also + +- The [Retry](xref:attribute-retry), [Repeat](xref:attribute-repeat), [MaxTime](xref:attribute-maxtime) and + [CancelAfter](xref:attribute-cancelafter) reference pages +- [Warnings](Warnings.md), for how warning results are reported diff --git a/docs/articles/nunit/writing-tests/ordinary-tests.md b/docs/articles/nunit/writing-tests/ordinary-tests.md index bacdc7893..e4e8bd50e 100644 --- a/docs/articles/nunit/writing-tests/ordinary-tests.md +++ b/docs/articles/nunit/writing-tests/ordinary-tests.md @@ -37,5 +37,6 @@ Use [`[TearDown]`](xref:attribute-teardown) for cleanup after each test, and - [Data driven tests](xref:datadriventests) run the same test with different inputs. - [Automating tests](xref:automatingtests) lets NUnit generate the inputs for you. +- [Multiple asserts](xref:multipleasserts) checks several things in one test and reports all the failures. - [Constraints](xref:constraints) lists everything you can check with `Assert.That`. - [Attributes](attributes.md) describes all the ways you can mark and control tests. diff --git a/docs/articles/nunit/writing-tests/organizing-tests.md b/docs/articles/nunit/writing-tests/organizing-tests.md new file mode 100644 index 000000000..617009f11 --- /dev/null +++ b/docs/articles/nunit/writing-tests/organizing-tests.md @@ -0,0 +1,62 @@ +--- +uid: organizingtests +--- + +# Organizing and Selecting Tests + +As a test suite grows, you often want to run only part of it: the fast tests on every build, the integration tests at +night, or the one test you are working on. NUnit lets you group tests, and then choose which groups to run. + +## Grouping tests with categories + +Put [`[Category]`](xref:attribute-category) on a test or a fixture. A test can be in several categories, and it +inherits the categories of its fixture. + +[!code-csharp[OrganizingCategories](~/snippets/Snippets.NUnit/WritingTestsGuideExamples.cs#OrganizingCategories)] + +## Running only some categories + +With `dotnet test`, filter on `TestCategory`: + +```shell +# Only the integration tests +dotnet test --filter "TestCategory=Integration" + +# Everything except the slow tests +dotnet test --filter "TestCategory!=Slow" +``` + +With the [NUnit console](xref:consolecommandline), use `--where` with the +[Test Selection Language](xref:testselectionlanguage), which can also select tests by name, class, namespace or +property: + +```shell +nunit3-console MyTests.dll --where "cat == Integration && cat != Slow" +``` + +The same expressions work with `dotnet test` through the `NUnit.Where` setting, for example +`dotnet test -- NUnit.Where="cat == Integration"`. See [Configuring with .runsettings](xref:tipsandtricks) for all the +settings. + +## Tests that run only on demand + +Mark a test with [`[Explicit]`](xref:attribute-explicit) when it should run only when you select it yourself, for +example a test that rebuilds a database. It is skipped when you run all the tests. + +## Tests that must not run for now + +Mark a test with [`[Ignore]`](xref:attribute-ignore) when it can't run at the moment, and give the reason. Ignored tests +show up as warnings, so they are not forgotten. With `Until`, the test starts running again after the given date. + +[!code-csharp[OrganizingExplicitIgnore](~/snippets/Snippets.NUnit/WritingTestsGuideExamples.cs#OrganizingExplicitIgnore)] + +> [!TIP] +> If a project contains only explicit tests, running the project runs all of them, because the adapter can't tell that +> apart from selecting them yourself. See [Explicit](xref:attribute-explicit) for details. + +## See also + +- [Test Selection Language](xref:testselectionlanguage) +- [Console Command Line](xref:consolecommandline) +- The [Category](xref:attribute-category), [Explicit](xref:attribute-explicit) and [Ignore](xref:attribute-ignore) + reference pages diff --git a/docs/articles/nunit/writing-tests/toc.yml b/docs/articles/nunit/writing-tests/toc.yml index 92ddb1db8..126745d6d 100644 --- a/docs/articles/nunit/writing-tests/toc.yml +++ b/docs/articles/nunit/writing-tests/toc.yml @@ -4,6 +4,12 @@ href: data-driven-tests.md - name: Automating Tests href: automating-tests.md +- name: Tests That Depend on Other Tests + href: dependent-tests.md +- name: Flaky and Slow Tests + href: flaky-and-slow-tests.md +- name: Organizing and Selecting Tests + href: organizing-tests.md - name: Attributes href: attributes.md - name: Attribute Descriptions @@ -28,10 +34,6 @@ href: TestFixtureData.md - name: TestContext href: TestContext.md -- name: AssertionHelper - href: AssertionHelper.md -- name: ListMapper - href: ListMapper.md - name: Randomizer Methods href: Randomizer-Methods.md diff --git a/docs/articles/toc.yml b/docs/articles/toc.yml index 0057a8af1..8000f5083 100644 --- a/docs/articles/toc.yml +++ b/docs/articles/toc.yml @@ -7,9 +7,6 @@ - name: NUnit Engine href: nunit-engine/toc.yml topicHref: nunit-engine/Index.md -- name: NUnit Xamarin Runners - href: xamarin-runners/toc.yml - topicHref: xamarin-runners/index.md - name: VS Test Generator href: vs-test-generator/toc.yml topicHref: vs-test-generator/Visual-Studio-Test-Generator.md @@ -20,9 +17,59 @@ items: - name: TestCentric GUI href: https://github.com/TestCentric/testcentric-gui/wiki - - name: NUnit Project Editor - href: https://github.com/nunit-legacy/nunit-project-editor/wiki/Project-Editor - name: Developer Info href: developer-info/toc.yml -- name: "Legacy (2.x) Docs" - href: legacy/index.md +- name: Archive + href: archive.md + items: + - name: NUnit 2.x Documentation + href: legacy/index.md + - name: Older Versions + items: + - name: Release Notes Before 3.5 + href: nunit/release-notes/Pre-3.5-Release-Notes.md + - name: Breaking Changes up to NUnit 4.0 + href: nunit/release-notes/breaking-changes.md + - name: Migrating to NUnit 4 + href: nunit/release-notes/Nunit4.0-MigrationGuide.md + - name: Upgrading from NUnit 2 and 3 + href: nunit/getting-started/upgrading.md + - name: Towards NUnit 4 + href: nunit/Towards-NUnit4.md + - name: .NET Core and .NET Standard + href: nunit/getting-started/dotnet-core-and-dotnet-standard.md + - name: Deprecated Features + items: + - name: AssertionHelper + href: nunit/writing-tests/AssertionHelper.md + - name: ListMapper + href: nunit/writing-tests/ListMapper.md + - name: Addin Replacement in the Framework + href: nunit/technical-notes/usage/Addin-Replacement-in-the-Framework.md + - name: Visual Studio Support + href: nunit/technical-notes/usage/Visual-Studio-Support.md + - name: NUnit Xamarin Runners + href: xamarin-runners/toc.yml + topicHref: xamarin-runners/index.md + - name: NUnit Project Editor + href: https://github.com/nunit-legacy/nunit-project-editor/wiki/Project-Editor + - name: Older Release Notes + items: + - name: Test Adapter V3 + href: vs-test-adapter/AdapterV3-Release-Notes.md + - name: Test Adapter V2 + href: vs-test-adapter/AdapterV2-Release-Notes.md + - name: Test Generator VS2017/VS2019 + href: vs-test-generator/TestGenerator-Release-Notes-VS2017-VS2019.md + - name: Test Generator VS2015 + href: vs-test-generator/TestGenerator-Release-Notes-VS2015.md + - name: Developer History + items: + - name: Notes Toward NUnit 4.0 + href: developer-info/Notes-Toward-NUnit-4.0.md + - name: NUnit 3.0 Architecture (2009) + href: nunit/technical-notes/nunit-internals/NUnit-3.0-Architecture-(2009).md + - name: Packaging the V2 Adapter + href: developer-info/Packaging-the-V2-Adapter.md + - name: Packaging the Installer + href: developer-info/Packaging-the-Installer.md diff --git a/docs/articles/vs-test-adapter/Debugging.md b/docs/articles/vs-test-adapter/Debugging.md index 46b84f54c..67b286925 100644 --- a/docs/articles/vs-test-adapter/Debugging.md +++ b/docs/articles/vs-test-adapter/Debugging.md @@ -44,6 +44,9 @@ section. A detailed explanation of the process can be found in [this blog post](https://hermit.no/debugging-the-nunit3testadapter-take-2/) +To step into the adapter source code from your own debugging session, see +[Adapter Source Stepping](Adapter-Source-Stepping.md). + ## Debugging earlier versions See [this blog post](https://hermit.no/debugging-the-nunit3testadapter/) for details on that process. diff --git a/docs/articles/vs-test-adapter/Index.md b/docs/articles/vs-test-adapter/Index.md index 2f11e8f44..eae0e179f 100644 --- a/docs/articles/vs-test-adapter/Index.md +++ b/docs/articles/vs-test-adapter/Index.md @@ -14,7 +14,9 @@ frameworks like NUnit. [Download Pre-release versions](https://www.myget.org/feed/nunit/package/nuget/NUnit3TestAdapter) -The adapter is delivered as a nuget package to be installed into all test projects. +The adapter is delivered as a nuget package to be installed into all test projects. See +[Installation](xref:vstestadapterinstallation) for how to add it, and [Usage](Usage.md) for running tests in +Visual Studio. > [!NOTE] > Up to version 3.17 there is also a VSIX extension version, which was used earlier for Visual Studio up to diff --git a/docs/articles/vs-test-adapter/toc.yml b/docs/articles/vs-test-adapter/toc.yml index 6fe6f01fd..841cc6da1 100644 --- a/docs/articles/vs-test-adapter/toc.yml +++ b/docs/articles/vs-test-adapter/toc.yml @@ -24,9 +24,5 @@ href: Adapter-Source-Stepping.md - name: Release Notes V4 href: AdapterV4-Release-Notes.md -- name: Release Notes V3 - href: AdapterV3-Release-Notes.md -- name: Release Notes V2 - href: AdapterV2-Release-Notes.md - name: License href: Adapter-License.md diff --git a/docs/articles/vs-test-generator/toc.yml b/docs/articles/vs-test-generator/toc.yml index 48142bc00..448a9004c 100644 --- a/docs/articles/vs-test-generator/toc.yml +++ b/docs/articles/vs-test-generator/toc.yml @@ -3,8 +3,4 @@ - name: Installation href: TestGenerator-Installation.md - name: Release Notes - href: TestGenerator-Release-Notes.md -- name: Release Notes VS2017/VS2019 - href: TestGenerator-Release-Notes-VS2017-VS2019.md -- name: Release Notes VS2015 - href: TestGenerator-Release-Notes-VS2015.md \ No newline at end of file + href: TestGenerator-Release-Notes.md \ No newline at end of file diff --git a/docs/home.md b/docs/home.md index 49a3d45b0..508a448aa 100644 --- a/docs/home.md +++ b/docs/home.md @@ -33,7 +33,10 @@ _description: Documentation for NUnit, the open-source unit-testing framework fo Test with many inputs Checking results Setup and cleanup +Tests that depend on each other +Flaky tests Running tests in parallel +Microsoft.Testing.Platform Upgrading to NUnit 5 Analyzer warnings

    @@ -63,13 +66,21 @@ public class CalculatorTests
  • Ordinary tests
  • Data driven tests
  • Automating tests
  • +
  • Checking several things at once
  • +
  • Tests that depend on other tests
  • +
  • Flaky and slow tests
  • +
  • Organizing and selecting tests
  • Reference

    @@ -83,6 +94,7 @@ public class CalculatorTests
  • In Rider
  • From the command line
  • In an existing project
  • +
  • Pre-release and developer builds
  • Samples
  • Upgrading to NUnit 5
  • @@ -106,9 +118,12 @@ public class CalculatorTests

    Run your tests in the IDE, on the command line or in your build.

    @@ -159,26 +177,24 @@ public class CalculatorTests
  • Custom constraints
  • Custom attributes
  • Action attributes
  • +
  • Execution hooks
  • Engine extensions
  • -

    Questions? Ask in GitHub Discussions · NUnit on GitHub · Help improve these docs

    +

    Questions? Ask in GitHub Discussions · NUnit on GitHub · Help improve these docs · License

    diff --git a/docs/snippets/Snippets.NUnit/WritingTestsGuideExamples.cs b/docs/snippets/Snippets.NUnit/WritingTestsGuideExamples.cs index f051c4f87..d4cfacfb8 100644 --- a/docs/snippets/Snippets.NUnit/WritingTestsGuideExamples.cs +++ b/docs/snippets/Snippets.NUnit/WritingTestsGuideExamples.cs @@ -183,4 +183,146 @@ public void Format_HandlesAllOptions( } } #endregion + + #region DependentTests + public class OrderWorkflowTests + { + private static readonly List 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); + } + } + #endregion + + #region FlakyRetry + public class ExternalServiceTests + { + [Test] + [Retry(3)] + public void Service_Responds() + { + // If the assertion fails, NUnit runs the test again, up to 3 attempts in total. + Assert.That(CallService(), Is.EqualTo("OK")); + } + + [Test] + [Retry(3, RetryExceptions = [typeof(TimeoutException)])] + public void Service_Responds_EvenAfterTimeouts() + { + // Also retried when the call throws a TimeoutException. + Assert.That(CallService(), Is.EqualTo("OK")); + } + + private static string CallService() => "OK"; + } + #endregion + + #region FlakyRepeatThreshold + public class RecommendationTests + { + [Test] + [Repeat(20, RequiredPassPercentage = 90)] + public void Recommendation_IsUsuallyRelevant() + { + // Passes when at least 18 of the 20 runs pass. + Assert.That(GetRecommendation(), Is.Not.Empty); + } + + private static string GetRecommendation() => "NUnit"; + } + #endregion + + #region SlowMaxTime + public class PerformanceTests + { + [Test] + [MaxTime(2000, WarningTime = 500)] + public void Search_IsFastEnough() + { + // A warning above 500 ms, a failure above 2 seconds. The test is never interrupted. + var result = Enumerable.Range(1, 1000).Where(n => n % 7 == 0).ToList(); + Assert.That(result, Is.Not.Empty); + } + } + #endregion + + #region SlowCancelAfter + public class DownloadTests + { + [Test] + [CancelAfter(5000)] + public async Task Download_Completes(CancellationToken cancellationToken) + { + // NUnit cancels the token after 5 seconds. Pass it on so the work actually stops. + var content = await DownloadAsync(cancellationToken); + Assert.That(content, Is.Not.Empty); + } + + private static async Task DownloadAsync(CancellationToken cancellationToken) + { + await Task.Delay(10, cancellationToken); + return "content"; + } + } + #endregion + + #region OrganizingCategories + [Category("Integration")] + public class DatabaseTests + { + [Test] + public void Connection_Opens() + { + Assert.Pass(); + } + + [Test] + [Category("Slow")] + public void Migration_Runs() + { + // This test is in both the "Integration" and the "Slow" category. + Assert.Pass(); + } + } + #endregion + + #region OrganizingExplicitIgnore + public class MaintenanceTests + { + [Test] + [Explicit("Rebuilds the test database, run it on demand")] + public void RebuildTestDatabase() + { + Assert.Pass(); + } + + [Test] + [Ignore("Waiting for issue #123 to be fixed", Until = "2099-12-31")] + public void Export_HandlesUnicode() + { + Assert.Fail("Not fixed yet"); + } + } + #endregion } From 2a3ee8c737553e0b6150189fa6fe2dc4204cd32c Mon Sep 17 00:00:00 2001 From: Terje Sandstrom Date: Sun, 27 Sep 2026 14:47:44 +0200 Subject: [PATCH 07/11] Make the new landing page the home page, refresh intro and adapter overview - The new layout is now index.md; the previous home page moves to classic.md and is linked from the top menu as "Classic Home". The preview banner and the layout-switch script are removed. - The NUnit introduction states that the docs cover NUnit 3 and later, with NUnit 2 as a separate product in the Archive, and points to where to start. - The test adapter overview is rewritten for adapter 6: NUnit 3 to 5, VSTest and Microsoft.Testing.Platform, .NET Framework 4.6.2 and .NET 8 and later, and configuration with runsettings. Co-Authored-By: Claude Opus 5.5 --- docs/articles/archive.md | 2 +- docs/articles/nunit/intro.md | 26 ++- docs/articles/vs-test-adapter/Index.md | 50 ++++-- docs/classic.md | 24 +++ docs/custom_template/styles/main.css | 14 +- docs/home.md | 200 ---------------------- docs/index.md | 219 ++++++++++++++++++++++--- docs/styles/main.js | 19 --- docs/toc.yml | 10 +- 9 files changed, 280 insertions(+), 284 deletions(-) create mode 100644 docs/classic.md delete mode 100644 docs/home.md diff --git a/docs/articles/archive.md b/docs/articles/archive.md index d5c479bc8..66944772f 100644 --- a/docs/articles/archive.md +++ b/docs/articles/archive.md @@ -7,7 +7,7 @@ uid: archive These pages describe older versions of NUnit, features that were removed or deprecated, and tools that are no longer maintained. They are kept for reference, and for anyone still working with older versions. -For the current version, start at the [documentation home page](../home.md). +For the current version, start at the [documentation home page](../index.md). ## Older versions of NUnit diff --git a/docs/articles/nunit/intro.md b/docs/articles/nunit/intro.md index fbb52ed31..439805bd6 100644 --- a/docs/articles/nunit/intro.md +++ b/docs/articles/nunit/intro.md @@ -4,11 +4,27 @@ uid: intro # NUnit Documentation -This documentation covers NUnit 3.0 and higher. +NUnit is the open-source unit-testing framework for all .NET languages. This section documents the NUnit framework, +NUnitLite and the NUnit Console, from NUnit 3 up to the current version, NUnit 5. -Where applicable, we have marked sections with the version in which a feature first appeared. +Most of the content applies to all these versions. Where a feature was added or changed in a specific version, the +page says so, for example "This constraint was added in NUnit 4.2". Behavior from earlier versions is described in +notes or in sections such as *NUnit 4 and earlier*. -If you are new to NUnit, we suggest you begin by reading the Getting Started section of this site. Those who have used -earlier releases may want to begin with the Upgrading section. +## Where to start -See the [Release Notes](xref:frameworkreleasenotes) for more information on each release. +* **New to NUnit?** Start with [Installation](xref:installation) to create a test project, and then + [Ordinary Tests](xref:ordinarytests) to write your first test. +* **Moving to NUnit 5?** See [What's new in NUnit 5](xref:v5newfeatures) and + [the breaking changes in NUnit 5](xref:v5breakingchanges). +* **Looking for a specific attribute, assertion or constraint?** See [Attributes](writing-tests/attributes.md), + [Assertions](xref:assertions) and [Constraints](xref:constraints). +* **What changed in a release?** See the [release notes](xref:frameworkreleasenotes). + +The [documentation home page](../../index.md) gives an overview of everything, including the test adapter, the +analyzers and the NUnit engine. + +## NUnit 2 + +NUnit 2 is a different product, with its own design and its own documentation. It is not covered here. Its +documentation is kept in the [Archive](xref:legacydocs). diff --git a/docs/articles/vs-test-adapter/Index.md b/docs/articles/vs-test-adapter/Index.md index eae0e179f..8a28b61b7 100644 --- a/docs/articles/vs-test-adapter/Index.md +++ b/docs/articles/vs-test-adapter/Index.md @@ -1,26 +1,42 @@ # Visual Studio Test Adapter -The NUnit 3 Test Adapter allows you to run NUnit 3 and 4 tests inside Visual Studio or with `dotnet` on the command line. +The NUnit Test Adapter lets you run NUnit tests in Visual Studio, Rider and Visual Studio Code, and from the command +line with `dotnet test`. It runs tests written with NUnit 3, NUnit 4 and NUnit 5. -The current release is designed to work with Visual Studio 2012, 2013, 2015, 2017, 2019 and 2022. Some features are not -available under VS2012 RTM. It also works from the command line using either `vstest.console` or `dotnet test`. +The adapter is published on NuGet as **NUnit3TestAdapter**. The name comes from the NUnit 3 era; the same package is +used for all current NUnit versions. -The current release works with .net framework 3.5 and higher, with .net core `3.*`, and with .net 5, .net 6, and .net 7. +* [Download released versions](https://www.nuget.org/packages/NUnit3TestAdapter/) +* [Download pre-release versions](https://www.myget.org/feed/nunit/package/nuget/NUnit3TestAdapter) -Releases of Visual Studio prior to VS 2012 did not have the ability to directly run tests built with Open Source testing -frameworks like NUnit. +## Getting started -[Download Released versions](https://www.nuget.org/packages/NUnit3TestAdapter/) +Add the adapter as a NuGet package to each test project. The NUnit project templates in Visual Studio, Rider and +`dotnet new nunit` already include it. See [Installation](xref:vstestadapterinstallation) for how to add it to an +existing project, and [Usage](Usage.md) for running and debugging tests in Visual Studio. -[Download Pre-release versions](https://www.myget.org/feed/nunit/package/nuget/NUnit3TestAdapter) +## Two ways to run tests -The adapter is delivered as a nuget package to be installed into all test projects. See -[Installation](xref:vstestadapterinstallation) for how to add it, and [Usage](Usage.md) for running tests in -Visual Studio. +The adapter supports both test platforms that `dotnet test` and the IDEs use: -> [!NOTE] -> Up to version 3.17 there is also a VSIX extension version, which was used earlier for Visual Studio up to -> version 2019. The support for this has been deprecated, and the existing VSIX version does not work for VS 2022. The -> recommendation is to avoid this altogether and use the nuget version. It is not possible to run NUnit 2.x tests using -> this adapter. Use the original adapter for that purpose. If you need to work with projects using NUnit 2.x and other -> projects using NUnit 3, you may install both versions of the adapter. +* **VSTest**, the classic test platform. This is the default. +* **[Microsoft.Testing.Platform](NUnit-And-Microsoft-Test-Platform.md)** (MTP), the newer and lighter test platform. + From adapter version 6.0, MTP version 2 is supported. + +## Supported .NET versions + +The current adapter, version 6, runs tests on .NET Framework 4.6.2 and later, and on .NET 8 and later. Older .NET +versions, such as .NET Core 3.1 and .NET 5 to 7, need an older adapter version. See +[Supported Frameworks](Supported-Frameworks.md) for which adapter version supports which .NET version. + +## Configuration + +Use a `.runsettings` file, or settings on the `dotnet test` command line, to control how the adapter runs your tests: +test filters, output, parallel execution, result files and more. See +[Configuration with runsettings](xref:tipsandtricks) for all the settings. + +## Older versions + +* The adapter can't run NUnit 2.x tests. Those need the NUnit 2 adapter, which is no longer maintained. +* Up to version 3.17, the adapter was also available as a VSIX extension for Visual Studio 2019 and earlier. The VSIX + version is deprecated and doesn't work with Visual Studio 2022 or later. Use the NuGet package instead. diff --git a/docs/classic.md b/docs/classic.md new file mode 100644 index 000000000..0c2ff9448 --- /dev/null +++ b/docs/classic.md @@ -0,0 +1,24 @@ +# NUnit Documentation Site + +> [!NOTE] +> This is the previous home page of the NUnit documentation, kept for a while for reference. The documentation now +> starts at the [new home page](index.md). Feedback is welcome in +> [this discussion](https://github.com/nunit/docs/discussions/1023). + +This web site contains the documentation for all active NUnit projects as well as developer documentation for those +working on NUnit or wishing to do so. + +## User Documentation + +* [NUnit](xref:intro) covers the core tools of NUnit, including the framework, NUnitLite, and the console runner. +* [NUnit VS Adapter](xref:vstestadapterinstallation) covers the test adapters for Visual Studio and .Net. +* [NUnit Analyzers](xref:nunitanalyzers) covers the NUnit Analyzers. +* [NUnit VS Test Generator](xref:vstestgenerator) covers the Visual Studio extension for generating tests in both NUnit + V2 and V3. +* [NUnit Xamarin Runners](xref:xamarinrunners) covers the NUnit test runners for Xamarin and mobile devices. +* [NUnit Engine](xref:nunitengine) covers the NUnit Engine, the central component all test runners are built around. + +## Developer Documentation + +* [Team practices](xref:teampractices) describe how NUnit works and how our teams work. +* [Specifications](xref:specifications) are descriptions of features we plan to add. diff --git a/docs/custom_template/styles/main.css b/docs/custom_template/styles/main.css index a1f4ada14..cd4dcf1a0 100644 --- a/docs/custom_template/styles/main.css +++ b/docs/custom_template/styles/main.css @@ -11,7 +11,7 @@ div.across ul li width:9em } /* ------------------------------------------------------------------ - New landing page (home.md). Everything is scoped under .nh so the + Documentation home page (index.md). Everything is scoped under .nh so the rest of the site is unaffected. ------------------------------------------------------------------ */ .nh { @@ -32,18 +32,6 @@ div.across ul li .nh h1, .nh h2, .nh h3 { font-weight: 600; letter-spacing: -0.01em; } .nh code { background: var(--nh-green-soft); color: var(--nh-green-dark); padding: 1px 5px; border-radius: 4px; } -/* Preview banner / layout switch */ -.nh-switch { - display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; - margin: 8px 0 20px; padding: 10px 16px; - border: 1px dashed var(--nh-border); border-radius: var(--nh-radius); - color: var(--nh-muted); font-size: 14px; -} -.nh-switch a { margin-left: auto; font-weight: 600; color: var(--nh-green); } -.nh-badge { - background: var(--nh-green); color: #fff; font-size: 11px; font-weight: 700; - text-transform: uppercase; letter-spacing: .06em; padding: 2px 8px; border-radius: 999px; -} /* Hero */ .nh-hero { diff --git a/docs/home.md b/docs/home.md deleted file mode 100644 index 508a448aa..000000000 --- a/docs/home.md +++ /dev/null @@ -1,200 +0,0 @@ ---- -title: NUnit Documentation -_disableAffix: true -_disableContribution: true -_description: Documentation for NUnit, the open-source unit-testing framework for all .NET languages. ---- - - -
    -
    -Preview -You are looking at the new documentation home page, which is still taking shape. -Switch to the classic home page -
    -
    -
    -

    NUnit documentation

    -

    Write tests you can trust, for any .NET code

    -

    NUnit is the open-source unit-testing framework for .NET. Write a test in a few lines, get warnings about mistakes as you type from the NUnit Analyzers, run it with many sets of data, and run it anywhere: in Visual Studio, Rider, VS Code, on the command line or in your build pipeline.

    - - -
    -
    -
    CalculatorTests.cs
    -
    using NUnit.Framework;
    -public class CalculatorTests
    -{
    -    [TestCase(2, 3, 5)]
    -    [TestCase(-1, 1, 0)]
    -    public void Add_ReturnsSum(int a, int b, int expected)
    -    {
    -        var result = new Calculator().Add(a, b);
    -        Assert.That(result, Is.EqualTo(expected));
    -    }
    -}
    -
    -
    -
    -
    - -
    - -

    Getting started

    -

    Create a test project in the tool you already use, or add NUnit to an existing one.

    - -
    - - - - - - - -
    -
    -

    Questions? Ask in GitHub Discussions · NUnit on GitHub · Help improve these docs · License

    -
    diff --git a/docs/index.md b/docs/index.md index 9d2f0f704..b81db07e4 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,25 +1,194 @@ -# NUnit Documentation Site - - -> [!TIP] -> We are working on a new home page for these docs. Try the preview, and -> share your feedback in [this discussion](https://github.com/nunit/docs/discussions/1023). - - -This web site contains the documentation for all active NUnit projects as well as developer documentation for those -working on NUnit or wishing to do so. - -## User Documentation - -* [NUnit](xref:intro) covers the core tools of NUnit, including the framework, NUnitLite, and the console runner. -* [NUnit VS Adapter](xref:vstestadapterinstallation) covers the test adapters for Visual Studio and .Net. -* [NUnit Analyzers](xref:nunitanalyzers) covers the NUnit Analyzers. -* [NUnit VS Test Generator](xref:vstestgenerator) covers the Visual Studio extension for generating tests in both NUnit - V2 and V3. -* [NUnit Xamarin Runners](xref:xamarinrunners) covers the NUnit test runners for Xamarin and mobile devices. -* [NUnit Engine](xref:nunitengine) covers the NUnit Engine, the central component all test runners are built around. - -## Developer Documentation - -* [Team practices](xref:teampractices) describe how NUnit works and how our teams work. -* [Specifications](xref:specifications) are descriptions of features we plan to add. +--- +title: NUnit Documentation +_disableAffix: true +_disableContribution: true +_description: Documentation for NUnit, the open-source unit-testing framework for all .NET languages. +--- + + +
    +
    +
    +

    NUnit documentation

    +

    Write tests you can trust, for any .NET code

    +

    NUnit is the open-source unit-testing framework for .NET. Write a test in a few lines, get warnings about mistakes as you type from the NUnit Analyzers, run it with many sets of data, and run it anywhere: in Visual Studio, Rider, VS Code, on the command line or in your build pipeline.

    + + +
    +
    +
    CalculatorTests.cs
    +
    using NUnit.Framework;
    +public class CalculatorTests
    +{
    +    [TestCase(2, 3, 5)]
    +    [TestCase(-1, 1, 0)]
    +    public void Add_ReturnsSum(int a, int b, int expected)
    +    {
    +        var result = new Calculator().Add(a, b);
    +        Assert.That(result, Is.EqualTo(expected));
    +    }
    +}
    +
    +
    +
    +
    + +
    + +

    Getting started

    +

    Create a test project in the tool you already use, or add NUnit to an existing one.

    + +
    + + + + + + + +
    +
    +

    Questions? Ask in GitHub Discussions · NUnit on GitHub · Help improve these docs · License

    +
    diff --git a/docs/styles/main.js b/docs/styles/main.js index 15ecb0d46..6dc4abafd 100644 --- a/docs/styles/main.js +++ b/docs/styles/main.js @@ -1,21 +1,2 @@ var currentYear= new Date().getFullYear(); document.getElementById("currentYear").innerHTML = currentYear; - -// Switching between the classic (index.md) and the new (home.md) home page. -// The choice is remembered per browser, so the site root opens the layout the reader picked last. -(function () { - var key = "nunit-docs-home-layout"; - function read() { try { return localStorage.getItem(key); } catch (e) { return null; } } - function write(value) { try { localStorage.setItem(key, value); } catch (e) { } } - - document.addEventListener("click", function (e) { - var link = e.target.closest ? e.target.closest("a[data-nh-layout]") : null; - if (link) write(link.getAttribute("data-nh-layout")); - }); - - var rel = document.querySelector('meta[name="docfx:rel"]'); - var atRoot = rel && rel.getAttribute("content") === "" && /\/(index\.html)?$/.test(location.pathname); - if (atRoot && read() === "new" && !/[?&]classic\b/.test(location.search)) { - location.replace("home.html" + location.hash); - } -})(); diff --git a/docs/toc.yml b/docs/toc.yml index 4aa0b672c..6f7c56bc6 100644 --- a/docs/toc.yml +++ b/docs/toc.yml @@ -1,4 +1,6 @@ -- name: Articles - href: articles/ -- name: API Reference - href: api/ \ No newline at end of file +- name: Articles + href: articles/ +- name: API Reference + href: api/ +- name: Classic Home + href: classic.md From 11ff51e7954f845c86079a76cb4c1e04fcacf5c5 Mon Sep 17 00:00:00 2001 From: Terje Sandstrom Date: Sun, 27 Sep 2026 15:02:57 +0200 Subject: [PATCH 08/11] Add a Setup and Teardown guide A user guide covering [SetUp]/[TearDown], [OneTimeSetUp]/ [OneTimeTearDown] and [SetUpFixture]: what each is for, how to choose, the order everything runs in, what happens when setup fails, and how constructors, IDisposable and FixtureLifeCycle relate. Code samples are tested in the snippets project. Linked from the Writing tests card, the "Setup and cleanup" chip, the Writing Tests menu and the Ordinary tests guide. Co-Authored-By: Claude Opus 5.5 --- .../nunit/writing-tests/ordinary-tests.md | 1 + .../nunit/writing-tests/setup-and-teardown.md | 117 +++++++++++++++ docs/articles/nunit/writing-tests/toc.yml | 2 + docs/index.md | 3 +- .../SetUpTearDownGuideExamples.cs | 134 ++++++++++++++++++ 5 files changed, 256 insertions(+), 1 deletion(-) create mode 100644 docs/articles/nunit/writing-tests/setup-and-teardown.md create mode 100644 docs/snippets/Snippets.NUnit/SetUpTearDownGuideExamples.cs diff --git a/docs/articles/nunit/writing-tests/ordinary-tests.md b/docs/articles/nunit/writing-tests/ordinary-tests.md index e4e8bd50e..d27c7d892 100644 --- a/docs/articles/nunit/writing-tests/ordinary-tests.md +++ b/docs/articles/nunit/writing-tests/ordinary-tests.md @@ -32,6 +32,7 @@ When several tests need the same starting point, move the common code into a met Use [`[TearDown]`](xref:attribute-teardown) for cleanup after each test, and [`[OneTimeSetUp]`](xref:attribute-onetimesetup) for expensive setup that should run only once for the whole class. +[Setup and Teardown](xref:setupandteardownguide) explains all the options and when to use each one. ## Next steps diff --git a/docs/articles/nunit/writing-tests/setup-and-teardown.md b/docs/articles/nunit/writing-tests/setup-and-teardown.md new file mode 100644 index 000000000..42a97b4a0 --- /dev/null +++ b/docs/articles/nunit/writing-tests/setup-and-teardown.md @@ -0,0 +1,117 @@ +--- +uid: setupandteardownguide +--- + +# Setup and Teardown + +Most tests need something prepared before they run: an object to test, a temporary folder, a database connection. Many +also need something cleaned up afterwards. NUnit lets you put this code in separate methods, so each test only +contains what it is actually testing. + +There are three levels, depending on how often the code should run: + +| Attribute | Runs | Use it for | +|---|---|---| +| [`[SetUp]`](xref:attribute-setup) | Before **each** test | State that every test needs a fresh copy of | +| [`[TearDown]`](xref:attribute-teardown) | After **each** test | Cleaning up what `[SetUp]` or the test created | +| [`[OneTimeSetUp]`](xref:attribute-onetimesetup) | **Once**, before all tests in the class | Expensive resources that the tests can share | +| [`[OneTimeTearDown]`](xref:attribute-onetimeteardown) | **Once**, after all tests in the class | Releasing those shared resources | +| [`[SetUpFixture]`](xref:attribute-setupfixture) | **Once** for a whole namespace, or the whole test assembly | Resources that many test classes share, such as a test server | + +## Before and after each test: [SetUp] and [TearDown] + +A method marked `[SetUp]` runs before every test in the class, and a method marked `[TearDown]` runs after every +test. This is the one to use by default: each test starts from the same, clean state, and tests can't affect each +other. + +[!code-csharp[PerTestSetUpTearDown](~/snippets/Snippets.NUnit/SetUpTearDownGuideExamples.cs#PerTestSetUpTearDown)] + +`[TearDown]` also runs when the test fails, and even when `[SetUp]` itself failed halfway. Write it so that it copes +with things that were never created, like the `Directory.Exists` check above. + +## Once for all tests in a class: [OneTimeSetUp] and [OneTimeTearDown] + +A method marked `[OneTimeSetUp]` runs once, before the first test in the class, and `[OneTimeTearDown]` runs once, +after the last one. Use them for things that are slow to create, such as loading data or starting a service, and that +the tests can safely share. + +You can combine the levels. In this example, the product catalog is expensive and only read by the tests, so it is +created once. The shopping cart is cheap and changed by every test, so each test gets a new one: + +[!code-csharp[PerFixtureOneTimeSetUp](~/snippets/Snippets.NUnit/SetUpTearDownGuideExamples.cs#PerFixtureOneTimeSetUp)] + +> [!WARNING] +> Anything created in `[OneTimeSetUp]` is shared by all tests in the class. If one test changes it, the next test sees +> the change, and the result can depend on the order the tests run in. Only share things the tests don't modify, or +> reset them in `[SetUp]`. + +## Once for many classes: [SetUpFixture] + +When several test classes need the same expensive setup, such as a test database or a web server, put it in a class +marked `[SetUpFixture]`. Its `[OneTimeSetUp]` method runs once, before any test in the **same namespace** and in its +child namespaces, and its `[OneTimeTearDown]` runs once after all of them. + +[!code-csharp[SetUpFixtureForNamespace](~/snippets/Snippets.NUnit/SetUpTearDownGuideExamples.cs#SetUpFixtureForNamespace)] + +- The namespace decides which tests the setup fixture covers. A setup fixture **outside any namespace** covers the + whole test assembly. +- The class must be public and have a default constructor, or be static. +- A setup fixture can only have `[OneTimeSetUp]` and `[OneTimeTearDown]` methods, not `[SetUp]` and `[TearDown]`. + +## Which one should I use? + +1. **Does each test need its own, fresh copy?** Use `[SetUp]` and `[TearDown]`. This is the safest choice, so start + here. +2. **Is it slow to create, and do the tests only read it?** Use `[OneTimeSetUp]` and `[OneTimeTearDown]` in the test + class. +3. **Do several test classes need it?** Use a `[SetUpFixture]` in the namespace that contains those classes, or outside + any namespace for the whole assembly. +4. **Does every test need to clean up after itself, even when it fails?** Put the cleanup in `[TearDown]` or + `[OneTimeTearDown]`, not at the end of the test, because the rest of a failing test doesn't run. + +## The order everything runs in + +For a test class in a namespace with a setup fixture, NUnit runs: + +1. `[OneTimeSetUp]` of the setup fixture outside any namespace, if there is one +2. `[OneTimeSetUp]` of the setup fixtures for the namespace, from the outermost namespace inward +3. `[OneTimeSetUp]` of the test class +4. For **each** test: `[SetUp]`, then the test, then `[TearDown]` +5. `[OneTimeTearDown]` of the test class +6. `[OneTimeTearDown]` of the setup fixtures, in the reverse order of step 1 and 2 + +With inheritance, setup methods in a base class run before those in the derived class, and teardown methods in the +derived class run before those in the base class. If a derived class overrides a base class setup method, only the +override runs, so give the methods different names instead. + +If a class has several methods with the same attribute, their order is not defined. Use one method per level, or +spread them over base and derived classes. + +## When setup fails + +- If **`[SetUp]` fails**, the test doesn't run and is reported as failed. `[TearDown]` still runs. +- If **`[OneTimeSetUp]` fails**, none of the tests in the class run, and they are all reported as failed, with the setup + error as the reason. `[OneTimeTearDown]` still runs. +- The same applies to a `[SetUpFixture]`: if its `[OneTimeSetUp]` fails, none of the tests it covers run. + +## Good to know + +- **Async setup:** all of these methods can be `async` and return a `Task`. NUnit waits for them to finish. +- **Constructors and `IDisposable`:** by default, NUnit creates one instance of the test class for all its tests, so + the constructor runs once, like `[OneTimeSetUp]`. If the class implements `IDisposable`, NUnit calls `Dispose` + when it is done with the instance. `[SetUp]` and `[TearDown]` make the intent clearer, and work the same way with + every life cycle. +- **A new instance for each test:** with + [`[FixtureLifeCycle(LifeCycle.InstancePerTestCase)]`](xref:attribute-fixturelifecycle), NUnit creates a new instance + of the test class for every test. Fields can then never leak between tests, which also helps when tests run in + [parallel](xref:attribute-parallelizable). `[OneTimeSetUp]` and `[OneTimeTearDown]` must be static in that case. +- **The current test:** inside `[SetUp]` and `[TearDown]`, [`TestContext.CurrentContext`](xref:testcontext) describes + the test that is about to run or has just run. In `[TearDown]` you can check its result, for example to save extra + logs only when a test failed. + +## See also + +- The [SetUp](xref:attribute-setup), [TearDown](xref:attribute-teardown), [OneTimeSetUp](xref:attribute-onetimesetup), + [OneTimeTearDown](xref:attribute-onetimeteardown) and [SetUpFixture](xref:attribute-setupfixture) reference pages +- [SetUp and TearDown](setup-teardown/index.md), with more details on inheritance +- [FixtureLifeCycle](xref:attribute-fixturelifecycle) diff --git a/docs/articles/nunit/writing-tests/toc.yml b/docs/articles/nunit/writing-tests/toc.yml index 126745d6d..b085f88ab 100644 --- a/docs/articles/nunit/writing-tests/toc.yml +++ b/docs/articles/nunit/writing-tests/toc.yml @@ -1,5 +1,7 @@ - name: Ordinary Tests href: ordinary-tests.md +- name: Setup and Teardown + href: setup-and-teardown.md - name: Data Driven Tests href: data-driven-tests.md - name: Automating Tests diff --git a/docs/index.md b/docs/index.md index b81db07e4..9c03d40a8 100644 --- a/docs/index.md +++ b/docs/index.md @@ -26,7 +26,7 @@ _description: Documentation for NUnit, the open-source unit-testing framework fo

    From a single test to tests that run with hundreds of inputs.

    • Ordinary tests
    • +
    • Setup and teardown
    • Data driven tests
    • Automating tests
    • Checking several things at once
    • diff --git a/docs/snippets/Snippets.NUnit/SetUpTearDownGuideExamples.cs b/docs/snippets/Snippets.NUnit/SetUpTearDownGuideExamples.cs new file mode 100644 index 000000000..5b0c23523 --- /dev/null +++ b/docs/snippets/Snippets.NUnit/SetUpTearDownGuideExamples.cs @@ -0,0 +1,134 @@ +using NUnit.Framework; + +#pragma warning disable CA1822 + +namespace Snippets.NUnit.SetUpTearDownGuide.PerTest +{ + #region PerTestSetUpTearDown + public class ReportWriterTests + { + private string _folder = null!; + + [SetUp] + public void CreateFolder() + { + // Runs before each test, so every test gets its own empty folder. + _folder = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + Directory.CreateDirectory(_folder); + } + + [TearDown] + public void DeleteFolder() + { + // Runs after each test, also when the test failed. + if (Directory.Exists(_folder)) + Directory.Delete(_folder, recursive: true); + } + + [Test] + public void Write_CreatesReportFile() + { + File.WriteAllText(Path.Combine(_folder, "report.txt"), "Hello"); + Assert.That(Directory.GetFiles(_folder), Has.Length.EqualTo(1)); + } + + [Test] + public void Folder_StartsEmpty() + { + Assert.That(Directory.GetFiles(_folder), Is.Empty); + } + } + #endregion +} + +namespace Snippets.NUnit.SetUpTearDownGuide.PerFixture +{ + public sealed class ProductCatalog : IDisposable + { + public static ProductCatalog LoadFromDatabase() => new(); + public IReadOnlyList Products { get; } = ["Apple", "Banana", "Cherry"]; + public void Dispose() { } + } + + public class ShoppingCart + { + private readonly List _items = []; + public IReadOnlyList Items => _items; + public void Add(string product) => _items.Add(product); + } + + #region PerFixtureOneTimeSetUp + public class ShoppingCartTests + { + private ProductCatalog _catalog = null!; + private ShoppingCart _cart = null!; + + [OneTimeSetUp] + public void LoadCatalog() + { + // Expensive, and only read by the tests: create it once for all of them. + _catalog = ProductCatalog.LoadFromDatabase(); + } + + [OneTimeTearDown] + public void DisposeCatalog() + { + _catalog.Dispose(); + } + + [SetUp] + public void CreateCart() + { + // Cheap, and the tests change it: create a fresh one for each test. + _cart = new ShoppingCart(); + } + + [Test] + public void Add_PutsProductInCart() + { + _cart.Add(_catalog.Products[0]); + Assert.That(_cart.Items, Has.Count.EqualTo(1)); + } + + [Test] + public void NewCart_IsEmpty() + { + Assert.That(_cart.Items, Is.Empty); + } + } + #endregion +} + +#region SetUpFixtureForNamespace +namespace Snippets.NUnit.SetUpTearDownGuide.Integration +{ + [SetUpFixture] + public class IntegrationTestEnvironment + { + public static string ConnectionString { get; private set; } = ""; + + [OneTimeSetUp] + public void StartServices() + { + // Runs once, before any test in this namespace and its child namespaces. + ConnectionString = "Server=localhost;Database=Tests"; + } + + [OneTimeTearDown] + public void StopServices() + { + // Runs once, after all tests in this namespace have finished. + ConnectionString = ""; + } + } + + public class OrderRepositoryTests + { + [Test] + public void ConnectionString_IsAvailable() + { + Assert.That(IntegrationTestEnvironment.ConnectionString, Does.Contain("Database=Tests")); + } + } +} +#endregion From 6e0d9c23ace19ea028c9a9f195e7bb72e698e793 Mon Sep 17 00:00:00 2001 From: Terje Sandstrom Date: Mon, 28 Sep 2026 21:01:29 +0200 Subject: [PATCH 09/11] Rename the setup guide to Preparing and Cleaning Up Tests Co-Authored-By: Claude Opus 5.5 --- docs/articles/nunit/writing-tests/ordinary-tests.md | 2 +- docs/articles/nunit/writing-tests/setup-and-teardown.md | 7 ++++--- docs/articles/nunit/writing-tests/toc.yml | 2 +- docs/index.md | 4 ++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/articles/nunit/writing-tests/ordinary-tests.md b/docs/articles/nunit/writing-tests/ordinary-tests.md index d27c7d892..b2cb7993b 100644 --- a/docs/articles/nunit/writing-tests/ordinary-tests.md +++ b/docs/articles/nunit/writing-tests/ordinary-tests.md @@ -32,7 +32,7 @@ When several tests need the same starting point, move the common code into a met Use [`[TearDown]`](xref:attribute-teardown) for cleanup after each test, and [`[OneTimeSetUp]`](xref:attribute-onetimesetup) for expensive setup that should run only once for the whole class. -[Setup and Teardown](xref:setupandteardownguide) explains all the options and when to use each one. +[Preparing and Cleaning Up Tests](xref:setupandteardownguide) explains all the options and when to use each one. ## Next steps diff --git a/docs/articles/nunit/writing-tests/setup-and-teardown.md b/docs/articles/nunit/writing-tests/setup-and-teardown.md index 42a97b4a0..a212e134b 100644 --- a/docs/articles/nunit/writing-tests/setup-and-teardown.md +++ b/docs/articles/nunit/writing-tests/setup-and-teardown.md @@ -2,11 +2,12 @@ uid: setupandteardownguide --- -# Setup and Teardown +# Preparing and Cleaning Up Tests Most tests need something prepared before they run: an object to test, a temporary folder, a database connection. Many -also need something cleaned up afterwards. NUnit lets you put this code in separate methods, so each test only -contains what it is actually testing. +also need something cleaned up afterwards. NUnit lets you put this code in separate methods, marked with +`[SetUp]`, `[TearDown]`, `[OneTimeSetUp]`, `[OneTimeTearDown]` or `[SetUpFixture]`, so each test only contains +what it is actually testing. There are three levels, depending on how often the code should run: diff --git a/docs/articles/nunit/writing-tests/toc.yml b/docs/articles/nunit/writing-tests/toc.yml index b085f88ab..22ca39122 100644 --- a/docs/articles/nunit/writing-tests/toc.yml +++ b/docs/articles/nunit/writing-tests/toc.yml @@ -1,6 +1,6 @@ - name: Ordinary Tests href: ordinary-tests.md -- name: Setup and Teardown +- name: Preparing and Cleaning Up Tests href: setup-and-teardown.md - name: Data Driven Tests href: data-driven-tests.md diff --git a/docs/index.md b/docs/index.md index 9c03d40a8..9be7ca656 100644 --- a/docs/index.md +++ b/docs/index.md @@ -26,7 +26,7 @@ _description: Documentation for NUnit, the open-source unit-testing framework fo

      From a single test to tests that run with hundreds of inputs.

      • Ordinary tests
      • -
      • Setup and teardown
      • +
      • Preparing and cleaning up
      • Data driven tests
      • Automating tests
      • Checking several things at once
      • From 61358050487b8697b5ce135845eecbaae4ac3172 Mon Sep 17 00:00:00 2001 From: Terje Sandstrom Date: Tue, 29 Sep 2026 20:21:02 +0200 Subject: [PATCH 10/11] Moved VSTestGenerator to archive, Upgrade V5 to News and setup a bit down on writing menu --- docs/articles/archive.md | 1 + docs/articles/nunit/writing-tests/toc.yml | 4 ++-- docs/articles/toc.yml | 6 +++--- docs/index.md | 5 ++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/articles/archive.md b/docs/articles/archive.md index 66944772f..de537ccff 100644 --- a/docs/articles/archive.md +++ b/docs/articles/archive.md @@ -29,6 +29,7 @@ For the current version, start at the [documentation home page](../index.md). ## Tools that are no longer maintained * [NUnit Xamarin Runners](xref:xamarinrunners) +* [NUnit VS Test Generator](xref:vstestgenerator) * [NUnit Project Editor](https://github.com/nunit-legacy/nunit-project-editor/wiki/Project-Editor) ## Older release notes diff --git a/docs/articles/nunit/writing-tests/toc.yml b/docs/articles/nunit/writing-tests/toc.yml index 22ca39122..ecb896df6 100644 --- a/docs/articles/nunit/writing-tests/toc.yml +++ b/docs/articles/nunit/writing-tests/toc.yml @@ -1,11 +1,11 @@ - name: Ordinary Tests href: ordinary-tests.md -- name: Preparing and Cleaning Up Tests - href: setup-and-teardown.md - name: Data Driven Tests href: data-driven-tests.md - name: Automating Tests href: automating-tests.md +- name: Preparing and Cleaning Up Tests + href: setup-and-teardown.md - name: Tests That Depend on Other Tests href: dependent-tests.md - name: Flaky and Slow Tests diff --git a/docs/articles/toc.yml b/docs/articles/toc.yml index 8000f5083..51c8368eb 100644 --- a/docs/articles/toc.yml +++ b/docs/articles/toc.yml @@ -7,9 +7,6 @@ - name: NUnit Engine href: nunit-engine/toc.yml topicHref: nunit-engine/Index.md -- name: VS Test Generator - href: vs-test-generator/toc.yml - topicHref: vs-test-generator/Visual-Studio-Test-Generator.md - name: NUnit Analyzers href: nunit-analyzers/toc.yml topicHref: nunit-analyzers/NUnit-Analyzers.md @@ -51,6 +48,9 @@ - name: NUnit Xamarin Runners href: xamarin-runners/toc.yml topicHref: xamarin-runners/index.md + - name: VS Test Generator + href: vs-test-generator/toc.yml + topicHref: vs-test-generator/Visual-Studio-Test-Generator.md - name: NUnit Project Editor href: https://github.com/nunit-legacy/nunit-project-editor/wiki/Project-Editor - name: Older Release Notes diff --git a/docs/index.md b/docs/index.md index 9be7ca656..6a25d3919 100644 --- a/docs/index.md +++ b/docs/index.md @@ -91,7 +91,6 @@ public class CalculatorTests
      • In an existing project
      • Pre-release and developer builds
      • Samples
      • -
      • Upgrading to NUnit 5
      @@ -100,11 +99,11 @@ public class CalculatorTests

      Release notes for NUnit and all its tools.

    @@ -186,6 +184,7 @@ public class CalculatorTests
  • Breaking changes up to NUnit 4.0
  • Upgrading from NUnit 2 and 3
  • Xamarin runners for mobile devices
  • +
  • VS Test Generator
  • Everything in the archive
  • From 3f1b8db188c54631b6a44c383e943748aea63858 Mon Sep 17 00:00:00 2001 From: Terje Sandstrom Date: Tue, 29 Sep 2026 20:51:18 +0200 Subject: [PATCH 11/11] corrected older nunit license, pointing to MIT license at root --- docs/articles/nunit/license.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/articles/nunit/license.md b/docs/articles/nunit/license.md index 80f673251..00cc7007e 100644 --- a/docs/articles/nunit/license.md +++ b/docs/articles/nunit/license.md @@ -1,6 +1,9 @@ # NUnit License -## Copyright (c) 2009-2019 Charlie Poole, 2014-2025 Rob Prouse, 2026 Terje Sandstrom and Contributors. +> [!NOTE] +> This is the former license. Now replaced with an [MIT license](https://github.com/nunit/docs/blob/master/LICENSE.md). + +## Copyright (c) 2004-2021 Charlie Poole, Rob Prouse and Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal