diff --git a/.claude/skills/attribute-documentation/skill.md b/.claude/skills/attribute-documentation/skill.md new file mode 100644 index 000000000..c1a4c3ac4 --- /dev/null +++ b/.claude/skills/attribute-documentation/skill.md @@ -0,0 +1,244 @@ +--- +name: NUnit Attribute Documentation +description: Create and update documentation for NUnit attributes following the established template structure +--- + +# NUnit Attribute Documentation + +This skill describes how to create and update documentation for NUnit attributes. + +## Documentation Template Structure + +Each attribute documentation file in `docs/articles/nunit/writing-tests/attributes/` should follow this structure: + +````markdown +# AttributeName + +Brief description of what the attribute does. + +## Constructor + +```csharp +AttributeName(paramType paramName) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `paramName` | `Type` | Description of the parameter. Include important notes like valid ranges or default behavior. | + +## Properties + +| Property | Type | Description | Default | +|----------|------|-------------|---------| +| `PropertyName` | `Type` | Description of the property. | `defaultValue` | + +> [!NOTE] +> Version notes if applicable (e.g., "Added in **NUnit 4.5.0**"). + +## Applies To + +Use a table with checkmarks to show where the attribute can be applied: + +| Target | Supported | +|--------|-----------| +| Test Methods | ✅ | +| Test Fixtures (Classes) | ✅ | +| Assemblies | ❌ | + +Use ✅ (green checkmark) where the attribute applies, ❌ (red X) where it doesn't. + +## Example + +[!code-csharp[ExampleName](~/snippets/Snippets.NUnit/Attributes/AttributeNameExamples.cs#RegionName)] + +## Notes + +1. Important behavioral notes +2. Limitations +3. Edge cases + +## See Also + +* [Related Attribute](relatedattribute.md) +```` + +### For Parameterless Attributes + +Use a simpler "Usage" section instead of Constructor/Properties: + +````markdown +## Usage + +This is a parameterless attribute that can only be applied to [target]. + +```csharp +[AttributeName] +``` +```` + +## Workflow for Updating Attribute Documentation + +> **Repository Layout Assumption**: This workflow assumes you have cloned both repositories as siblings: +> - `/nunit/` - The NUnit framework source code ([nunit/nunit](https://github.com/nunit/nunit)) +> - `/docs/` - This documentation repository ([nunit/docs](https://github.com/nunit/docs)) +> +> Adjust paths below to match your local setup. + +### Step 1: Find the Source Code + +Search for the attribute class in the NUnit framework: + +```shell +# Find the attribute source file (adjust path to your nunit repo location) +grep -r "class AttributeNameAttribute" ../nunit --include="*.cs" +``` + +The source is typically at: +`/src/NUnitFramework/framework/Attributes/AttributeNameAttribute.cs` + +### Step 2: Analyze the Source Code + +From the source file, extract: +- Constructor parameters and their XML doc comments +- Properties with their types, descriptions, and default values +- `AttributeUsage` to determine valid targets (Class, Method, Assembly) +- Whether `Inherited = true` + +### Step 3: Check for Existing Unit Tests + +```shell +# Find unit tests for the attribute (adjust path to your nunit repo location) +grep -r "AttributeName" ../nunit/src/NUnitFramework/tests --include="*.cs" +``` + +Tests are typically at: +`/src/NUnitFramework/tests/Attributes/AttributeNameAttributeTests.cs` + +Unit tests provide good examples of usage patterns and edge cases. + +### Step 4: Create Snippet File + +Create a new file at: +`docs/snippets/Snippets.NUnit/Attributes/AttributeNameAttributeExamples.cs` + +Follow this pattern: + +```csharp +using NUnit.Framework; + +namespace Snippets.NUnit.Attributes +{ + public class AttributeNameAttributeExamples + { + #region ExampleName + [TestFixture] + public class ExampleTests + { + [Test] + public void ExampleTest() + { + // Test code that demonstrates the attribute + Assert.That(true, Is.True); + } + } + #endregion + + #region AnotherExample + // More examples... + #endregion + } +} +``` + +Key points: +- Use `#region` / `#endregion` to mark code sections +- Region names are used in the markdown reference: `#RegionName` +- Tests must actually pass - avoid stub code that doesn't work +- If you need helper classes, make them private nested classes + +### Step 5: Update the Markdown Documentation + +Reference snippets using DocFX syntax: + +```markdown +[!code-csharp[ExampleName](~/snippets/Snippets.NUnit/Attributes/AttributeNameExamples.cs#ExampleName)] +``` + +### Step 6: Build and Test + +Always verify the snippets compile and tests pass. From the docs repository root: + +```shell +# Build +dotnet build docs/snippets/Snippets.slnx + +# Run all tests +dotnet test docs/snippets/Snippets.slnx --no-build + +# Run specific tests +dotnet test docs/snippets/Snippets.slnx --no-build --filter "FullyQualifiedName~AttributeNameExamples" --verbosity normal +``` + +### Step 7: Update the Plan File + +Mark the attribute as done in `docs-improvement-plan.md`: + +```markdown +| AttributeName | Done | Brief notes about what was added | +``` + +## Common Attribute Patterns + +### Attributes with Constructor Parameters Only +Examples: `Retry`, `Repeat`, `MaxTime`, `Order` + +### Attributes with Properties +Examples: `Retry` (has `RetryExceptions`), `TestCase` (has many named parameters) + +### Parameterless Attributes +Examples: `SingleThreaded`, `NonParallelizable`, `Combinatorial` + +### Enum-based Attributes +Examples: `Parallelizable` (takes `ParallelScope`), `Apartment` (takes `ApartmentState`) + +Document the enum values in a table. + +## Command Line Documentation Guidelines + +When documenting command line usage: + +1. **Use appropriate code fences** - Use ` ```shell ` for command line examples, not ` ```bash `, ` ```text `, or untagged code blocks. + +2. **Prioritize `dotnet test`** - Always mention `dotnet test` before the NUnit console runner, as it is used far more frequently. + +3. **Include runsettings equivalents** - When mentioning console runner options (like `--timeout`, `--workers`, etc.), note that these settings can also be configured for `dotnet test` via the NUnit adapter's `.runsettings` file. + +Example: + +````markdown +## Command Line Usage + +```shell +# dotnet test (via NUnit adapter) +dotnet test --filter "TestCategory=Fast" + +# Or via runsettings +dotnet test --settings test.runsettings + +# NUnit Console Runner +nunit3-console MyTests.dll --where "cat == Fast" +``` +```` + +## Quality Checklist + +Before marking an attribute as done: + +- [ ] Constructor section with parameter table (if applicable) +- [ ] Properties section with defaults (if applicable) +- [ ] At least one working code example in snippets folder +- [ ] Examples build without errors +- [ ] Example tests pass +- [ ] Notes section with important behavioral info +- [ ] See Also section with related attributes +- [ ] Plan file updated diff --git a/cSpell.json b/cSpell.json index c21ba1af5..1c765defe 100644 --- a/cSpell.json +++ b/cSpell.json @@ -33,6 +33,7 @@ "Parallelizable", "parallelization", "paramref", + "parameterless", "PDBs", "Pluggable", "prefilter", diff --git a/docs/articles/nunit-analyzers/NUnit1008.md b/docs/articles/nunit-analyzers/NUnit1008.md index 518228c3b..22bb423a5 100644 --- a/docs/articles/nunit-analyzers/NUnit1008.md +++ b/docs/articles/nunit-analyzers/NUnit1008.md @@ -31,7 +31,7 @@ In `AssemblyInfo.cs`: ### Explanation -`ParallelScope.Self` [only applies to classes and methods](xref:parallelizableattribute), +`ParallelScope.Self` [only applies to classes and methods](xref:attribute-parallelizable), not to assemblies. ### Fix diff --git a/docs/articles/nunit-analyzers/NUnit1010.md b/docs/articles/nunit-analyzers/NUnit1010.md index 32aeba686..623b4b8f7 100644 --- a/docs/articles/nunit-analyzers/NUnit1010.md +++ b/docs/articles/nunit-analyzers/NUnit1010.md @@ -36,7 +36,7 @@ public void NUnit1010SampleTest() In the sample above, `ParallelScope.Fixtures` is specified. However, in the context of a test method, a scope of `Fixtures` does not make sense. This scope [only applies at the -assembly or class level](xref:parallelizableattribute). +assembly or class level](xref:attribute-parallelizable). ### Fix diff --git a/docs/articles/nunit-analyzers/NUnit1015.md b/docs/articles/nunit-analyzers/NUnit1015.md index 5fd08d949..327ad2d11 100644 --- a/docs/articles/nunit-analyzers/NUnit1015.md +++ b/docs/articles/nunit-analyzers/NUnit1015.md @@ -48,7 +48,7 @@ class DivideCases In the sample above, the class `DivideCases` does not implement `IEnumerable` nor `IAsyncEnumerable` However, source types specified by `TestCaseSource` -[must implement `IEnumerable` or `IAsyncEnumerable`](xref:testcasesourceattribute). +[must implement `IEnumerable` or `IAsyncEnumerable`](xref:attribute-testcasesource). ### Fix diff --git a/docs/articles/nunit-analyzers/NUnit1016.md b/docs/articles/nunit-analyzers/NUnit1016.md index 1060d2517..95d2df3f5 100644 --- a/docs/articles/nunit-analyzers/NUnit1016.md +++ b/docs/articles/nunit-analyzers/NUnit1016.md @@ -50,7 +50,7 @@ class DivideCases : IEnumerable In the sample above, the class `DivideCases` does not have a default constructor - i.e. a constructor with no parameters. However, source types specified by `TestCaseSource` -[must have a default constructor](xref:testcasesourceattribute). +[must have a default constructor](xref:attribute-testcasesource). ### Fix diff --git a/docs/articles/nunit-analyzers/NUnit1017.md b/docs/articles/nunit-analyzers/NUnit1017.md index d5ebd7e69..84b326a63 100644 --- a/docs/articles/nunit-analyzers/NUnit1017.md +++ b/docs/articles/nunit-analyzers/NUnit1017.md @@ -45,7 +45,7 @@ public class MyTestClass In the sample above, `DivideCases` is not a `static` field. However, sources specified by `TestCaseSource` -[must be `static`](xref:testcasesourceattribute). +[must be `static`](xref:attribute-testcasesource). ### Fix diff --git a/docs/articles/nunit-analyzers/NUnit1019.md b/docs/articles/nunit-analyzers/NUnit1019.md index b49bd7b6e..2aa691e12 100644 --- a/docs/articles/nunit-analyzers/NUnit1019.md +++ b/docs/articles/nunit-analyzers/NUnit1019.md @@ -40,7 +40,7 @@ In the sample above, the source specified by `TestCaseSource` - the field `testC `I(Async)Enumerable` or a type that implements `I(Async)Enumerable`, instead it returns an `int`. However, sources specified by `TestCaseSource` -[must return an `I(Async)Enumerable` or a type that implements `I(Async)Enumerable`.](xref:testcasesourceattribute). +[must return an `I(Async)Enumerable` or a type that implements `I(Async)Enumerable`.](xref:attribute-testcasesource). ### Fix diff --git a/docs/articles/nunit-analyzers/NUnit1022.md b/docs/articles/nunit-analyzers/NUnit1022.md index 9c23bff6a..c12ff9bd9 100644 --- a/docs/articles/nunit-analyzers/NUnit1022.md +++ b/docs/articles/nunit-analyzers/NUnit1022.md @@ -39,7 +39,7 @@ public class MyTestClass In the sample above, `Numbers` is not a `static` property. -However, sources specified by `ValueSource` [must be `static`](xref:valuesource). +However, sources specified by `ValueSource` [must be `static`](xref:attribute-valuesource). ### Fix diff --git a/docs/articles/nunit-analyzers/NUnit1024.md b/docs/articles/nunit-analyzers/NUnit1024.md index 03e3cd3b4..95042b4e5 100644 --- a/docs/articles/nunit-analyzers/NUnit1024.md +++ b/docs/articles/nunit-analyzers/NUnit1024.md @@ -40,7 +40,7 @@ In the sample above, the source specified by `ValueSource` - the field `testCase `I(Async)Enumerable` or a type that implements `I(Async)Enumerable`, instead it returns an `int`. However, sources specified by `ValueSource` -[must return an `I(Async)Enumerable` or a type that implements `I(Async)Enumerable`.](xref:valuesource). +[must return an `I(Async)Enumerable` or a type that implements `I(Async)Enumerable`.](xref:attribute-valuesource). ### Fix diff --git a/docs/articles/nunit/Towards-NUnit4.md b/docs/articles/nunit/Towards-NUnit4.md index b9ad8773c..76b806d8e 100644 --- a/docs/articles/nunit/Towards-NUnit4.md +++ b/docs/articles/nunit/Towards-NUnit4.md @@ -189,7 +189,7 @@ the classic .NET Framework, it prevents `finally` clauses and other cleanup rout Cancellation is supposed to be done in a cooperative way. -To achieve this in NUnit v4, we introduce a [CancelAfter Attribute](./writing-tests/attributes/cancelafter.md) +To achieve this in NUnit v4, we introduce a [CancelAfter Attribute](xref:attribute-cancelafter) ## Nullability diff --git a/docs/articles/nunit/extending-nunit/Execution-Hooks.md b/docs/articles/nunit/extending-nunit/Execution-Hooks.md index 092b0fc05..bd1d04362 100644 --- a/docs/articles/nunit/extending-nunit/Execution-Hooks.md +++ b/docs/articles/nunit/extending-nunit/Execution-Hooks.md @@ -1,116 +1,116 @@ -# Execution Hooks - -Added in **NUnit 4.5** - -Execution Hooks provide structured, ordered, exception-aware extension points around each core test lifecycle phase. They complement (and can wrap) [Action Attributes](Action-Attributes.md) while staying focused on execution. - -Key differences to Action Attributes: - -- Execution Hooks focus on the immediate test invocation phases (before/after setup, test, teardown and test action callbacks). -- Only overridden hook methods are registered, keeping runtime overhead low. -- After-hooks run in reverse order (stack behavior) to naturally unwind resources paired with the corresponding before-hooks. - -## When to use Execution Hooks - -Execution Hooks should be used when there is a need to: - -- Time, log, trace or audit test phases precisely. -- Inject state around each SetUp/TearDown. -- Pair resource acquisition/release symmetrically (BeforeX/AfterX). -- React to exceptions thrown by setup, test or teardown methods. -- Integrate with or augment existing Action Attributes behavior at a finer granularity. - -## Getting started - -Derive from `ExecutionHookAttribute` and override only the methods that are relevant: - -| Method | Triggered immediately | Applies To | -|--------|-----------------------|------------| -| `BeforeEverySetUpHook` | Before each `[SetUp]` or `[OneTimeSetUp]` method | All fixture & base fixture setup methods | -| `AfterEverySetUpHook` | After each `[SetUp]` or `[OneTimeSetUp]` method | All fixture & base fixture setup methods | -| `BeforeTestHook` | Before the test method | The test method | -| `AfterTestHook` | After the test method | The test method | -| `BeforeEveryTearDownHook` | Before each `[TearDown]` or `[OneTimeTearDown]` method | All fixture & base fixture teardown methods | -| `AfterEveryTearDownHook` | After each `[TearDown]` or `[OneTimeTearDown]` method | All fixture & base fixture teardown methods | -| `BeforeTestActionBeforeTestHook` | Before an `ITestAction.BeforeTest(ITest)` executes | Each applicable Action Attribute | -| `BeforeTestActionAfterTestHook` | After an `ITestAction.BeforeTest(ITest)` executes | Each applicable Action Attribute | -| `AfterTestActionBeforeTestHook` | Before an `ITestAction.AfterTest(ITest)` executes | Each applicable Action Attribute | -| `AfterTestActionAfterTestHook` | After an `ITestAction.AfterTest(ITest)` executes | Each applicable Action Attribute | - -This derived attribute can be applied at the method, class, or assembly level. - -Each hook receives a `HookData` instance: - -- `Context`: A `TestContext` snapshot (current test, properties, etc.). -- `HookedMethod`: The `MethodInfoAdapter` of the method currently executing (e.g., the specific `[SetUp]`, test, or `[TearDown]`). -- `Exception`: Non-null only for after-hooks when the hooked method threw. - -Use these fields for logging, conditional logic, or adaptive cleanup. - -## One-Time vs Per-Test Setup/TearDown - -`BeforeEverySetUpHook`/`AfterEverySetUpHook` and `BeforeEveryTearDownHook`/`AfterEveryTearDownHook` run for both per-test and one-time setup/teardown. Inside a hook, the supported way to distinguish the two is the current test context: `Context.Test.IsSuite` is `true` for [OneTimeSetUp]/[OneTimeTearDown] (suite context) and `false` for [SetUp]/[TearDown] (test method context). - -See [Example: One-Time vs Per-Test Setup and TearDown](#example-one-time-vs-per-test-setup-and-teardown) for a complete hook implementation. - -## Example: One-Time vs Per-Test Setup and TearDown - -[!code-csharp[ExecutionHookAttributeExample](~/snippets/Snippets.NUnit/ExecutionHookExamples.cs#OneTimeVsPerTestSetupTearDownExample)] - -## Example: Measure Time for Setup - -[!code-csharp[ExecutionHookAttributeExample](~/snippets/Snippets.NUnit/ExecutionHookExamples.cs#TimingHookAttribute)] - -Usage: - -[!code-csharp[ExecutionHookAttributeExample](~/snippets/Snippets.NUnit/ExecutionHookExamples.cs#Usage)] - -## Example: Logging All Phases - -[!code-csharp[ExecutionHookAttributeExample](~/snippets/Snippets.NUnit/ExecutionHookExamples.cs#LoggingAllPhases)] - -## Exception Handling - -In general: - -- If an Execution Hook throws an exception, NUnit treats it in the same way as if the hooked method had thrown it. -For example, an exception from a before/after setup hook is handled the same way as an exception from the setup method itself. -- Independent if a before hook method or the hooked method itself is throwing an exception it is always guaranteed that the after hook method is called and contains the exception details within the `HookData`. - -Behavior illustrated by hooking a test method: - -- If a `BeforeTestHook` throws, the test method body is skipped, but its `AfterTestHook` still runs (with `HookData.Exception` set) allowing cleanup/logging. -- If an `AfterTestHook` throws, NUnit still proceeds with TearDown phases (remaining hooks and teardown methods run). -- Failures inside a test body still trigger all `AfterTestHook` executions. -- Setup/TearDown exceptions are reported by the corresponding after-hook with `HookData.Exception` populated. - -## Ordering Semantics - -If multiple attributes are applied: - -- Before-hooks (`BeforeEverySetUpHook`, `BeforeTestHook`, etc.) execute in the order, attributes were applied (declaration order on the method/class/assembly). -- After-hooks execute in reverse order, enabling natural stacking: - - Attribute A before, Attribute B before - Attribute B after, then Attribute A after. -- When multiple attributes appear at different scopes (assembly, class, method), hooks from broader scopes run before narrower scopes for "before" phases, and after narrower scopes for "after" phases (as shown in sequence tests). - -## Scope: Method vs Class vs Assembly - -Because the `AttributeUsage` targets can be chosen on the derived attribute, control over where hooks can be applied is provided: - -- Method: affects only that test method. -- Class: affects all tests within the fixture and inherited base fixture methods. -- Assembly: affects every test in the assembly. - -Hooks from broader scopes wrap those from narrower scopes. For a single test method with an assembly-level and a method-level TimingHook: - -1. Assembly `BeforeTestHook` runs first. -2. Method `BeforeTestHook` runs. -3. Test executes. -4. Method `AfterTestHook` runs. -5. Assembly `AfterTestHook` runs. - -## See Also - -- [Action Attributes](~/articles/nunit/extending-nunit/Action-Attributes.md) -- [Custom Attributes](~/articles/nunit/extending-nunit/Custom-Attributes.md) -- [Framework Extensibility](~/articles/nunit/extending-nunit/Framework-Extensibility.md) +# Execution Hooks + +Added in **NUnit 4.5** + +Execution Hooks provide structured, ordered, exception-aware extension points around each core test lifecycle phase. They complement (and can wrap) [Action Attributes](Action-Attributes.md) while staying focused on execution. + +Key differences to Action Attributes: + +- Execution Hooks focus on the immediate test invocation phases (before/after setup, test, teardown and test action callbacks). +- Only overridden hook methods are registered, keeping runtime overhead low. +- After-hooks run in reverse order (stack behavior) to naturally unwind resources paired with the corresponding before-hooks. + +## When to use Execution Hooks + +Execution Hooks should be used when there is a need to: + +- Time, log, trace or audit test phases precisely. +- Inject state around each SetUp/TearDown. +- Pair resource acquisition/release symmetrically (BeforeX/AfterX). +- React to exceptions thrown by setup, test or teardown methods. +- Integrate with or augment existing Action Attributes behavior at a finer granularity. + +## Getting started + +Derive from `ExecutionHookAttribute` and override only the methods that are relevant: + +| Method | Triggered immediately | Applies To | +|--------|-----------------------|------------| +| `BeforeEverySetUpHook` | Before each `[SetUp]` or `[OneTimeSetUp]` method | All fixture & base fixture setup methods | +| `AfterEverySetUpHook` | After each `[SetUp]` or `[OneTimeSetUp]` method | All fixture & base fixture setup methods | +| `BeforeTestHook` | Before the test method | The test method | +| `AfterTestHook` | After the test method | The test method | +| `BeforeEveryTearDownHook` | Before each `[TearDown]` or `[OneTimeTearDown]` method | All fixture & base fixture teardown methods | +| `AfterEveryTearDownHook` | After each `[TearDown]` or `[OneTimeTearDown]` method | All fixture & base fixture teardown methods | +| `BeforeTestActionBeforeTestHook` | Before an `ITestAction.BeforeTest(ITest)` executes | Each applicable Action Attribute | +| `BeforeTestActionAfterTestHook` | After an `ITestAction.BeforeTest(ITest)` executes | Each applicable Action Attribute | +| `AfterTestActionBeforeTestHook` | Before an `ITestAction.AfterTest(ITest)` executes | Each applicable Action Attribute | +| `AfterTestActionAfterTestHook` | After an `ITestAction.AfterTest(ITest)` executes | Each applicable Action Attribute | + +This derived attribute can be applied at the method, class, or assembly level. + +Each hook receives a `HookData` instance: + +- `Context`: A `TestContext` snapshot (current test, properties, etc.). +- `HookedMethod`: The `MethodInfoAdapter` of the method currently executing (e.g., the specific `[SetUp]`, test, or `[TearDown]`). +- `Exception`: Non-null only for after-hooks when the hooked method threw. + +Use these fields for logging, conditional logic, or adaptive cleanup. + +## One-Time vs Per-Test Setup/TearDown + +`BeforeEverySetUpHook`/`AfterEverySetUpHook` and `BeforeEveryTearDownHook`/`AfterEveryTearDownHook` run for both per-test and one-time setup/teardown. Inside a hook, the supported way to distinguish the two is the current test context: `Context.Test.IsSuite` is `true` for [OneTimeSetUp]/[OneTimeTearDown] (suite context) and `false` for [SetUp]/[TearDown] (test method context). + +See [Example: One-Time vs Per-Test Setup and TearDown](#example-one-time-vs-per-test-setup-and-teardown) for a complete hook implementation. + +## Example: One-Time vs Per-Test Setup and TearDown + +[!code-csharp[ExecutionHookAttributeExample](~/snippets/Snippets.NUnit/ExecutionHookExamples.cs#OneTimeVsPerTestSetupTearDownExample)] + +## Example: Measure Time for Setup + +[!code-csharp[ExecutionHookAttributeExample](~/snippets/Snippets.NUnit/ExecutionHookExamples.cs#TimingHookAttribute)] + +Usage: + +[!code-csharp[ExecutionHookAttributeExample](~/snippets/Snippets.NUnit/ExecutionHookExamples.cs#Usage)] + +## Example: Logging All Phases + +[!code-csharp[ExecutionHookAttributeExample](~/snippets/Snippets.NUnit/ExecutionHookExamples.cs#LoggingAllPhases)] + +## Exception Handling + +In general: + +- If an Execution Hook throws an exception, NUnit treats it in the same way as if the hooked method had thrown it. +For example, an exception from a before/after setup hook is handled the same way as an exception from the setup method itself. +- Independent if a before hook method or the hooked method itself is throwing an exception it is always guaranteed that the after hook method is called and contains the exception details within the `HookData`. + +Behavior illustrated by hooking a test method: + +- If a `BeforeTestHook` throws, the test method body is skipped, but its `AfterTestHook` still runs (with `HookData.Exception` set) allowing cleanup/logging. +- If an `AfterTestHook` throws, NUnit still proceeds with TearDown phases (remaining hooks and teardown methods run). +- Failures inside a test body still trigger all `AfterTestHook` executions. +- Setup/TearDown exceptions are reported by the corresponding after-hook with `HookData.Exception` populated. + +## Ordering Semantics + +If multiple attributes are applied: + +- Before-hooks (`BeforeEverySetUpHook`, `BeforeTestHook`, etc.) execute in the order, attributes were applied (declaration order on the method/class/assembly). +- After-hooks execute in reverse order, enabling natural stacking: + - Attribute A before, Attribute B before - Attribute B after, then Attribute A after. +- When multiple attributes appear at different scopes (assembly, class, method), hooks from broader scopes run before narrower scopes for "before" phases, and after narrower scopes for "after" phases (as shown in sequence tests). + +## Scope: Method vs Class vs Assembly + +Because the `AttributeUsage` targets can be chosen on the derived attribute, control over where hooks can be applied is provided: + +- Method: affects only that test method. +- Class: affects all tests within the fixture and inherited base fixture methods. +- Assembly: affects every test in the assembly. + +Hooks from broader scopes wrap those from narrower scopes. For a single test method with an assembly-level and a method-level TimingHook: + +1. Assembly `BeforeTestHook` runs first. +2. Method `BeforeTestHook` runs. +3. Test executes. +4. Method `AfterTestHook` runs. +5. Assembly `AfterTestHook` runs. + +## See Also + +- [Action Attributes](~/articles/nunit/extending-nunit/Action-Attributes.md) +- [Custom Attributes](~/articles/nunit/extending-nunit/Custom-Attributes.md) +- [Framework Extensibility](~/articles/nunit/extending-nunit/Framework-Extensibility.md) diff --git a/docs/articles/nunit/extending-nunit/IApplyToContext-Interface.md b/docs/articles/nunit/extending-nunit/IApplyToContext-Interface.md index 1b9c76e38..f718b305c 100644 --- a/docs/articles/nunit/extending-nunit/IApplyToContext-Interface.md +++ b/docs/articles/nunit/extending-nunit/IApplyToContext-Interface.md @@ -26,9 +26,9 @@ arguments supplied to them. They are not called after the test is run and have n The NUnit attributes that implement `IApplyToContext` are as follows: -* [`DefaultFloatingPointToleranceAttribute`](../writing-tests/attributes/defaultfloatingpointtolerance.md) -* [`ParallelizableAttribute`](../writing-tests/attributes/parallelizable.md) -* [`SetCultureAttribute`](../writing-tests/attributes/setculture.md) -* [`SetUICultureAttribute`](../writing-tests/attributes/setuiculture.md) -* [`SingleThreadedAttribute`](../writing-tests/attributes/singlethreaded.md) -* [`TimeoutAttribute`](../writing-tests/attributes/timeout.md) +* [`DefaultFloatingPointToleranceAttribute`](xref:attribute-defaultfloatingpointtolerance) +* [`ParallelizableAttribute`](xref:attribute-parallelizable) +* [`SetCultureAttribute`](xref:attribute-setculture) +* [`SetUICultureAttribute`](xref:attribute-setuiculture) +* [`SingleThreadedAttribute`](xref:attribute-singlethreaded) +* [`TimeoutAttribute`](xref:attribute-timeout) diff --git a/docs/articles/nunit/extending-nunit/IApplyToTest-Interface.md b/docs/articles/nunit/extending-nunit/IApplyToTest-Interface.md index 15d068103..5b363dd1f 100644 --- a/docs/articles/nunit/extending-nunit/IApplyToTest-Interface.md +++ b/docs/articles/nunit/extending-nunit/IApplyToTest-Interface.md @@ -37,14 +37,14 @@ if (test.RunState != RunState.NotRunnable) The following NUnit attributes implement `IApplyToTest`: -* [`CategoryAttribute`](../writing-tests/attributes/category.md) +* [`CategoryAttribute`](xref:attribute-category) * `CombiningStrategyAttribute` -* [`CultureAttribute`](../writing-tests/attributes/culture.md) -* [`ExplicitAttribute`](../writing-tests/attributes/explicit.md) -* [`IgnoreAttribute`](../writing-tests/attributes/ignore.md) -* [`OrderAttribute`](../writing-tests/attributes/order.md) -* [`PlatformAttribute`](../writing-tests/attributes/platform.md) -* [`PropertyAttribute`](../writing-tests/attributes/property.md) (and, through it, a large number of derived attributes) -* [`RequiresThreadAttribute`](../writing-tests/attributes/requiresthread.md) -* [`TestAttribute`](../writing-tests/attributes/test.md) -* [`TestFixtureAttribute`](../writing-tests/attributes/testfixture.md) +* [`CultureAttribute`](xref:attribute-culture) +* [`ExplicitAttribute`](xref:attribute-explicit) +* [`IgnoreAttribute`](xref:attribute-ignore) +* [`OrderAttribute`](xref:attribute-order) +* [`PlatformAttribute`](xref:attribute-platform) +* [`PropertyAttribute`](xref:attribute-property) (and, through it, a large number of derived attributes) +* [`RequiresThreadAttribute`](xref:attribute-requiresthread) +* [`TestAttribute`](xref:attribute-test) +* [`TestFixtureAttribute`](xref:attribute-testfixture) diff --git a/docs/articles/nunit/extending-nunit/ICommandWrapper-Interface.md b/docs/articles/nunit/extending-nunit/ICommandWrapper-Interface.md index ee89380b6..e57b46d4f 100644 --- a/docs/articles/nunit/extending-nunit/ICommandWrapper-Interface.md +++ b/docs/articles/nunit/extending-nunit/ICommandWrapper-Interface.md @@ -33,8 +33,8 @@ the implementation of `MaxTimeAttribute`. The following NUnit attributes implement the `IWrapSetUpTearDown` interface: -* [`MaxTimeAttribute`](../writing-tests/attributes/maxtime.md) -* [`RepeatAttribute`](../writing-tests/attributes/repeat.md) -* [`RetryAttribute`](../writing-tests/attributes/retry.md) +* [`MaxTimeAttribute`](xref:attribute-maxtime) +* [`RepeatAttribute`](xref:attribute-repeat) +* [`RetryAttribute`](xref:attribute-retry) The `IWrapTestMethod`interface is not currently used by any NUnit attributes. diff --git a/docs/articles/nunit/extending-nunit/IFixtureBuilder-Interface.md b/docs/articles/nunit/extending-nunit/IFixtureBuilder-Interface.md index f483c4b72..840f868f1 100644 --- a/docs/articles/nunit/extending-nunit/IFixtureBuilder-Interface.md +++ b/docs/articles/nunit/extending-nunit/IFixtureBuilder-Interface.md @@ -16,9 +16,9 @@ create it. The following NUnit attributes currently implement this interface: -* [`TestFixtureAttribute`](../writing-tests/attributes/testfixture.md) -* [`TestFixtureSourceAttribute`](../writing-tests/attributes/testfixturesource.md) -* [`SetUpFixtureAttribute`](../writing-tests/attributes/setupfixture.md) +* [`TestFixtureAttribute`](xref:attribute-testfixture) +* [`TestFixtureSourceAttribute`](xref:attribute-testfixturesource) +* [`SetUpFixtureAttribute`](xref:attribute-setupfixture) **Notes:** diff --git a/docs/articles/nunit/extending-nunit/IImplyFixture-Interface.md b/docs/articles/nunit/extending-nunit/IImplyFixture-Interface.md index 4d772a9d0..2c0e5703d 100644 --- a/docs/articles/nunit/extending-nunit/IImplyFixture-Interface.md +++ b/docs/articles/nunit/extending-nunit/IImplyFixture-Interface.md @@ -12,7 +12,7 @@ If a class contains any method with an attribute that implements this interface, TestFixture without any `TestFixture` attribute being specified. The following NUnit attributes currently implement this interface: -* [`TestAttribute`](../writing-tests/attributes/test.md) -* [`TestCaseAttribute`](../writing-tests/attributes/testcase.md) -* [`TestCaseSourceAttribute`](../writing-tests/attributes/testcasesource.md) -* [`TheoryAttribute`](../writing-tests/attributes/theory.md) +* [`TestAttribute`](xref:attribute-test) +* [`TestCaseAttribute`](xref:attribute-testcase) +* [`TestCaseSourceAttribute`](xref:attribute-testcasesource) +* [`TheoryAttribute`](xref:attribute-theory) diff --git a/docs/articles/nunit/extending-nunit/IParameterDataSource-Interface.md b/docs/articles/nunit/extending-nunit/IParameterDataSource-Interface.md index 99df73fa6..b78291ce4 100644 --- a/docs/articles/nunit/extending-nunit/IParameterDataSource-Interface.md +++ b/docs/articles/nunit/extending-nunit/IParameterDataSource-Interface.md @@ -21,7 +21,7 @@ up to other attributes and ultimately NUnit itself. The following NUnit attributes currently implement `IParameterDataSource`: -* [`RandomAttribute`](../writing-tests/attributes/random.md) -* [`ValuesAttribute`](../writing-tests/attributes/values.md), with the derived class - * [`RangeAttribute`](../writing-tests/attributes/range.md) -* [`ValueSourceAttribute`](../writing-tests/attributes/valuesource.md) +* [`RandomAttribute`](xref:attribute-random) +* [`ValuesAttribute`](xref:attribute-values), with the derived class + * [`RangeAttribute`](xref:attribute-range) +* [`ValueSourceAttribute`](xref:attribute-valuesource) diff --git a/docs/articles/nunit/extending-nunit/ISimpleTestBuilder-Interface.md b/docs/articles/nunit/extending-nunit/ISimpleTestBuilder-Interface.md index a3ad88b70..7d93b5234 100644 --- a/docs/articles/nunit/extending-nunit/ISimpleTestBuilder-Interface.md +++ b/docs/articles/nunit/extending-nunit/ISimpleTestBuilder-Interface.md @@ -24,4 +24,4 @@ implement `ITestBuilder`. This allows, for example, use of `[Test]` on a method specified, without any error arising. Such usage has existed in NUnit for some time and this special handling of the interface allows us to preserve it. -In the current build, only [`TestAttribute`](../writing-tests/attributes/test.md) implements this interface. +In the current build, only [`TestAttribute`](xref:attribute-test) implements this interface. diff --git a/docs/articles/nunit/extending-nunit/ITestBuilder-Interface.md b/docs/articles/nunit/extending-nunit/ITestBuilder-Interface.md index e8dbb3aa7..451dc0eb1 100644 --- a/docs/articles/nunit/extending-nunit/ITestBuilder-Interface.md +++ b/docs/articles/nunit/extending-nunit/ITestBuilder-Interface.md @@ -25,9 +25,9 @@ them. The following NUnit attributes currently implement `ITestBuilder`: * `CombiningStrategyAttribute`, with the following derived classes: - * [`CombinatorialAttribute`](../writing-tests/attributes/combinatorial.md) - * [`PairwiseAttribute`](../writing-tests/attributes/pairwise.md) - * [`SequentialAttribute`](../writing-tests/attributes/sequential.md) -* [`TestCaseAttribute`](../writing-tests/attributes/testcase.md) -* [`TestCaseSourceAttribute`](../writing-tests/attributes/testcasesource.md) -* [`TheoryAttribute`](../writing-tests/attributes/theory.md) + * [`CombinatorialAttribute`](xref:attribute-combinatorial) + * [`PairwiseAttribute`](xref:attribute-pairwise) + * [`SequentialAttribute`](xref:attribute-sequential) +* [`TestCaseAttribute`](xref:attribute-testcase) +* [`TestCaseSourceAttribute`](xref:attribute-testcasesource) +* [`TheoryAttribute`](xref:attribute-theory) diff --git a/docs/articles/nunit/release-notes/Nunit4.0-MigrationGuide.md b/docs/articles/nunit/release-notes/Nunit4.0-MigrationGuide.md index 46e2b7b56..daec59a8b 100644 --- a/docs/articles/nunit/release-notes/Nunit4.0-MigrationGuide.md +++ b/docs/articles/nunit/release-notes/Nunit4.0-MigrationGuide.md @@ -16,17 +16,17 @@ Ensure you use a compatible runner for NUnit Version 4. ## 3.x -> 4.x -NUnit 4.0 has a few [breaking changes](../release-notes/breaking-changes.md#nunit-40) making it neither binary nor +NUnit 4.0 has a few [breaking changes](xref:breakingchanges#nunit-40) making it neither binary nor source code compatible with NUnit 3.14.0 -* Change to [Classic Asserts](../writing-tests/assertions/assertion-models/classic.md) +* Change to [Classic Asserts](xref:classicmodel) * Removal of `Assert.That` overloads with _format_ specification and `params`. ### Classic Assert migration There are different ways to migrate these to NUnit 4.0 -* Convert Classic Assert to the [Constraint model](../writing-tests/assertions/assertion-models/constraint.md) +* Convert Classic Assert to the [Constraint model](xref:constraintmodel) * Update source code to new namespace and class name * Using `global using` aliases * In own source file @@ -394,7 +394,7 @@ for each project with a contents similar to the one shown above. ### Assert.That with _format_ specification and `params` overload conversion These overloads were removed to allow for better messages in case of failure. See [The "Towards NUnit 4" -article](../Towards-NUnit4.md#improved-assert-result-messages) for more information. +article](xref:towardsnunit4#improved-assert-result-messages) for more information. NUnit 4.x has been optimized such that these formattable strings only get formatted in case the test is failing. diff --git a/docs/articles/nunit/release-notes/breaking-changes.md b/docs/articles/nunit/release-notes/breaking-changes.md index 033e3eb48..53b569e32 100644 --- a/docs/articles/nunit/release-notes/breaking-changes.md +++ b/docs/articles/nunit/release-notes/breaking-changes.md @@ -1,7 +1,7 @@ --- uid: breakingchanges --- - + # Breaking Changes ## NUnit 4.0 @@ -9,13 +9,13 @@ uid: breakingchanges See the [Migration Guide](xref:migrationguidance) for moving your tests from NUnit 3.x to NUnit 4.0 if you are using any of the following features: -* The [Classic Asserts][def] have been moved to a separate library +* The [Classic Asserts](xref:classicmodel) have been moved to a separate library and their namespace and their class name were renamed to: `NUnit.Framework.Legacy.ClassicAssert`. * The standalone assert classes have also been moved to the `NUnit.Framework.Legacy` namespace. These classes are: - * [CollectionAssert](../writing-tests/assertions/classic-assertions/Collection-Assert.md) - * [StringAssert](../writing-tests/assertions/classic-assertions/String-Assert.md) - * [DirectoryAssert](../writing-tests/assertions/classic-assertions/Directory-Assert.md) - * [FileAssert](../writing-tests/assertions/classic-assertions/File-Assert.md) + * [CollectionAssert](xref:classic-collection-assert) + * [StringAssert](xref:classic-string-assert) + * [DirectoryAssert](xref:classic-directory-assert) + * [FileAssert](xref:classic-file-assert) * Assert.That overloads with _format_ specification and `params` have been removed in favor of an overload using `FormattableString`. * The lowest framework version supported is now version 4.6.2 and .Net 6.0. @@ -158,5 +158,3 @@ runner supports. | `--noshadow` | Disable shadow copy | No longer supported. The console runner now disables shadow copy by default. use `--shadowcopy` on the command-line to turn it on. | | `--nothread` | Disable use of a separate thread for tests | No longer supported. | | `--nodots` | Do not display dots as a progress indicator | No longer supported. | - -[def]: ../writing-tests/assertions/assertion-models/classic.md diff --git a/docs/articles/nunit/release-notes/framework.md b/docs/articles/nunit/release-notes/framework.md index 47f9a0683..1affac9d6 100644 --- a/docs/articles/nunit/release-notes/framework.md +++ b/docs/articles/nunit/release-notes/framework.md @@ -958,7 +958,7 @@ If you use the `NUnit Console`, you will need version `3.15.3` or later (but not The minimum target framework supported is now dotnet framework `4.6.2`, and .net `6.0`. -See the [planning notes](../Towards-NUnit4.md) for more information about the changes. +See the [planning notes](xref:towardsnunit4) for more information about the changes. See the [migration guide](https://docs.nunit.org/articles/nunit/release-notes/Nunit4.0-MigrationGuide.html) for how to move your projects from NUnit 3 to NUnit 4. @@ -1279,11 +1279,11 @@ results file. ## NUnit 3.13 - January 7, 2021 -The [`FixtureLifeCycle`](xref:fixturelifecycleattribute) attribute has been added to indicate that an instance for a +The [`FixtureLifeCycle`](xref:attribute-fixturelifecycle) attribute has been added to indicate that an instance for a test fixture or all test fixtures in an assembly should be constructed for each test within the fixture or assembly. This attribute may be applied to a test fixture (class) or to a test assembly. It is useful in combination with the -[Parallelizable Attribute](xref:parallelizableattribute) so that a new instance of a test fixture is constructed for +[Parallelizable Attribute](xref:attribute-parallelizable) so that a new instance of a test fixture is constructed for every test within the test fixture. This allows tests to run in isolation without sharing instance fields and properties during parallel test runs. This make running parallel tests easier because it is easier to make your tests thread safe. @@ -1859,7 +1859,7 @@ prior to version 3.9. ## NUnit 3.7 - May 29, 2017 This release of NUnit expands on parallel test execution to allow test methods to be run in parallel. Please see the -[Parallelizable Attribute](xref:parallelizableattribute) for more information. +[Parallelizable Attribute](xref:attribute-parallelizable) for more information. NUnit 3.7 also drops the Portable build of the framework and replaces it with a .NET Standard 1.3 version to compliment the .NET Standard 1.6 version. This change enables several constraints and other features in the .NET Standard builds diff --git a/docs/articles/nunit/running-tests/Console-Command-Line.md b/docs/articles/nunit/running-tests/Console-Command-Line.md index f96ce70a3..30de1c3d4 100644 --- a/docs/articles/nunit/running-tests/Console-Command-Line.md +++ b/docs/articles/nunit/running-tests/Console-Command-Line.md @@ -46,7 +46,7 @@ beginning with 2.0. Without the V2 driver, only version 3.0 and higher tests may |`--dispose-runners` | Dispose each test runner after it has finished running its tests | |`--timeout=MILLISECONDS` | Set timeout for each test case in MILLISECONDS. | |`--seed=SEED` | Set the random SEED used to generate test cases. | -|`--workers=NUMBER` | Specify the NUMBER of worker threads to be used in running tests. This setting is used to control running your tests in parallel and is used in conjunction with the [Parallelizable Attribute](xref:parallelizableattribute). If not specified, workers defaults to the number of processors on the machine, or 2, whichever is greater. | +|`--workers=NUMBER` | Specify the NUMBER of worker threads to be used in running tests. This setting is used to control running your tests in parallel and is used in conjunction with the [Parallelizable Attribute](xref:attribute-parallelizable). If not specified, workers defaults to the number of processors on the machine, or 2, whichever is greater. | |`--stoponerror` | Stop run immediately upon any test failure or error. | |`--skipnontestassemblies` | Skip any non-test assemblies specified - or assemblies containing NUnit.Framework.NonTestAssemblyAttribute, without error. | |`--debug` | Causes NUnit to break into the debugger immediately before it executes your tests. This is particularly useful when the tests are running in a separate process to which you would otherwise have to attach. | diff --git a/docs/articles/nunit/running-tests/Test-Selection-Language.md b/docs/articles/nunit/running-tests/Test-Selection-Language.md index c56bc25d8..f50dffdf1 100644 --- a/docs/articles/nunit/running-tests/Test-Selection-Language.md +++ b/docs/articles/nunit/running-tests/Test-Selection-Language.md @@ -105,7 +105,7 @@ the Category property currently accomplishes the same thing as the cat keyword. these properties by NUnit is considered an implementation detail and they may change in the future. We envision that most filtering by property will be based on user-defined properties, created for this purpose by -inheriting from [Property Attribute](xref:propertyattribute). When defining a property, you should keep the limitation +inheriting from [Property Attribute](xref:attribute-property). When defining a property, you should keep the limitation to string values in mind. For example, a PriorityAttribute taking values of "High", "Medium" and "Low" could be used for filtering, while one that took the integers 1, 2 and 3 could not. diff --git a/docs/articles/nunit/technical-notes/usage/Parameterized-Tests.md b/docs/articles/nunit/technical-notes/usage/Parameterized-Tests.md index ced868e5e..d436c0f7e 100644 --- a/docs/articles/nunit/technical-notes/usage/Parameterized-Tests.md +++ b/docs/articles/nunit/technical-notes/usage/Parameterized-Tests.md @@ -17,15 +17,15 @@ as shown in the following table. | | Complete Test Cases | Data for One Argument | |--------------|------------------------------|-----------------------| -| **Inline** | [TestCase Attribute](xref:testcaseattribute) | [Random Attribute](xref:randomattribute), [Range Attribute](xref:rangeattribute), [Values Attribute](xref:valuesattribute) | -| **Separate** | [TestCaseSource Attribute](xref:testcasesourceattribute) | [ValueSource Attribute](xref:valuesource) | +| **Inline** | [TestCase Attribute](xref:attribute-testcase) | [Random Attribute](xref:attribute-random), [Range Attribute](xref:attribute-range), [Values Attribute](xref:attribute-values) | +| **Separate** | [TestCaseSource Attribute](xref:attribute-testcasesource) | [ValueSource Attribute](xref:attribute-valuesource) | In addition, when data is specified for individual arguments, special attributes may be added to the test method itself in order to tell NUnit how to go about combining the arguments. Currently, the following attributes are provided: -* [Combinatorial Attribute](xref:combinatorialattribute) (default) -* [Pairwise Attribute](xref:pairwiseattribute) -* [Sequential Attribute](xref:sequentialattribute) +* [Combinatorial Attribute](xref:attribute-combinatorial) (default) +* [Pairwise Attribute](xref:attribute-pairwise) +* [Sequential Attribute](xref:attribute-sequential) ## Order of Execution diff --git a/docs/articles/nunit/technical-notes/usage/SetUp-and-TearDown.md b/docs/articles/nunit/technical-notes/usage/SetUp-and-TearDown.md index 3c332e271..fd44b69f4 100644 --- a/docs/articles/nunit/technical-notes/usage/SetUp-and-TearDown.md +++ b/docs/articles/nunit/technical-notes/usage/SetUp-and-TearDown.md @@ -2,13 +2,13 @@ ## Attribute Usage -* [SetUpAttribute](xref:setup-attribute) is now used exclusively for per-test setup. -* [TearDownAttribute](xref:teardown-attribute) is now used exclusively for per-test teardown. -* [OneTimeSetUpAttribute](xref:onetimesetup-attribute) is used for one-time setup per test-run. If you run _n_ tests, +* [SetUpAttribute](xref:attribute-setup) is now used exclusively for per-test setup. +* [TearDownAttribute](xref:attribute-teardown) is now used exclusively for per-test teardown. +* [OneTimeSetUpAttribute](xref:attribute-onetimesetup) is used for one-time setup per test-run. If you run _n_ tests, this event will only occur once. -* [OneTimeTearDownAttribute](xref:onetimeteardown-attribute) is used for one-time teardown per test-run. If you run _n_ +* [OneTimeTearDownAttribute](xref:attribute-onetimeteardown) is used for one-time teardown per test-run. If you run _n_ tests, this event will only occur once -* [SetUpFixtureAttribute](xref:setupfixture-attribute) continues to be used as at before, but with changed method +* [SetUpFixtureAttribute](xref:attribute-setupfixture) continues to be used as at before, but with changed method attributes. ### Attribute Usage by Fixture Type diff --git a/docs/articles/nunit/writing-tests/TestCaseData.md b/docs/articles/nunit/writing-tests/TestCaseData.md index 9667a9043..24e6552b7 100644 --- a/docs/articles/nunit/writing-tests/TestCaseData.md +++ b/docs/articles/nunit/writing-tests/TestCaseData.md @@ -16,9 +16,11 @@ This example uses the fluent interface supported by **TestCaseData** to make the * **Explicit()** or **Explicit(string)** causes the test case to be marked explicit, optionally specifying the reason for doing so. -* **Ignore(string)** causes the test case to be ignored and specifies the reason, which is required. +* **Ignore(string)** causes the test case to be ignored and specifies the reason, which is required. Can be chained + with **Until(DateTimeOffset)** to specify a date after which the test should run again. * **Returns** specifies the expected result to be returned from the method, which must have a compatible return type. * **SetArgDisplayNames(string[])** sets the list of display names to use as the parameters in the test name. +* **SetArgDisplayNames(object[])** sets the list of display names using objects that are automatically formatted. * **SetCategory(string)** applies a category to the test. * **SetDescription(string)** sets the description property of the test. * **SetName(string)** provides a name for the test. If not specified, a name is generated based on the method name and @@ -26,3 +28,36 @@ This example uses the fluent interface supported by **TestCaseData** to make the * **SetProperty(string, string)**, **SetProperty(string, int)** and **SetProperty(string, double)** apply a named property and value to the test. * **TypeArgs** specifies the `Type`s to be used when targeting a generic test method. (_NUnit 4.1+_) +* **Until(DateTimeOffset)** can be chained after **Ignore(string)** to specify a date after which the test case + should no longer be ignored. Once the date passes, the test will run automatically. (_NUnit 4+_) + +## Temporarily ignoring test cases with Until + +The **Until** method allows you to temporarily ignore a test case until a specific date. This is useful for tests +that are known to fail due to external factors (e.g., waiting for an API release, known bug in a dependency) but +should automatically start running again after a certain date. + +[!code-csharp[IgnoreUntilExample](~/snippets/Snippets.NUnit/TestCaseDataExample.cs#IgnoreUntilExample)] + +## Generic TestCaseData variants + +As of NUnit 4.1, generic versions of `TestCaseData` are available that automatically set the `TypeArgs` property +based on their type parameters. This provides a more concise syntax when working with generic test methods: + +| Class | Usage | +|-------|-------| +| `TestCaseData` | Single type parameter | +| `TestCaseData` | Two type parameters | +| `TestCaseData` | Three type parameters | +| `TestCaseData` | Four type parameters | +| `TestCaseData` | Five type parameters | + +[!code-csharp[GenericTestCaseDataExample](~/snippets/Snippets.NUnit/TestCaseDataExample.cs#GenericTestCaseDataExample)] + +## SetArgDisplayNames with objects + +The `SetArgDisplayNames` method has an overload that accepts `object[]` instead of `string[]`. Objects passed to +this overload are automatically formatted using NUnit's value formatting logic, which is the same logic used for +default test names. + +[!code-csharp[SetArgDisplayNamesObjectExample](~/snippets/Snippets.NUnit/TestCaseDataExample.cs#SetArgDisplayNamesObjectExample)] diff --git a/docs/articles/nunit/writing-tests/TestFixtureData.md b/docs/articles/nunit/writing-tests/TestFixtureData.md index cb49cfc3e..2b5c8eae3 100644 --- a/docs/articles/nunit/writing-tests/TestFixtureData.md +++ b/docs/articles/nunit/writing-tests/TestFixtureData.md @@ -8,7 +8,7 @@ The `TestFixtureData` class provides specific instance information for a paramet deriving from `TestFixtureParameters` may be used. Unlike NUnit 2, you cannot implement `IFixtureData`, you must derive from `TestFixtureParameters`. -The following example varies the example shown under [TestFixture Attribute](xref:testfixtureattribute) by using a +The following example varies the example shown under [TestFixture Attribute](xref:attribute-testfixture) by using a `TestFixtureSourceAttribute` with a data source in a separately defined class. [!code-csharp[TestFixtureDataExample](~/snippets/Snippets.NUnit/TestFixtureDataExample.cs#TestFixtureDataExample)] diff --git a/docs/articles/nunit/writing-tests/assertions/assertion-models/classic.md b/docs/articles/nunit/writing-tests/assertions/assertion-models/classic.md index c4b2ba2a7..f81936b5a 100644 --- a/docs/articles/nunit/writing-tests/assertions/assertion-models/classic.md +++ b/docs/articles/nunit/writing-tests/assertions/assertion-models/classic.md @@ -26,43 +26,43 @@ StringAssert.AreEqualIgnoringCase("Hello", myString); The Assert class provides the most common classic assertions in NUnit: -* [Assert.True](../classic-assertions/Assert.True.md) -* [Assert.False](../classic-assertions/Assert.False.md) -* [Assert.Null](../classic-assertions/Assert.Null.md) -* [Assert.NotNull](../classic-assertions/Assert.NotNull.md) -* [Assert.Zero](../classic-assertions/Assert.Zero.md) -* [Assert.NotZero](../classic-assertions/Assert.NotZero.md) -* [Assert.IsNaN](../classic-assertions/Assert.IsNaN.md) -* [Assert.IsEmpty](../classic-assertions/Assert.IsEmpty.md) -* [Assert.IsNotEmpty](../classic-assertions/Assert.IsNotEmpty.md) -* [Assert.AreEqual](../classic-assertions/Assert.AreEqual.md) -* [Assert.AreNotEqual](../classic-assertions/Assert.AreNotEqual.md) -* [Assert.AreSame](../classic-assertions/Assert.AreSame.md) -* [Assert.AreNotSame](../classic-assertions/Assert.AreNotSame.md) -* [Assert.Contains](../classic-assertions/Assert.Contains.md) -* [Assert.Greater](../classic-assertions/Assert.Greater.md) -* [Assert.GreaterOrEqual](../classic-assertions/Assert.GreaterOrEqual.md) -* [Assert.Less](../classic-assertions/Assert.Less.md) -* [Assert.LessOrEqual](../classic-assertions/Assert.LessOrEqual.md) -* [Assert.Positive](../classic-assertions/Assert.Positive.md) -* [Assert.Negative](../classic-assertions/Assert.Negative.md) -* [Assert.IsInstanceOf](../classic-assertions/Assert.IsInstanceOf.md) -* [Assert.IsNotInstanceOf](../classic-assertions/Assert.IsNotInstanceOf.md) -* [Assert.IsAssignableFrom](../classic-assertions/Assert.IsAssignableFrom.md) -* [Assert.IsNotAssignableFrom](../classic-assertions/Assert.IsNotAssignableFrom.md) -* [Assert.Throws](../classic-assertions/Assert.Throws.md) -* [Assert.ThrowsAsync](../classic-assertions/Assert.ThrowsAsync.md) -* [Assert.DoesNotThrow](../classic-assertions/Assert.DoesNotThrow.md) -* [Assert.DoesNotThrowAsync](../classic-assertions/Assert.DoesNotThrowAsync.md) -* [Assert.Catch](../classic-assertions/Assert.Catch.md) -* [Assert.CatchAsync](../classic-assertions/Assert.CatchAsync.md) +* [Assert.True](xref:classic-assert-true) +* [Assert.False](xref:classic-assert-false) +* [Assert.Null](xref:classic-assert-null) +* [Assert.NotNull](xref:classic-assert-not-null) +* [Assert.Zero](xref:classic-assert-zero) +* [Assert.NotZero](xref:classic-assert-not-zero) +* [Assert.IsNaN](xref:classic-assert-is-nan) +* [Assert.IsEmpty](xref:classic-assert-is-empty) +* [Assert.IsNotEmpty](xref:classic-assert-is-not-empty) +* [Assert.AreEqual](xref:classic-assert-are-equal) +* [Assert.AreNotEqual](xref:classic-assert-are-not-equal) +* [Assert.AreSame](xref:classic-assert-are-same) +* [Assert.AreNotSame](xref:classic-assert-are-not-same) +* [Assert.Contains](xref:classic-assert-contains) +* [Assert.Greater](xref:classic-assert-greater) +* [Assert.GreaterOrEqual](xref:classic-assert-greater-or-equal) +* [Assert.Less](xref:classic-assert-less) +* [Assert.LessOrEqual](xref:classic-assert-less-or-equal) +* [Assert.Positive](xref:classic-assert-positive) +* [Assert.Negative](xref:classic-assert-negative) +* [Assert.IsInstanceOf](xref:classic-assert-is-instance-of) +* [Assert.IsNotInstanceOf](xref:classic-assert-is-not-instance-of) +* [Assert.IsAssignableFrom](xref:classic-assert-is-assignable-from) +* [Assert.IsNotAssignableFrom](xref:classic-assert-is-not-assignable-from) +* [Assert.Throws](xref:classic-assert-throws) +* [Assert.ThrowsAsync](xref:classic-assert-throws-async) +* [Assert.DoesNotThrow](xref:classic-assert-does-not-throw) +* [Assert.DoesNotThrowAsync](xref:classic-assert-does-not-throw-async) +* [Assert.Catch](xref:classic-assert-catch) +* [Assert.CatchAsync](xref:classic-assert-catch-async) Additional assertions are provided by the following classes, which are in the `NUnit.Framework.Legacy` namespace: -* [String Assert](../classic-assertions/String-Assert.md) -* [Collection Assert](../classic-assertions/Collection-Assert.md) -* [File Assert](../classic-assertions/File-Assert.md) -* [Directory Assert](../classic-assertions/Directory-Assert.md) +* [String Assert](xref:classic-string-assert) +* [Collection Assert](xref:classic-collection-assert) +* [File Assert](xref:classic-file-assert) +* [Directory Assert](xref:classic-directory-assert) ## See Also diff --git a/docs/articles/nunit/writing-tests/assertions/assertion-models/special.md b/docs/articles/nunit/writing-tests/assertions/assertion-models/special.md index 9c977f92e..739140274 100644 --- a/docs/articles/nunit/writing-tests/assertions/assertion-models/special.md +++ b/docs/articles/nunit/writing-tests/assertions/assertion-models/special.md @@ -1,10 +1,13 @@ +--- +uid: specialmodel +--- # Special Assertions The special assertions do not check any condition. They are used for special purposes, like unconditional failure or success, ignoring a test, etc. -* [Assert.Pass](../special-assertions/Assert.Pass.md) -* [Assert.Fail](../special-assertions/Assert.Fail.md) -* [Assert.Ignore](../special-assertions/Assert.Ignore.md) -* [Assert.Inconclusive](../special-assertions/Assert.Inconclusive.md) +* [Assert.Pass](xref:special-assert-pass) +* [Assert.Fail](xref:special-assert-fail) +* [Assert.Ignore](xref:special-assert-ignore) +* [Assert.Inconclusive](xref:special-assert-inconclusive) diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.AreEqual.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.AreEqual.md index fa7562171..9c4429a84 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.AreEqual.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.AreEqual.md @@ -1,3 +1,7 @@ +--- +uid: classic-assert-are-equal +--- + # Assert.AreEqual **Assert.AreEqual** tests whether the two arguments are equal. diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.AreNotEqual.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.AreNotEqual.md index 28099994f..6b7d13fbb 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.AreNotEqual.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.AreNotEqual.md @@ -1,3 +1,7 @@ +--- +uid: classic-assert-are-not-equal +--- + # Assert.AreNotEqual **Assert.AreNotEqual** tests whether the two arguments are unequal. diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.AreNotSame.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.AreNotSame.md index 274b540a4..0e6122d90 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.AreNotSame.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.AreNotSame.md @@ -1,3 +1,7 @@ +--- +uid: classic-assert-are-not-same +--- + # Assert.AreNotSame **Assert.AreNotSame** tests that the two arguments do not reference the same object. diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.AreSame.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.AreSame.md index 2153acd4d..80b2e2801 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.AreSame.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.AreSame.md @@ -1,3 +1,7 @@ +--- +uid: classic-assert-are-same +--- + # Assert.AreSame **Assert.AreSame** tests that the two arguments reference the same object. diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Catch.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Catch.md index e77d7610f..c28c53522 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Catch.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Catch.md @@ -1,3 +1,7 @@ +--- +uid: classic-assert-catch +--- + # Assert.Catch **Assert.Catch** is similar to **Assert.Throws** but will pass for an exception diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.CatchAsync.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.CatchAsync.md index 4ae54c789..58d8c2101 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.CatchAsync.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.CatchAsync.md @@ -1,3 +1,7 @@ +--- +uid: classic-assert-catch-async +--- + # Assert.CatchAsync **Assert.CatchAsync** is similar to [Assert.ThrowsAsync](Assert.ThrowsAsync.md) but will pass for an exception diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Contains.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Contains.md index ab5973af6..9c3cbe143 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Contains.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Contains.md @@ -1,3 +1,7 @@ +--- +uid: classic-assert-contains +--- + # Assert.Contains **Assert.Contains** is used to test whether an object is contained in a diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.DoesNotThrow.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.DoesNotThrow.md index ef368d193..e4824a67d 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.DoesNotThrow.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.DoesNotThrow.md @@ -1,3 +1,7 @@ +--- +uid: classic-assert-does-not-throw +--- + # Assert.DoesNotThrow **Assert.DoesNotThrow** verifies that the delegate provided as an argument diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.DoesNotThrowAsync.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.DoesNotThrowAsync.md index bbcfec911..39e461c5c 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.DoesNotThrowAsync.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.DoesNotThrowAsync.md @@ -1,3 +1,7 @@ +--- +uid: classic-assert-does-not-throw-async +--- + # Assert.DoesNotThrowAsync **Assert.DoesNotThrowAsync** verifies that the delegate provided as an argument diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.False.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.False.md index 762eb666b..2ea5248bb 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.False.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.False.md @@ -1,3 +1,7 @@ +--- +uid: classic-assert-false +--- + # Assert.False **Assert.False** and **Assert.IsFalse** test that the specified condition is false. diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Greater.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Greater.md index ff48a8939..7bec68fdf 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Greater.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Greater.md @@ -1,3 +1,7 @@ +--- +uid: classic-assert-greater +--- + # Assert.Greater **Assert.Greater** tests whether one object is greater than another. diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.GreaterOrEqual.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.GreaterOrEqual.md index da360ffb5..af00960ac 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.GreaterOrEqual.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.GreaterOrEqual.md @@ -1,3 +1,7 @@ +--- +uid: classic-assert-greater-or-equal +--- + # Assert.GreaterOrEqual **Assert.GreaterOrEqual** tests whether one object is greater than or equal to another. diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.IsAssignableFrom.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.IsAssignableFrom.md index c8c7fd8ea..0553a2130 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.IsAssignableFrom.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.IsAssignableFrom.md @@ -1,3 +1,7 @@ +--- +uid: classic-assert-is-assignable-from +--- + # Assert.IsAssignableFrom **Assert.IsAssignableFrom** succeeds if the object provided may be assigned a value of the expected type. diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.IsEmpty.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.IsEmpty.md index 525bc3481..41df2c630 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.IsEmpty.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.IsEmpty.md @@ -1,3 +1,7 @@ +--- +uid: classic-assert-is-empty +--- + # Assert.IsEmpty **Assert.IsEmpty** may be used to test either a string or a collection or IEnumerable. When used with a string, diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.IsInstanceOf.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.IsInstanceOf.md index 8cc47c3bd..d4ffd19c5 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.IsInstanceOf.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.IsInstanceOf.md @@ -1,3 +1,7 @@ +--- +uid: classic-assert-is-instance-of +--- + # Assert.IsInstanceOf **Assert.IsInstanceOf** succeeds if the object provided as an actual value is an instance of the expected type. diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.IsNaN.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.IsNaN.md index ad4644325..b333f9199 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.IsNaN.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.IsNaN.md @@ -1,3 +1,7 @@ +--- +uid: classic-assert-is-nan +--- + # Assert.IsNaN **Assert.IsNaN** tests that the specified double value is NaN. diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.IsNotAssignableFrom.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.IsNotAssignableFrom.md index d28d1a10d..b7652be55 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.IsNotAssignableFrom.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.IsNotAssignableFrom.md @@ -1,3 +1,7 @@ +--- +uid: classic-assert-is-not-assignable-from +--- + # Assert.IsNotAssignableFrom **Assert.IsNotAssignableFrom** succeeds if the object provided may not be assigned a value of the expected type. diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.IsNotEmpty.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.IsNotEmpty.md index 479cf32f2..bbe10f2e9 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.IsNotEmpty.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.IsNotEmpty.md @@ -1,3 +1,7 @@ +--- +uid: classic-assert-is-not-empty +--- + # Assert.IsNotEmpty **Assert.IsNotEmpty** may be used to test either a string or a collection or IEnumerable. When used with a diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.IsNotInstanceOf.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.IsNotInstanceOf.md index cef2dceef..74e38df01 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.IsNotInstanceOf.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.IsNotInstanceOf.md @@ -1,3 +1,7 @@ +--- +uid: classic-assert-is-not-instance-of +--- + # Assert.IsNotInstanceOf **Assert.IsNotInstanceOf** succeeds if the object provided as an actual value is not an instance of the expected type. diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Less.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Less.md index 62ef96932..b0dcfb298 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Less.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Less.md @@ -1,3 +1,7 @@ +--- +uid: classic-assert-less +--- + # Assert.Less **Assert.Less** tests whether one object is less than another. diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.LessOrEqual.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.LessOrEqual.md index cbb95b200..ffd68dd0f 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.LessOrEqual.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.LessOrEqual.md @@ -1,3 +1,7 @@ +--- +uid: classic-assert-less-or-equal +--- + # Assert.LessOrEqual **Assert.LessOrEqual** tests whether one object is less than or equal to another. diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Negative.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Negative.md index fc061991d..4d5a45509 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Negative.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Negative.md @@ -1,3 +1,7 @@ +--- +uid: classic-assert-negative +--- + # Assert.Negative Asserts that a number is negative. diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.NotNull.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.NotNull.md index cd7db00e4..d3c9e8dc5 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.NotNull.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.NotNull.md @@ -1,3 +1,7 @@ +--- +uid: classic-assert-not-null +--- + # Assert.NotNull **Assert.NotNull** and **Assert.IsNotNull** test that the specified object is non-null. diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.NotZero.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.NotZero.md index 784efb7ad..70d91e8b0 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.NotZero.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.NotZero.md @@ -1,3 +1,7 @@ +--- +uid: classic-assert-not-zero +--- + # Assert.NotZero **Assert.NotZero** tests that a value is not zero. diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Null.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Null.md index e3575f72c..50e77a21d 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Null.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Null.md @@ -1,3 +1,7 @@ +--- +uid: classic-assert-null +--- + # Assert.Null **Assert.Null** and **Assert.IsNull** test that the specified object is null. diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Positive.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Positive.md index b9cc9b8d5..43c775851 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Positive.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Positive.md @@ -1,3 +1,7 @@ +--- +uid: classic-assert-positive +--- + # Assert.Positive Asserts that a number is positive. diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Throws.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Throws.md index ea7e3ccf5..95958a4d1 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Throws.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Throws.md @@ -1,3 +1,7 @@ +--- +uid: classic-assert-throws +--- + # Assert.Throws The **Assert.Throws** method is pretty much in a class by itself. Rather than diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.ThrowsAsync.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.ThrowsAsync.md index 42abaad05..7c160e4de 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.ThrowsAsync.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.ThrowsAsync.md @@ -1,3 +1,7 @@ +--- +uid: classic-assert-throws-async +--- + # Assert.ThrowsAsync The **Assert.ThrowsAsync** is the async equivalent to [Assert.Throws](Assert.Throws.md) diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.True.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.True.md index aa1d35fa6..bcb439064 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.True.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.True.md @@ -1,3 +1,7 @@ +--- +uid: classic-assert-true +--- + # Assert.True **Assert.True** and **Assert.IsTrue** test that the specified condition is true. diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Zero.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Zero.md index 8800a4e05..a61d5c3a1 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Zero.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Zero.md @@ -1,3 +1,7 @@ +--- +uid: classic-assert-zero +--- + # Assert.Zero **Assert.Zero** tests that a value is zero. diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Collection-Assert.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Collection-Assert.md index 92fcb172c..b187233bd 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Collection-Assert.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Collection-Assert.md @@ -1,3 +1,7 @@ +--- +uid: classic-collection-assert +--- + # CollectionAssert The CollectionAssert class provides a number of methods that are useful when examining collections and their contents or diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Directory-Assert.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Directory-Assert.md index 036a06dea..5d16836eb 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/Directory-Assert.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/Directory-Assert.md @@ -1,3 +1,7 @@ +--- +uid: classic-directory-assert +--- + # DirectoryAssert The DirectoryAssert class provides methods for comparing two directories diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/File-Assert.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/File-Assert.md index 5f22bf358..42c324dbd 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/File-Assert.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/File-Assert.md @@ -1,3 +1,7 @@ +--- +uid: classic-file-assert +--- + # FileAssert The FileAssert class provides methods for comparing or verifying the existence of files, diff --git a/docs/articles/nunit/writing-tests/assertions/classic-assertions/String-Assert.md b/docs/articles/nunit/writing-tests/assertions/classic-assertions/String-Assert.md index d6c7b4676..39555130e 100644 --- a/docs/articles/nunit/writing-tests/assertions/classic-assertions/String-Assert.md +++ b/docs/articles/nunit/writing-tests/assertions/classic-assertions/String-Assert.md @@ -1,3 +1,7 @@ +--- +uid: classic-string-assert +--- + # StringAssert The StringAssert class provides a number of methods that are useful diff --git a/docs/articles/nunit/writing-tests/assertions/special-assertions/Assert.Fail.md b/docs/articles/nunit/writing-tests/assertions/special-assertions/Assert.Fail.md index c26d9df89..417b5c24c 100644 --- a/docs/articles/nunit/writing-tests/assertions/special-assertions/Assert.Fail.md +++ b/docs/articles/nunit/writing-tests/assertions/special-assertions/Assert.Fail.md @@ -1,3 +1,7 @@ +--- +uid: special-assert-fail +--- + # Assert.Fail The **Assert.Fail** method provides you with the ability to generate a failure based diff --git a/docs/articles/nunit/writing-tests/assertions/special-assertions/Assert.Ignore.md b/docs/articles/nunit/writing-tests/assertions/special-assertions/Assert.Ignore.md index 01a941430..37bc33ef3 100644 --- a/docs/articles/nunit/writing-tests/assertions/special-assertions/Assert.Ignore.md +++ b/docs/articles/nunit/writing-tests/assertions/special-assertions/Assert.Ignore.md @@ -1,3 +1,7 @@ +--- +uid: special-assert-ignore +--- + # Assert.Ignore The **Assert.Ignore** method provides you with the ability to dynamically cause a diff --git a/docs/articles/nunit/writing-tests/assertions/special-assertions/Assert.Inconclusive.md b/docs/articles/nunit/writing-tests/assertions/special-assertions/Assert.Inconclusive.md index fd5b257e9..83239f14e 100644 --- a/docs/articles/nunit/writing-tests/assertions/special-assertions/Assert.Inconclusive.md +++ b/docs/articles/nunit/writing-tests/assertions/special-assertions/Assert.Inconclusive.md @@ -1,3 +1,7 @@ +--- +uid: special-assert-inconclusive +--- + # Assert.Inconclusive The **Assert.Inconclusive** method indicates that the test could not be diff --git a/docs/articles/nunit/writing-tests/assertions/special-assertions/Assert.Pass.md b/docs/articles/nunit/writing-tests/assertions/special-assertions/Assert.Pass.md index f99e7b519..0fce3f597 100644 --- a/docs/articles/nunit/writing-tests/assertions/special-assertions/Assert.Pass.md +++ b/docs/articles/nunit/writing-tests/assertions/special-assertions/Assert.Pass.md @@ -1,3 +1,7 @@ +--- +uid: special-assert-pass +--- + # Assert.Pass The **Assert.Pass** method allows you to immediately end the test, recording diff --git a/docs/articles/nunit/writing-tests/attributes.md b/docs/articles/nunit/writing-tests/attributes.md index 595d31d3c..f44d0ae2b 100644 --- a/docs/articles/nunit/writing-tests/attributes.md +++ b/docs/articles/nunit/writing-tests/attributes.md @@ -8,51 +8,51 @@ This table lists all the attributes supported by NUnit. | Attribute | Usage | |-----------------------------------|-------------| -| [Apartment Attribute](attributes/apartment.md) | Indicates that the test should run in a particular apartment. | -| [Author Attribute](attributes/author.md) | Provides the name of the test author. | -| [CancelAfter Attribute](attributes/cancelafter.md) | Provides a timeout value in milliseconds for test cases. | -| [Category Attribute](attributes/category.md) | Specifies one or more categories for the test. | -| [Combinatorial Attribute](attributes/combinatorial.md) | Generates test cases for all possible combinations of the values provided. | -| [Culture Attribute](attributes/culture.md) | Specifies cultures for which a test or fixture should be run. | -| [Datapoint Attribute](attributes/datapoint.md) | Provides data for [Theories](xref:theoryattribute). | -| [DatapointSource Attribute](attributes/datapointsource.md) | Provides data for [Theories](xref:theoryattribute). | -| [DefaultFloatingPointTolerance Attribute](attributes/defaultfloatingpointtolerance.md) | Indicates that the test should use the specified tolerance as default for float and double comparisons. | -| [Description Attribute](attributes/description.md) | Applies descriptive text to a Test, TestFixture or Assembly. | -| [Explicit Attribute](attributes/explicit.md) | Indicates that a test should be skipped unless explicitly run. | -| [FixtureLifeCycle Attribute](attributes/fixturelifecycle.md) | Specifies the lifecycle of a fixture allowing a new instance of a test fixture to be constructed for each test case. Useful in situations where test case parallelism is important. | -| [Ignore Attribute](attributes/ignore.md) | Indicates that a test shouldn't be run for some reason. | -| [LevelOfParallelism Attribute](attributes/levelofparallelism.md) | Specifies the level of parallelism at assembly level. | -| [MaxTime Attribute](attributes/maxtime.md) | Specifies the maximum time in milliseconds for a test case to succeed. | -| [NonParallelizable Attribute](attributes/nonparallelizable.md) | Specifies that the test and its descendants may not be run in parallel. | -| [NonTestAssembly Attribute](attributes/nontestassembly.md) | Specifies that the assembly references the NUnit framework, but that it does not contain tests. | -| [OneTimeSetUp Attribute](attributes/onetimesetup.md) | Identifies methods to be called once prior to any child tests. | -| [OneTimeTearDown Attribute](attributes/onetimeteardown.md) | Identifies methods to be called once after all child tests. | -| [Order Attribute](attributes/order.md) | Specifies the order in which decorated test should be run within the containing fixture or suite. | -| [Pairwise Attribute](attributes/pairwise.md) | Generate test cases for all possible pairs of the values provided. | -| [Parallelizable Attribute](attributes/parallelizable.md) | Indicates whether test and/or its descendants can be run in parallel. | -| [Platform Attribute](attributes/platform.md) | Specifies platforms for which a test or fixture should be run. | -| [Property Attribute](attributes/property.md) | Allows setting named properties on any test case or fixture. | -| [Random Attribute](attributes/random.md) | Specifies generation of random values as arguments to a parameterized test. | -| [Range Attribute](attributes/range.md) | Specifies a range of values as arguments to a parameterized test. | -| [Repeat Attribute](attributes/repeat.md) | Specifies that the decorated method should be executed multiple times. | -| [RequiresThread Attribute](attributes/requiresthread.md) | Indicates that a test method, class or assembly should be run on a separate thread. | -| [Retry Attribute](attributes/retry.md) | Causes a test to be rerun if it fails, up to a maximum number of times. | -| [Sequential Attribute](attributes/sequential.md) | Generates test cases using values in the order provided, without additional combinations. | -| [SetCulture Attribute](attributes/setculture.md) | Sets the current Culture for the duration of a test. | -| [SetUICulture Attribute](attributes/setuiculture.md) | Sets the current UI Culture for the duration of a test. | -| [SetUp Attribute](attributes/setup.md) | Indicates a method of a TestFixture called just before each test method. | -| [SetUpFixture Attribute](attributes/setupfixture.md) | Marks a class with one-time setup or teardown methods for all the test fixtures in a namespace. | -| [SingleThreaded Attribute](attributes/singlethreaded.md) | Marks a fixture that requires all its tests to run on the same thread. | -| [TearDown Attribute](attributes/teardown.md) | Indicates a method of a TestFixture called just after each test method. | -| [Test Attribute](attributes/test.md) | Marks a method of a TestFixture that represents a test. | -| [TestCase Attribute](attributes/testcase.md) | Marks a method with parameters as a test and provides inline arguments. | -| [TestCaseSource Attribute](attributes/testcasesource.md) | Marks a method with parameters as a test and provides a source of arguments. | -| [TestFixture Attribute](attributes/testfixture.md) | Marks a class as a test fixture and may provide inline constructor arguments. | -| [TestFixtureSetup Attribute](attributes/testfixturesetup.md) | Deprecated synonym for [OneTimeSetUp Attribute](attributes/onetimesetup.md). | -| [TestFixtureSource Attribute](attributes/testfixturesource.md) | Marks a class as a test fixture and provides a source for constructor arguments. | -| [TestFixtureTeardown Attribute](attributes/testfixtureteardown.md) | Deprecated synonym for [OneTimeTearDown Attribute](attributes/onetimeteardown.md). | -| [TestOf Attribute](attributes/testof.md) | Indicates the name or Type of the class being tested. | -| [Theory Attribute](attributes/theory.md) | Marks a test method as a Theory, a special kind of test in NUnit. | -| [Timeout Attribute](attributes/timeout.md) | Provides a timeout value in milliseconds for test cases. | -| [Values Attribute](attributes/values.md) | Provides a set of inline values for a parameter of a test method. | -| [ValueSource Attribute](attributes/valuesource.md) | Provides a source of values for a parameter of a test method. | +| [Apartment Attribute](xref:attribute-apartment) | Indicates that the test should run in a particular apartment. | +| [Author Attribute](xref:attribute-author) | Provides the name of the test author. | +| [CancelAfter Attribute](xref:attribute-cancelafter) | Provides a timeout value in milliseconds for test cases. | +| [Category Attribute](xref:attribute-category) | Specifies one or more categories for the test. | +| [Combinatorial Attribute](xref:attribute-combinatorial) | Generates test cases for all possible combinations of the values provided. | +| [Culture Attribute](xref:attribute-culture) | Specifies cultures for which a test or fixture should be run. | +| [Datapoint Attribute](xref:attribute-datapoint) | Provides data for [Theories](xref:attribute-theory). | +| [DatapointSource Attribute](xref:attribute-datapointsource) | Provides data for [Theories](xref:attribute-theory). | +| [DefaultFloatingPointTolerance Attribute](xref:attribute-defaultfloatingpointtolerance) | Indicates that the test should use the specified tolerance as default for float and double comparisons. | +| [Description Attribute](xref:attribute-description) | Applies descriptive text to a Test, TestFixture or Assembly. | +| [Explicit Attribute](xref:attribute-explicit) | Indicates that a test should be skipped unless explicitly run. | +| [FixtureLifeCycle Attribute](xref:attribute-fixturelifecycle) | Specifies the lifecycle of a fixture allowing a new instance of a test fixture to be constructed for each test case. Useful in situations where test case parallelism is important. | +| [Ignore Attribute](xref:attribute-ignore) | Indicates that a test shouldn't be run for some reason. | +| [LevelOfParallelism Attribute](xref:attribute-levelofparallelism) | Specifies the level of parallelism at assembly level. | +| [MaxTime Attribute](xref:attribute-maxtime) | Specifies the maximum time in milliseconds for a test case to succeed. | +| [NonParallelizable Attribute](xref:attribute-nonparallelizable) | Specifies that the test and its descendants may not be run in parallel. | +| [NonTestAssembly Attribute](xref:attribute-nontestassembly) | Specifies that the assembly references the NUnit framework, but that it does not contain tests. | +| [OneTimeSetUp Attribute](xref:attribute-onetimesetup) | Identifies methods to be called once prior to any child tests. | +| [OneTimeTearDown Attribute](xref:attribute-onetimeteardown) | Identifies methods to be called once after all child tests. | +| [Order Attribute](xref:attribute-order) | Specifies the order in which decorated test should be run within the containing fixture or suite. | +| [Pairwise Attribute](xref:attribute-pairwise) | Generate test cases for all possible pairs of the values provided. | +| [Parallelizable Attribute](xref:attribute-parallelizable) | Indicates whether test and/or its descendants can be run in parallel. | +| [Platform Attribute](xref:attribute-platform) | Specifies platforms for which a test or fixture should be run. | +| [Property Attribute](xref:attribute-property) | Allows setting named properties on any test case or fixture. | +| [Random Attribute](xref:attribute-random) | Specifies generation of random values as arguments to a parameterized test. | +| [Range Attribute](xref:attribute-range) | Specifies a range of values as arguments to a parameterized test. | +| [Repeat Attribute](xref:attribute-repeat) | Specifies that the decorated method should be executed multiple times. | +| [RequiresThread Attribute](xref:attribute-requiresthread) | Indicates that a test method, class or assembly should be run on a separate thread. | +| [Retry Attribute](xref:attribute-retry) | Causes a test to be rerun if it fails, up to a maximum number of times. | +| [Sequential Attribute](xref:attribute-sequential) | Generates test cases using values in the order provided, without additional combinations. | +| [SetCulture Attribute](xref:attribute-setculture) | Sets the current Culture for the duration of a test. | +| [SetUICulture Attribute](xref:attribute-setuiculture) | Sets the current UI Culture for the duration of a test. | +| [SetUp Attribute](xref:attribute-setup) | Indicates a method of a TestFixture called just before each test method. | +| [SetUpFixture Attribute](xref:attribute-setupfixture) | Marks a class with one-time setup or teardown methods for all the test fixtures in a namespace. | +| [SingleThreaded Attribute](xref:attribute-singlethreaded) | Marks a fixture that requires all its tests to run on the same thread. | +| [TearDown Attribute](xref:attribute-teardown) | Indicates a method of a TestFixture called just after each test method. | +| [Test Attribute](xref:attribute-test) | Marks a method of a TestFixture that represents a test. | +| [TestCase Attribute](xref:attribute-testcase) | Marks a method with parameters as a test and provides inline arguments. | +| [TestCaseSource Attribute](xref:attribute-testcasesource) | Marks a method with parameters as a test and provides a source of arguments. | +| [TestFixture Attribute](xref:attribute-testfixture) | Marks a class as a test fixture and may provide inline constructor arguments. | +| [TestFixtureSetup Attribute](xref:attribute-testfixturesetup) | Deprecated synonym for [OneTimeSetUp Attribute](xref:attribute-onetimesetup). | +| [TestFixtureSource Attribute](xref:attribute-testfixturesource) | Marks a class as a test fixture and provides a source for constructor arguments. | +| [TestFixtureTeardown Attribute](xref:attribute-testfixtureteardown) | Deprecated synonym for [OneTimeTearDown Attribute](xref:attribute-onetimeteardown). | +| [TestOf Attribute](xref:attribute-testof) | Indicates the name or Type of the class being tested. | +| [Theory Attribute](xref:attribute-theory) | Marks a test method as a Theory, a special kind of test in NUnit. | +| [Timeout Attribute](xref:attribute-timeout) | Provides a timeout value in milliseconds for test cases. | +| [Values Attribute](xref:attribute-values) | Provides a set of inline values for a parameter of a test method. | +| [ValueSource Attribute](xref:attribute-valuesource) | Provides a source of values for a parameter of a test method. | diff --git a/docs/articles/nunit/writing-tests/attributes/apartment.md b/docs/articles/nunit/writing-tests/attributes/apartment.md index 8fa098e7d..7e221f64f 100644 --- a/docs/articles/nunit/writing-tests/attributes/apartment.md +++ b/docs/articles/nunit/writing-tests/attributes/apartment.md @@ -1,77 +1,65 @@ --- -uid: apartment-attribute +uid: attribute-apartment --- # Apartment -The `ApartmentAttribute` is used on a test method, class or assembly to specify that the tests should be run in a -particular [apartment](https://learn.microsoft.com/en-us/windows/win32/com/processes--threads--and-apartments), either -the STA or the MTA. +`ApartmentAttribute` is used to specify that tests should run in a particular COM [apartment](https://learn.microsoft.com/en-us/windows/win32/com/processes--threads--and-apartments) state, either STA (Single-Threaded Apartment) or MTA (Multi-Threaded Apartment). -When running tests in parallel, the test is simply scheduled to execute from a queue that uses the apartment specified. -When the parallel feature is not in use, it causes creation of a new thread if the parent test is not already running in -the correct apartment. +This is primarily needed for tests that interact with COM objects, Windows Forms controls, or WPF components that require a specific apartment state. -When this attribute is not specified, tests run in the MTA. +## Constructor -This attribute replaces the RequiresMTA and RequiresSTA attributes, which are now considered obsolete. +```csharp +ApartmentAttribute(ApartmentState apartmentState) +``` -## Assembly Level Examples +| Parameter | Type | Description | +|-----------|------|-------------| +| `apartmentState` | `ApartmentState` | The apartment state for the test. Must be `STA` or `MTA` (not `Unknown`). | -```csharp +## ApartmentState Values -// All the tests in this assembly will use the MTA by default. Since -// this is the general default, the attribute is not actually needed. -[assembly:Apartment(ApartmentState.MTA)] +| Value | Description | +|-------|-------------| +| `ApartmentState.STA` | Single-Threaded Apartment. Required for most UI components (WinForms, WPF, COM controls). | +| `ApartmentState.MTA` | Multi-Threaded Apartment. The default for NUnit tests. | -... +## Applies To -// All the tests in this assembly will use the STA by default -[assembly:Apartment(ApartmentState.STA)] +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ✅ | ✅ | ✅ | -``` +When applied at multiple levels, the most specific level takes precedence. + +## Examples -## Test Fixture Examples +### Assembly Level ```csharp +// All tests in this assembly will use the STA by default +[assembly: Apartment(ApartmentState.STA)] +``` -// TestFixture requiring use of the MTA. The attribute is not -// needed unless the STA was specified at a higher level. -[TestFixture, Apartment(ApartmentState.MTA)] -public class FixtureRequiringMTA -{ - // All tests in the fixture will run in the MTA. -} - -// TestFixture requiring use of the STA. -[TestFixture, Apartment(ApartmentState.STA)] -public class FixtureRequiringSTA -{ - // All tests in the fixture will run in the STA. -} +### Test Fixture Level -``` +[!code-csharp[ApartmentFixture](~/snippets/Snippets.NUnit/Attributes/ApartmentAttributeExamples.cs#ApartmentFixture)] -## Test Method Examples +### Test Method Level -```csharp -[TestFixture] -public class AnotherFixture -{ - [Test, Apartment(ApartmentState.MTA)] - public void TestRequiringMTA() - { - // This test will run in the MTA. - } - - [Test, Apartment(ApartmentState.STA)] - public void TestRequiringSTA() - { - // This test will run in the STA. - } -} -``` +[!code-csharp[ApartmentMethod](~/snippets/Snippets.NUnit/Attributes/ApartmentAttributeExamples.cs#ApartmentMethod)] + +## Notes + +1. When this attribute is not specified, tests run in the **MTA** by default. +2. When running tests in parallel, tests are scheduled to execute on a thread with the specified apartment state. +3. When parallel execution is disabled, a new thread may be created if the current thread doesn't have the correct apartment state. +4. This attribute replaces the obsolete `RequiresMTA` and `RequiresSTA` attributes. +5. The `ApartmentState.Unknown` value is not allowed and will cause an error. ## See Also -* [RequiresThread Attribute](requiresthread.md) +* [RequiresThread Attribute](xref:attribute-requiresthread) +* [SingleThreaded Attribute](xref:attribute-singlethreaded) +* [Parallelizable Attribute](xref:attribute-parallelizable) diff --git a/docs/articles/nunit/writing-tests/attributes/author.md b/docs/articles/nunit/writing-tests/attributes/author.md index b84ef2d9d..68b4d98ab 100644 --- a/docs/articles/nunit/writing-tests/attributes/author.md +++ b/docs/articles/nunit/writing-tests/attributes/author.md @@ -1,17 +1,51 @@ --- -uid: author-attribute +uid: attribute-author --- # Author -The **Author** Attribute adds information about the author of the tests. It can be applied to test fixtures and to -tests. +`AuthorAttribute` adds information about the author of tests. This metadata can be used by test runners and reporting tools to track test ownership and contact information. -The constructor takes the name of the test author and optionally the author's email address. Author can also be -specified on a TestFixture or Test attribute. +## Constructors + +```csharp +AuthorAttribute(string name) +AuthorAttribute(string name, string email) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `string` | The name of the test author. | +| `email` | `string` | The email address of the author. When provided, stored as `"name "`. | + +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ✅ | ✅ | ✅ | + +## Alternative Syntax + +`Author` can also be specified as a named parameter on `[TestFixture]` or `[Test]` attributes (name only, no email): + +```csharp +[TestFixture(Author = "Jane Doe")] +[Test(Author = "Joe Developer")] +``` + +## Example [!code-csharp[AuthorAttributeExample](~/snippets/Snippets.NUnit/Attributes/AuthorAttributeExamples.cs#AuthorAttributeExample)] -> [!NOTE] -> From NUnit version 3.7, you can have multiple Author attributes per fixture or test. Before version 3.7 you -> could only have one Author attribute per fixture or test. +## Notes + +1. This attribute inherits from `PropertyAttribute` and sets the `Author` property. +2. Multiple `Author` attributes can be applied to the same fixture or test (since **NUnit 3.7**). +3. Prior to NUnit 3.7, only one Author attribute was allowed per fixture or test. +4. When using the named parameter syntax (`Author = "name"`), only the name can be specified, not the email. + +## See Also + +* [Property Attribute](xref:attribute-property) +* [Description Attribute](xref:attribute-description) +* [TestOf Attribute](xref:attribute-testof) diff --git a/docs/articles/nunit/writing-tests/attributes/cancelafter.md b/docs/articles/nunit/writing-tests/attributes/cancelafter.md index 0f035182b..8ab3ec541 100644 --- a/docs/articles/nunit/writing-tests/attributes/cancelafter.md +++ b/docs/articles/nunit/writing-tests/attributes/cancelafter.md @@ -1,15 +1,35 @@ --- -uid: cancelafterattribute +uid: attribute-cancelafter --- # CancelAfter -Normally, NUnit simply runs tests and waits for them to terminate -- the test is allowed to run indefinitely. For -certain kinds of tests, however, it may be desirable to specify a timeout value. +`CancelAfterAttribute` sets a timeout after which NUnit marks a `CancellationToken` as canceled. The test must observe that token (directly or indirectly) for cancellation to take effect. + +## Constructor + +```csharp +CancelAfterAttribute(int timeout) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `timeout` | `int` | Timeout in milliseconds. When exceeded, the cancellation token supplied to the test is canceled (cooperative cancellation). | + +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ✅ | ✅ | ❌ | + +> [!NOTE] +> Applying `CancelAfter` to a fixture sets the default timeout for tests in that fixture unless overridden at method level. + +## Background For .NET Core and later, [`Thread.Abort`](https://learn.microsoft.com/en-us/dotnet/api/system.threading.thread.abort?view=net-8.0) as used by the -[`TimeoutAttribute`](./timeout.md) can no longer be used, and there is therefore no way to interrupt an endless loop. +[`TimeoutAttribute`](xref:attribute-timeout) can no longer be used, and there is therefore no way to interrupt an endless loop. For all tests, one could use the `--blame-hang(-timeout)` options of [`dotnet test`](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-test#options). However, this will stop any further @@ -17,7 +37,7 @@ execution of the remaining tests. To still be able to cancel tests, one has to move to cooperative cancellation. See [Cancellation in Managed Threads](https://learn.microsoft.com/en-us/dotnet/standard/threading/cancellation-in-managed-threads) using a -[`CancellationToken``](https://learn.microsoft.com/en-us/dotnet/api/system.threading.cancellationtoken?view=net-8.0). +[`CancellationToken`](https://learn.microsoft.com/en-us/dotnet/api/system.threading.cancellationtoken?view=net-8.0). The `CancelAfterAttribute` is used to specify a timeout value in milliseconds for a test case. If the test case runs longer than the time specified, the supplied `CancellationToken` is set to canceled. It is however up to the test code @@ -39,38 +59,28 @@ When used on test methods, NUnit automatically adds an extra argument to your me `CancellationToken`. If you want to check for cancellation in `SetUp` methods, you can use `TestContext.CurrentContext.CancellationToken` -## Example +## Examples -The `CancelAfterAttribute` supports cancellation across a variety of ways to write tests. +The `CancelAfterAttribute` supports cooperative cancellation in several test styles. -A simple test, written using the `Test` attribute: +### Simple test [!code-csharp[TestWithCancellationToken](~/snippets/Snippets.NUnit/Attributes/CancelAfterAttributeExamples.cs#TestWithCancellationToken)] -A parameterized test written using the `TestCase` attribute: +### Parameterized test with `TestCase` -```csharp -[CancelAfter(2000)] -[TestCase("http://server1")] -[TestCase("http://server2")] -public async Task PotentiallyLongRunningTest(string uri, CancellationToken token) -{ - HttpClient client = _httpClientFactory.CreateClient(); - HttpContent content = CreateContent(); - await client.PostAync(uri, content, token); - HttpResponseMessage response = await client.GetAsync(uri, token); - /* */ -} -``` +[!code-csharp[TestCaseWithCancellationToken](~/snippets/Snippets.NUnit/Attributes/CancelAfterAttributeExamples.cs#TestCaseWithCancellationToken)] -A parameterized test written using the `TestCaseSource` attribute: +### Parameterized test with `TestCaseSource` [!code-csharp[TestCaseSourceWithCancellationToken](~/snippets/Snippets.NUnit/Attributes/CancelAfterAttributeExamples.cs#TestCaseSourceWithCancellationToken)] -> [!NOTE] -> When debugging a unit test, i.e. when a debugger is attached to the process, the timeout is not enforced. +## Notes + +1. When a debugger is attached, the timeout is not enforced. +2. Use `TestContext.CurrentContext.CancellationToken` in `SetUp` / `TearDown` when you need the same token outside the test method. ## See Also -* [Timeout Attribute](./timeout.md) -* [MaxTime Attribute](./maxtime.md) +* [Timeout Attribute](xref:attribute-timeout) +* [MaxTime Attribute](xref:attribute-maxtime) diff --git a/docs/articles/nunit/writing-tests/attributes/category.md b/docs/articles/nunit/writing-tests/attributes/category.md index 1d5cdb097..b518ec466 100644 --- a/docs/articles/nunit/writing-tests/attributes/category.md +++ b/docs/articles/nunit/writing-tests/attributes/category.md @@ -1,28 +1,85 @@ +--- +uid: attribute-category +--- + # Category -The Category attribute provides an alternative to suites for dealing with groups of tests. Either individual test cases -or fixtures may be identified as belonging to a particular category. Some runners, including the Console Runner, allow -specifying categories to be included in or excluded from the run. When categories are used, only the tests in the -selected categories will be run. Those tests in categories that are not selected are not reported at all. +`CategoryAttribute` provides a way to group tests into categories. Categories can be used to include or exclude specific groups of tests when running from the command line or test runners. When categories are used to filter tests, only tests in the selected categories will be run, and excluded tests are not reported. + +## Constructors + +```csharp +CategoryAttribute(string name) +protected CategoryAttribute() // For derived classes +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `string` | The name of the category. May not contain `,`, `+`, `-`, or `!` characters. | + +The protected parameterless constructor is used when creating custom category attributes - it sets the category name to the derived class name (minus the "Attribute" suffix). + +## Properties + +| Property | Type | Description | +|----------|------|-------------| +| `Name` | `string` | Gets the name of the category. | + +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ✅ | ✅ | ✅ | > [!WARNING] -> While the C# syntax allows you to place a Category attribute on a SetUpFixture class, the attribute is -> ignored by NUnit and has no effect in current releases. +> While the C# syntax allows you to place a Category attribute on a SetUpFixture class, the attribute is ignored by NUnit and has no effect. -## Test Fixture Syntax +## Examples + +### Test Fixture Level [!code-csharp[CategoryTestFixtureExample](~/snippets/Snippets.NUnit/AttributeExamples.cs#CategoryTestFixtureExample)] -## Test Syntax +### Test Method Level [!code-csharp[CategoryTestExample](~/snippets/Snippets.NUnit/AttributeExamples.cs#CategoryTestExample)] ### Custom Category Attributes -Custom attributes that derive from **CategoryAttribute** will be recognized by NUnit. The default protected constructor -of CategoryAttribute sets the category name to the name of your class. - -Here's an example that creates a category of Critical tests. It works just like any other category, but has a simpler -syntax. A test reporting system might make use of the attribute to provide special reports. +Custom attributes that derive from `CategoryAttribute` will be recognized by NUnit. The default protected constructor sets the category name to the name of your class (minus "Attribute"). [!code-csharp[CustomCategoryAttribute](~/snippets/Snippets.NUnit/AttributeExamples.cs#CustomCategoryAttribute)] + +## Command Line Usage + +Categories can be filtered using `dotnet test` or the NUnit console runner: + +```shell +# dotnet test (via NUnit adapter) +dotnet test --filter "TestCategory=Fast" +dotnet test -- NUnit.Where="cat == Fast" + +# Exclude a category +dotnet test --filter "TestCategory!=Slow" + +# Multiple categories +dotnet test --filter "TestCategory=Unit|TestCategory=Integration" + +# NUnit Console Runner +nunit3-console MyTests.dll --where "cat == Fast" +nunit3-console MyTests.dll --where "cat != Slow" +nunit3-console MyTests.dll --where "cat == Unit || cat == Integration" +``` + +## Notes + +1. Multiple `Category` attributes can be applied to the same test or fixture. +2. Category names may not contain the characters `,`, `+`, `-`, or `!` as these are used as operators in category expressions. +3. Categories are inherited - a test inherits all categories from its fixture and assembly. +4. Category names are case-sensitive. +5. When no category filter is specified, all tests run regardless of their categories. + +## See Also + +* [Console Command Line](xref:consolecommandline) +* [Property Attribute](xref:attribute-property) diff --git a/docs/articles/nunit/writing-tests/attributes/combinatorial.md b/docs/articles/nunit/writing-tests/attributes/combinatorial.md index eeef77898..ea07f252f 100644 --- a/docs/articles/nunit/writing-tests/attributes/combinatorial.md +++ b/docs/articles/nunit/writing-tests/attributes/combinatorial.md @@ -1,28 +1,33 @@ --- -uid: combinatorialattribute +uid: attribute-combinatorial --- # Combinatorial -The **CombinatorialAttribute** is used on a test to specify that NUnit should -generate test cases for all possible combinations of the individual -data items provided for the parameters of a test. Since this is the -default, use of this attribute is optional. +`CombinatorialAttribute` is used on a test method to tell NUnit to generate test cases for all possible combinations of parameter values. -## Example +This is NUnit's default combining strategy, so using this attribute is optional unless you want to be explicit. + +## Usage -The following test will be executed six times: +This is a parameterless attribute that can only be applied to test methods. ```csharp -[Test, Combinatorial] -public void MyTest( - [Values(1, 2, 3)] int x, - [Values("A", "B")] string s) -{ - ... -} +[Combinatorial] ``` +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ✅ | ❌ | ❌ | + +## Example + +The following test is executed six times: + +[!code-csharp[CombinatorialBasic](~/snippets/Snippets.NUnit/Attributes/CombinatorialAttributeExamples.cs#CombinatorialBasic)] + MyTest is called six times, as follows: ```csharp @@ -34,14 +39,14 @@ MyTest(3, "A") MyTest(3, "B") ``` -## Limitations +## Notes -When used on a generic method the programmer must ensure that all -possible combinations of arguments are valid. When multiple parameters -use the same generic type (e.g.: T) this may not be possible and the -attribute may generate invalid test cases. +1. When used on a generic method, ensure all combinations of generated arguments are valid. +2. If multiple parameters share the same generic type (for example, `T`), some generated combinations may be invalid. +3. Use `Sequential` or `Pairwise` when combinatorial generation produces too many or unsuitable combinations. ## See Also -* [Sequential Attribute](sequential.md) -* [Pairwise Attribute](pairwise.md) +* [Sequential Attribute](xref:attribute-sequential) +* [Pairwise Attribute](xref:attribute-pairwise) +* [Values Attribute](xref:attribute-values) diff --git a/docs/articles/nunit/writing-tests/attributes/culture.md b/docs/articles/nunit/writing-tests/attributes/culture.md index a99deb4ee..fbbb9ebee 100644 --- a/docs/articles/nunit/writing-tests/attributes/culture.md +++ b/docs/articles/nunit/writing-tests/attributes/culture.md @@ -1,50 +1,64 @@ -# Culture +--- +uid: attribute-culture +--- -The Culture attribute is used to specify cultures for which a test or fixture should be run. It does not affect the -culture setting, but merely uses it to determine whether to run the test. If you wish to change the culture when running -a test, use the SetCulture attribute instead. +# Culture -If the specified culture requirements for a test are not met it is skipped. In the gui, the tree node for the test -remains gray and the status bar color is not affected. +`CultureAttribute` is used to specify cultures for which a test or fixture should be run. It does **not** change the culture setting, but merely uses it to determine whether to run the test. If the specified culture requirements are not met, the test is skipped. -One use of the Culture attribute is to provide alternative tests under different cultures. You may specify either -specific cultures, like "en-GB" or neutral cultures like "de". +This attribute is useful for providing alternative tests under different cultures, or for skipping tests that are not applicable to certain cultures. -## Test Fixture Syntax +## Constructors ```csharp -namespace NUnit.Tests -{ - using System; - using NUnit.Framework; - - [TestFixture] - [Culture("fr-FR")] - public class FrenchCultureTests - { - // ... - } -} +CultureAttribute() +CultureAttribute(string cultures) ``` -## Test Syntax +| Parameter | Type | Description | +|-----------|------|-------------| +| `cultures` | `string` | A comma-delimited list of culture names to include. You may specify either specific cultures like `"en-GB"` or neutral cultures like `"de"`. | -```csharp -namespace NUnit.Tests -{ - using System; - using NUnit.Framework; - - [TestFixture] - public class SuccessTests - { - [Test] - [Culture(Exclude="en,de")] - public void SomeTest() - { /* ... */ } -} -``` +## Properties + +| Property | Type | Description | Default | +|----------|------|-------------|---------| +| `Include` | `string` | Comma-delimited list of cultures on which the test should run. | `null` | +| `Exclude` | `string` | Comma-delimited list of cultures on which the test should **not** run. | `null` | +| `Reason` | `string` | The reason for including or excluding the test. Displayed when the test is skipped. | `null` | + +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ✅ | ✅ | ✅ | + +## Examples + +### Including Specific Cultures + +[!code-csharp[CultureInclude](~/snippets/Snippets.NUnit/Attributes/CultureAttributeExamples.cs#CultureInclude)] + +### Excluding Cultures + +[!code-csharp[CultureExclude](~/snippets/Snippets.NUnit/Attributes/CultureAttributeExamples.cs#CultureExclude)] + +### Applying to a Fixture + +[!code-csharp[CultureOnFixture](~/snippets/Snippets.NUnit/Attributes/CultureAttributeExamples.cs#CultureOnFixture)] + +### Providing a Reason + +[!code-csharp[CultureWithReason](~/snippets/Snippets.NUnit/Attributes/CultureAttributeExamples.cs#CultureWithReason)] + +## Notes + +1. When specifying a neutral culture (e.g., `"fr"`), the test will run on any specific culture variant (e.g., `fr-FR`, `fr-CA`, `fr-BE`). +2. If both `Include` and `Exclude` are specified, `Include` is evaluated first. +3. This attribute does **not** change the culture. To change the culture for a test, use `SetCulture` or `SetUICulture` instead. +4. Tests that are skipped due to culture requirements appear as "Skipped" in test results with the reason displayed. ## See Also -* [SetCulture Attribute](setculture.md) +* [SetCulture Attribute](xref:attribute-setculture) +* [SetUICulture Attribute](xref:attribute-setuiculture) diff --git a/docs/articles/nunit/writing-tests/attributes/datapoint.md b/docs/articles/nunit/writing-tests/attributes/datapoint.md index ce5ea5961..bdb532ab8 100644 --- a/docs/articles/nunit/writing-tests/attributes/datapoint.md +++ b/docs/articles/nunit/writing-tests/attributes/datapoint.md @@ -1,34 +1,64 @@ +--- +uid: attribute-datapoint +--- + # Datapoint -The **Datapoint** attribute is used -to provide data for **Theories** and is ignored for ordinary -tests - including tests with parameters. +`DatapointAttribute` is used to mark a field as providing a single data value for [Theory](xref:attribute-theory) tests. When NUnit executes a Theory, it uses all fields of matching type annotated with `[Datapoint]` to supply argument values. + +This attribute is ignored for ordinary tests, including parameterized tests using `[TestCase]`. + +## Usage + +This is a parameterless attribute that can only be applied to fields. + +```csharp +[Datapoint] +``` + +## Applies To + +| Field | Test Methods | Test Fixtures (Classes) | Assembly | +|-------|--------------|--------------------------|----------| +| ✅ | ❌ | ❌ | ❌ | + +> [!NOTE] +> The field type must exactly match the Theory parameter type - no implicit conversions are performed. -When a Theory is loaded, NUnit creates arguments for each -of its parameters by using any fields of the same type -as the parameter annotated with the **DatapointAttribute**. -Fields must be members of the class containing the Theory -and their Type must exactly match the argument for which -data is being supplied. +## Examples + +### Basic Usage + +[!code-csharp[DatapointBasic](~/snippets/Snippets.NUnit/Attributes/DatapointAttributeExamples.cs#DatapointBasic)] + +### With Enums and Automatic Datapoints + +[!code-csharp[DatapointWithEnum](~/snippets/Snippets.NUnit/Attributes/DatapointAttributeExamples.cs#DatapointWithEnum)] + +### Multiple Types + +[!code-csharp[DatapointMultipleTypes](~/snippets/Snippets.NUnit/Attributes/DatapointAttributeExamples.cs#DatapointMultipleTypes)] ## Automatically Supplied Datapoints -It is normally not necessary to specify datapoints for -**boolean** or **enum** arguments. -NUnit automatically supplies values of **true** -and **false** for **boolean** arguments and will supply all -defined values of any enumeration. +NUnit automatically supplies datapoints for certain types: + +| Type | Automatic Values | +|------|-----------------| +| `bool` | `true`, `false` | +| Any `enum` | All defined enum values | -If for some reason you don't wish to use all possible values, you -can override this behavior by supplying your own datapoints. If you -supply any datapoints for an argument, automatic datapoint generation -is suppressed. +If you supply any datapoints for a parameter type, automatic datapoint generation for that type is suppressed. -## Example +## Notes -For an example of use, see [Theory Attribute](theory.md) +1. Fields must be members of the class containing the Theory. +2. The field type must **exactly** match the parameter type - no implicit conversions are performed. +3. Use `DatapointSource` when you need to provide multiple values from a single source (arrays, collections, or methods). +4. Datapoints from multiple fields of the same type are combined. ## See Also -* [Theory Attribute](theory.md) +* [DatapointSource Attribute](xref:attribute-datapointsource) +* [Theory Attribute](xref:attribute-theory) * [Parameterized Tests](xref:parameterizedtests) diff --git a/docs/articles/nunit/writing-tests/attributes/datapointsource.md b/docs/articles/nunit/writing-tests/attributes/datapointsource.md index fcf219438..0437769d1 100644 --- a/docs/articles/nunit/writing-tests/attributes/datapointsource.md +++ b/docs/articles/nunit/writing-tests/attributes/datapointsource.md @@ -1,37 +1,55 @@ +--- +uid: attribute-datapointsource +--- + # DatapointSource -The **DatapointSource** attribute is used -to provide data for **Theories** and is ignored for ordinary -tests - including tests with parameters. +`DatapointSourceAttribute` is used to mark a field, property, or method as providing a collection of data values for [Theory](xref:attribute-theory) tests. The source must return either an array of the required type or an `IEnumerable`. -Collections of datapoints may be provided by use of the **DatapointSourceAttribute**. -This attribute may be placed on methods or -properties in addition to fields. The returned value must be -either an array of the required type or an `IEnumerable` returning an enumeration -of the required type. The data Type must exactly match the argument -for which data is being supplied. +This attribute is ignored for ordinary tests, including parameterized tests using `[TestCase]`. -> In earlier versions of NUnit, the obsolete **DatapointsAttribute** -> was used in place of **DatapointSourceAttribute**. +## Usage -## Automatically Supplied Datapoints +This is a parameterless attribute that can be applied to fields, properties, or methods. + +```csharp +[DatapointSource] +``` -It is normally not necessary to specify datapoints for -**boolean** or **enum** arguments. -NUnit automatically supplies values of **true** -and **false** for **boolean** arguments and will supply all -defined values of any enumeration. +## Applies To -If for some reason you don't wish to use all possible values, you -can override this behavior by supplying your own datapoints. If you -supply any datapoints for an argument, automatic datapoint generation -is suppressed. +| Field | Property | Parameterless Methods | Test Methods | Test Fixtures (Classes) | Assembly | +|-------|----------|-----------------------|--------------|--------------------------|----------| +| ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | + +> [!NOTE] +> Parameterless methods used with this attribute must return an array or `IEnumerable`, and the element type must exactly match the Theory parameter type. ## Example -For an example of use, see [Theory Attribute](theory.md) +[!code-csharp[DatapointSource](~/snippets/Snippets.NUnit/Attributes/DatapointAttributeExamples.cs#DatapointSource)] + +## Automatically Supplied Datapoints + +NUnit automatically supplies datapoints for certain types: + +| Type | Automatic Values | +|------|-----------------| +| `bool` | `true`, `false` | +| Any `enum` | All defined enum values | + +If you supply any datapoints for a parameter type, automatic datapoint generation for that type is suppressed. + +## Notes + +1. The data source must be a member of the class containing the Theory. +2. The element type must **exactly** match the parameter type - no implicit conversions are performed. +3. Multiple `DatapointSource` attributes of the same type are combined. +4. Use `Datapoint` when you only need to provide a single value from a field. +5. The obsolete `DatapointsAttribute` was replaced by `DatapointSourceAttribute` in earlier versions. ## See Also -* [Theory Attribute](theory.md) +* [Datapoint Attribute](xref:attribute-datapoint) +* [Theory Attribute](xref:attribute-theory) * [Parameterized Tests](xref:parameterizedtests) diff --git a/docs/articles/nunit/writing-tests/attributes/defaultfloatingpointtolerance.md b/docs/articles/nunit/writing-tests/attributes/defaultfloatingpointtolerance.md index 0d7e81c7f..6d2e67b8f 100644 --- a/docs/articles/nunit/writing-tests/attributes/defaultfloatingpointtolerance.md +++ b/docs/articles/nunit/writing-tests/attributes/defaultfloatingpointtolerance.md @@ -1,51 +1,49 @@ +--- +uid: attribute-defaultfloatingpointtolerance +--- + # DefaultFloatingPointTolerance -The **DefaultFloatingPointToleranceAttribute** is used to indicate that -comparisons of values of types `float` and `double` - within the test method, -class, or assembly marked with the attribute - should use the tolerance -specified in the constructor unless a specific tolerance is given for the -comparison. +`DefaultFloatingPointToleranceAttribute` sets the default tolerance for floating-point equality comparisons (`float` and `double`) unless a comparison explicitly specifies a tolerance. -## Examples +You can apply it at method, fixture, or assembly scope. + +## Constructor ```csharp -[TestFixture] -[DefaultFloatingPointTolerance(1)] -public class ToleranceTest -{ - [Test] - public void ComparisonUsingDefaultFloatingPointToleranceFromFixture() - { - // Passes due to the DefaultFloatingPointToleranceAttribute from the fixture. - Assert.That(1f, Is.EqualTo(2)); - } - - [Test] - public void ComparisonOfIntegersDoNotUseTolerance() - { - // Fails as DefaultFloatingPointTolerance only effects comparisons - // of floats and doubles. - Assert.That(1, Is.EqualTo(2)); - } - - [Test] - public void ComparisonUsingSpecificTolerance() - { - // Fails as 1 is not equal to 2 using the specified tolerance 0. - Assert.That(1f, Is.EqualTo(2).Within(0)); - } - - [Test] - [DefaultFloatingPointTolerance(2)] - public void ComparisonUsingDefaultFloatingPointToleranceFromTest() - { - // Passes due to the DefaultFloatingPointTolerance from the test. - Assert.That(2f, Is.EqualTo(4)); - } -} +DefaultFloatingPointToleranceAttribute(double tolerance) ``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `tolerance` | `double` | The default tolerance used for floating-point comparisons when no explicit tolerance is specified. | + +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ✅ | ✅ | ✅ | + +> [!NOTE] +> When applied at fixture or assembly level, this default tolerance applies to all contained tests unless overridden by a more specific scope or by an explicit tolerance in an assertion. + +## Examples + +### Fixture Default Tolerance + +[!code-csharp[DefaultFloatingPointToleranceFixture](~/snippets/Snippets.NUnit/Attributes/DefaultFloatingPointToleranceAttributeExamples.cs#DefaultFloatingPointToleranceFixture)] + +### Method Override + +[!code-csharp[DefaultFloatingPointToleranceMethodOverride](~/snippets/Snippets.NUnit/Attributes/DefaultFloatingPointToleranceAttributeExamples.cs#DefaultFloatingPointToleranceMethodOverride)] + +## Notes + +1. This attribute affects default tolerance for floating-point equality comparisons only. +2. Integer comparisons are not affected. +3. An explicit tolerance in an assertion (for example, `.Within(...)`) overrides the default tolerance. + ## See Also -* [Assert.AreEqual](../assertions/classic-assertions/Assert.AreEqual.md) -* [EqualConstraint](../constraints/EqualConstraint.md) +* [Assert.AreEqual](xref:classic-assert-are-equal) +* [EqualConstraint](xref:constraint-equal) — numeric **`Within`** tolerances and floating-point comparison behavior (including the **Comparing floating-point values** section) diff --git a/docs/articles/nunit/writing-tests/attributes/description.md b/docs/articles/nunit/writing-tests/attributes/description.md index a9edcaf24..3bbcb922e 100644 --- a/docs/articles/nunit/writing-tests/attributes/description.md +++ b/docs/articles/nunit/writing-tests/attributes/description.md @@ -1,12 +1,59 @@ +--- +uid: attribute-description +--- + # Description -The Description attribute is used to apply descriptive text to a Test, TestFixture or Assembly. The text appears in the -XML output file. +`DescriptionAttribute` is used to apply descriptive text to a test, test fixture, or assembly. The description appears in test output and XML result files, providing additional context about what a test does. + +## Constructor + +```csharp +DescriptionAttribute(string description) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `description` | `string` | The descriptive text for the test or fixture. | + +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ✅ | ✅ | ✅ | + +## Alternative Syntax + +`Description` can also be specified as a named parameter on `[TestFixture]` or `[Test]` attributes: + +```csharp +[TestFixture(Description = "Tests for user authentication")] +[Test(Description = "Verifies login with valid credentials")] +``` + +## Examples + +### Fixture Level + +[!code-csharp[DescriptionFixture](~/snippets/Snippets.NUnit/Attributes/DescriptionAttributeExamples.cs#DescriptionFixture)] + +### Method Level + +[!code-csharp[DescriptionMethod](~/snippets/Snippets.NUnit/Attributes/DescriptionAttributeExamples.cs#DescriptionMethod)] + +### Using Named Parameter Syntax + +[!code-csharp[DescriptionNamedParameter](~/snippets/Snippets.NUnit/Attributes/DescriptionAttributeExamples.cs#DescriptionNamedParameter)] + +## Notes -## Example +1. This attribute inherits from `PropertyAttribute` and sets the `Description` property. +2. Only one description can be applied per element (`AllowMultiple = false`). +3. If both the `[Description]` attribute and the `Description` property on `[Test]`/`[TestFixture]` are used, the `[Description]` attribute takes precedence. +4. Descriptions are useful for generating readable test reports and documentation. -[!code-csharp[DescriptionTestExample](~/snippets/Snippets.NUnit/AttributeExamples.cs#DescriptionTestExample)] +## See Also -> [!NOTE] -> The Test and TestFixture attributes continue to support an optional Description property. The Description -> attribute should be used for new applications. If both are used, the Description attribute takes precedence. +* [Property Attribute](xref:attribute-property) +* [Author Attribute](xref:attribute-author) +* [Category Attribute](xref:attribute-category) diff --git a/docs/articles/nunit/writing-tests/attributes/explicit.md b/docs/articles/nunit/writing-tests/attributes/explicit.md index ac41bd85c..c79796d94 100644 --- a/docs/articles/nunit/writing-tests/attributes/explicit.md +++ b/docs/articles/nunit/writing-tests/attributes/explicit.md @@ -1,15 +1,40 @@ +--- +uid: attribute-explicit +--- + # Explicit -The Explicit attribute causes a test or test fixture to be skipped unless it is explicitly selected for running. The -test or fixture will be run if it is selected by name or if it is included by use of a filter. A **not** filter, which -excludes certain tests, is not treated as an explicit selection and never causes an explicit test to be run. All other -filters are considered to explicitly select the tests that they match. See examples below. +`ExplicitAttribute` marks a test, fixture, or assembly so it is **not** run merely because an enclosing suite ran. It +runs only when it is **explicitly selected**—for example by choosing that test or fixture by name, or by using a filter +that counts as an explicit match for it. + +A filter that **excludes** tests (often written with **not**, such as `--where test!=My.Fixture`) is **not** treated as +explicitly selecting what is left behind, so explicit tests remain skipped unless you chose them via a positive +selection (direct name selection or filters that affirmatively match the test or a suite it lives under). The +command-line examples below show forms that include or exclude explicit tests. + +You can pass an optional **reason** string; when the test is skipped as explicit, runners may show that text. + +If an explicit item is executed as part of a broad “run everything” session but was never explicitly selected, NUnit skips +it with an **explicit** result. That outcome does not fail the run or count as an ordinary failure. Presentation in the UI +(or console summary) varies by runner. + +## Constructors -An optional string argument may be used to give the reason for marking the test Explicit. +```csharp +ExplicitAttribute() +ExplicitAttribute(string reason) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `reason` | `string` | Optional reason shown in skip output. | -If a test or fixture with the Explicit attribute is encountered in the course of running tests, it is skipped unless it -has been specifically selected by one of the above means. The test does not affect the overall result of the test run. -Explicit tests are displayed in the gui as skipped. +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ✅ | ✅ | ✅ | > [!WARNING] > While the C# syntax allows you to place an Explicit attribute on a SetUpFixture class, the attribute is @@ -74,114 +99,8 @@ dotnet test -- NUnit.ExplicitMode=None ## Test Fixture Syntax -C#: - -```csharp -namespace NUnit.Tests -{ - using System; - using NUnit.Framework; - - [TestFixture, Explicit] - public class ExplicitTests - { - // ... - } -} -``` - -Visual Basic: - -```VB -Imports System -Imports NUnit.Framework - -Namespace NUnit.Tests - - - Public Class ExplicitTests - ' ... - End Class -End Namespace -``` - -C++: - -```cpp -using namespace System; -using namespace NUnit::Framework; - -namespace NUnitTests -{ - [TestFixture] - [Explicit] - public __gc class ExplicitTests - { - // ... - }; -} - -# include "cppsample.h" - -namespace NUnitTests { - // ... -} -``` +[!code-csharp[ExplicitFixtureExample](~/snippets/Snippets.NUnit/Attributes/ExplicitAttributeExamples.cs#ExplicitFixtureExample)] ## Test Syntax -C#: - -```csharp -namespace NUnit.Tests -{ - using System; - using NUnit.Framework; - - [TestFixture] - public class SuccessTests - { - [Test, Explicit] - public void ExplicitTest() - { /* ... */ } -} -``` - -Visual Basic: - -```vb -Imports System -Imports NUnit.Framework - -Namespace NUnit.Tests - - Public Class SuccessTests - Public Sub ExplicitTest() - ' ... - End Sub - End Class -End Namespace -``` - -C++: - -```cpp -# using -using namespace System; -using namespace NUnit::Framework; - -namespace NUnitTests -{ - [TestFixture] - public __gc class SuccessTests - { - [Test][Explicit] void ExplicitTest(); - }; -} - -# include "cppsample.h" - -namespace NUnitTests { - // ... -} -``` +[!code-csharp[ExplicitTestExample](~/snippets/Snippets.NUnit/Attributes/ExplicitAttributeExamples.cs#ExplicitTestExample)] diff --git a/docs/articles/nunit/writing-tests/attributes/fixturelifecycle.md b/docs/articles/nunit/writing-tests/attributes/fixturelifecycle.md index 6bfeb05b3..18de6cfbd 100644 --- a/docs/articles/nunit/writing-tests/attributes/fixturelifecycle.md +++ b/docs/articles/nunit/writing-tests/attributes/fixturelifecycle.md @@ -1,49 +1,73 @@ ---- -uid: fixturelifecycleattribute ---- - -# FixtureLifeCycle - -Added in **NUnit 3.13** - -The `FixtureLifeCycleAttribute` is used to indicate that an instance for a test fixture or all test fixtures in an -assembly should be constructed for each test within the fixture or assembly. - -This attribute may be applied to a test fixture (class) or to a test assembly. It is useful in combination with the -[Parallelizable Attribute](parallelizable.md) so that a new instance of a test fixture is constructed for every test -within the test fixture. This allows tests to run in isolation without sharing instance fields and properties during -parallel test runs. This make running parallel tests easier because it is easier to make your tests thread safe. - -This attribute can be applied to classes or to the entire test assembly. If applied to an assembly, it may be overridden -at the class level. - -## LifeCycle Enumeration - -The constructor of `FixtureLifeCycleAttribute` takes a `LifeCycle` attribute to indicate if a single instance of a test -fixture should be created for all tests or if a new instance should be created for each test. - - Value | Meaning --------|--------- -`LifeCycle.SingleInstance` | A single instance is created and shared for all test cases. This is the default. -`LifeCycle.InstancePerTestCase` | A new instance is created for each test case - -## Notes - -* When using `LifeCycle.InstancePerTestCase`, the [`OneTimeSetUp`](xref:onetimesetup-attribute) and - [`OneTimeTearDown`](xref:onetimeteardown-attribute) methods must be static, and each are only called once. This is - required so that the setup or teardown methods do not access instance fields or properties that are reset for every - test. - -* When using `LifeCycle.InstancePerTestCase`, a class's constructor will be called before every test is executed and - `IDisposable` test fixtures will be disposed after the test is finished. - -* [`SetUp`](xref:setup-attribute) and [`TearDown`](xref:teardown-attribute) methods are called before and after every - test. - -* The `Order` attribute is respected. - -## See Also - -* [Parallelizable Attribute](xref:parallelizableattribute) -* [OneTimeSetUp Attribute](xref:onetimesetup-attribute) -* [OneTimeTearDown Attribute](xref:onetimeteardown-attribute) +--- +uid: attribute-fixturelifecycle +--- + +# FixtureLifeCycle + +Added in **NUnit 3.13**. + +`FixtureLifeCycleAttribute` selects how NUnit constructs your fixture class: + +* **`LifeCycle.SingleInstance`** — one instance is created and **shared** by every test in the fixture. This matches the + usual NUnit default when you do not use the attribute. +* **`LifeCycle.InstancePerTestCase`** — a **new** instance is created for each test. + +Place the attribute on a **fixture class** to control that class, or on the **assembly** to set a default for all +fixtures in that assembly. A class-level attribute **overrides** an assembly-level default. + +`InstancePerTestCase` is often combined with [Parallelizable](xref:attribute-parallelizable). With a separate instance per test, +instance fields are not shared while tests run in parallel, which avoids a common source of interference and often makes +**thread safety for instance state** easier—while still leaving you responsible for static state, shared singletons, and +other resources outside the fixture instance. + +## Constructor + +```csharp +FixtureLifeCycleAttribute(LifeCycle lifeCycle) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `lifeCycle` | `LifeCycle` | `SingleInstance` or `InstancePerTestCase`. | + +## Properties + +| Property | Type | Description | Default | +|----------|------|-------------|---------| +| `LifeCycle` | `LifeCycle` | Life cycle for the fixture or assembly. | _(from constructor)_ | + +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ❌ | ✅ | ✅ | + +Assembly-level settings can be overridden by a class-level attribute. + +## LifeCycle enumeration + +| Value | Meaning | +|-------|---------| +| `LifeCycle.SingleInstance` | A single instance is created and shared for all test cases. This is the default. | +| `LifeCycle.InstancePerTestCase` | A new instance is created for each test case. | + +## Notes + +* When using `LifeCycle.InstancePerTestCase`, the [`OneTimeSetUp`](xref:attribute-onetimesetup) and + [`OneTimeTearDown`](xref:attribute-onetimeteardown) methods must be static, and each are only called once. This is + required so that the setup or teardown methods do not access instance fields or properties that are reset for every + test. + +* When using `LifeCycle.InstancePerTestCase`, a class's constructor will be called before every test is executed and + `IDisposable` test fixtures will be disposed after the test is finished. + +* [`SetUp`](xref:attribute-setup) and [`TearDown`](xref:attribute-teardown) methods are called before and after every + test. + +* The `Order` attribute is respected. + +## See Also + +* [Parallelizable Attribute](xref:attribute-parallelizable) +* [OneTimeSetUp Attribute](xref:attribute-onetimesetup) +* [OneTimeTearDown Attribute](xref:attribute-onetimeteardown) diff --git a/docs/articles/nunit/writing-tests/attributes/ignore.md b/docs/articles/nunit/writing-tests/attributes/ignore.md index 86cbc8407..a83e26bf6 100644 --- a/docs/articles/nunit/writing-tests/attributes/ignore.md +++ b/docs/articles/nunit/writing-tests/attributes/ignore.md @@ -1,48 +1,52 @@ +--- +uid: attribute-ignore +--- + # Ignore -**IgnoreAttribute** is used to indicate that a test should not be executed for some reason. Note that with NUnit 3, the -reason must be specified. Ignored tests are displayed by the runners as warnings in order to provide a reminder that the -test needs to be corrected or otherwise changed and re-instated. +`IgnoreAttribute` indicates that a test should not be executed. In NUnit 3 and later, a reason must be provided. -Note that the **IgnoreAttribute** is attached to a method. If you have multiple test cases using the same method, adding -it will ignore all the cases. To ignore individual test cases see [Ignoring Individual Test -Cases](#ignoring-individual-test-cases) below. +Ignored tests are shown as warnings by runners, which helps highlight tests that need to be fixed or re-enabled. -## Test Fixture Syntax +## Constructor ```csharp -namespace NUnit.Tests -{ - using System; - using NUnit.Framework; - - [TestFixture] - [Ignore("Ignore a fixture")] - public class SuccessTests - { - // ... - } -} +IgnoreAttribute(string reason) ``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `reason` | `string` | The reason the test or fixture is ignored. This value is required. | + +## Properties + +| Property | Type | Description | Default | +|----------|------|-------------|---------| +| `Until` | `string` | Optional date/time string. The test is ignored until this date/time, then runs normally. | `null` | + +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ✅ | ✅ | ✅ | + +> [!NOTE] +> When applied to a fixture or assembly, all contained tests are ignored. + +## Test Fixture Syntax + +[!code-csharp[IgnoreFixtureExample](~/snippets/Snippets.NUnit/Attributes/IgnoreAttributeExamples.cs#IgnoreFixtureExample)] + ## Test Syntax -[!code-csharp[IgnoreTestExample](~/snippets/Snippets.NUnit/AttributeExamples.cs#IgnoreTestExample)] +[!code-csharp[IgnoreTestExample](~/snippets/Snippets.NUnit/Attributes/IgnoreAttributeExamples.cs#IgnoreTestExample)] ## Ignore Until The `Until` named parameter allows you to ignore a test for a specific period of time, after which the test will run normally. The until date must be a string that can be parsed to a date. -```csharp -[TestFixture] -[Ignore("Waiting for Joe to fix his bugs", Until = "2014-07-31 12:00:00Z")] -public class MyTests -{ - [Test] - public void Test1() { /* ... */ } -} -``` +[!code-csharp[IgnoreUntilExample](~/snippets/Snippets.NUnit/Attributes/IgnoreAttributeExamples.cs#IgnoreUntilExample)] In the above example, it's assumed that the test would fail if run. With the IgnoreAttribute, it will give a warning until the specified date. After that time, it will run normally and either pass or fail. @@ -52,7 +56,19 @@ until the specified date. After that time, it will run normally and either pass The **IgnoreAttribute** causes all the test cases using the method on which it is placed to be ignored. Ignoring individual test cases is possible, depending on how they are specified. - Attribute | How to ignore a case ---------------------|------------------------------------------------------------------ -**TestCase** | Use the **Ignore** named parameter of the **TestCaseAttribute.** -**TestCaseSource** | Use **TestCaseData** for the source and set the **Ignore** property. +| Attribute | How to ignore a case | +|-----------|----------------------| +| **TestCase** | Use the **Ignore** named parameter of `TestCaseAttribute`. | +| **TestCaseSource** | Use `TestCaseData` for the source and set the **Ignore** property. | + +## Notes + +1. Applying `IgnoreAttribute` to a test method ignores all test cases produced by that method. +2. To ignore individual cases, use `Ignore` on `TestCaseAttribute` or `TestCaseData`. +3. The `Until` value must be parseable as a date/time; after that instant, the test runs normally. + +## See Also + +* [Explicit Attribute](xref:attribute-explicit) +* [TestCase Attribute](xref:attribute-testcase) +* [TestCaseSource Attribute](xref:attribute-testcasesource) diff --git a/docs/articles/nunit/writing-tests/attributes/levelofparallelism.md b/docs/articles/nunit/writing-tests/attributes/levelofparallelism.md index 824bb585c..b3c9143b2 100644 --- a/docs/articles/nunit/writing-tests/attributes/levelofparallelism.md +++ b/docs/articles/nunit/writing-tests/attributes/levelofparallelism.md @@ -1,26 +1,53 @@ +--- +uid: attribute-levelofparallelism +--- + # LevelOfParallelism -This is an _assembly-level_ attribute, which may be used to specify the level of parallelism, that is, the maximum -number of worker threads executing tests in the assembly. It may be overridden using a command-line option in the -console runner. +`LevelOfParallelismAttribute` is an assembly-level attribute used to specify the maximum number of worker threads that may execute tests simultaneously. This controls how many tests can run in parallel. + +## Constructor + +```csharp +LevelOfParallelismAttribute(int level) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `level` | `int` | The maximum number of worker threads to be created by the framework for running tests. | -This attribute is optional. If it is not specified, NUnit uses the processor count or 2, whichever is greater. For -example, on a four processor machine the default value is 4. +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ❌ | ❌ | ✅ | + +Typically placed in `AssemblyInfo.cs` or a global usings file. + +## Default Value + +If this attribute is not specified, NUnit uses `Environment.ProcessorCount` or 2, whichever is greater. For example, on an 8-core machine, the default is 8 worker threads. ## Example -The following code, which might be placed in AssemblyInfo.cs, sets the level of parallelism to 3: +The following code, placed in `AssemblyInfo.cs`, limits parallel execution to 3 worker threads: ```csharp -[assembly:LevelOfParallelism(3)] +using NUnit.Framework; + +[assembly: LevelOfParallelism(3)] ``` -## Platform Support +## Notes -Parallel execution is supported by the NUnit framework on desktop .NET runtimes. It is not supported in our Portable or -.NET Standard builds at this time, although the attributes are recognized without error in order to allow use in -projects that build against multiple targets. +1. This attribute controls the **maximum** number of parallel workers. The actual number may be lower depending on the tests and their parallelization settings. +2. Tests must be marked with `[Parallelizable]` to actually run in parallel. This attribute only sets the upper limit on worker threads. +3. Setting the level to 1 effectively disables parallelism (only one test runs at a time). +4. This value can be overridden using the `--workers` command-line option in the NUnit console runner. +5. Consider your test dependencies and shared resources when setting this value. Higher parallelism can cause issues with tests that share state. ## See Also -* [Parallelizable Attribute](parallelizable.md) +* [Parallelizable Attribute](xref:attribute-parallelizable) +* [NonParallelizable Attribute](xref:attribute-nonparallelizable) +* [Console Command Line](xref:consolecommandline) diff --git a/docs/articles/nunit/writing-tests/attributes/maxtime.md b/docs/articles/nunit/writing-tests/attributes/maxtime.md index 8200778e8..706dd355b 100644 --- a/docs/articles/nunit/writing-tests/attributes/maxtime.md +++ b/docs/articles/nunit/writing-tests/attributes/maxtime.md @@ -1,30 +1,48 @@ +--- +uid: attribute-maxtime +--- + # MaxTime -The **MaxTimeAttribute** is used on test methods to specify a maximum time -in milliseconds for a test case. If the test case takes longer than the -specified time to complete, it is reported as a failure. +`MaxTimeAttribute` is used on test methods to specify a maximum time in milliseconds for a test case. If the test takes longer than the specified time to complete, it is reported as a failure. + +Unlike `CancelAfter`, this attribute does **not** cancel the test - it waits for the test to complete and then checks the elapsed time. -## Example +## Constructor ```csharp -[Test, MaxTime(2000)] -public void TimedTest() -{ - /* ... */ -} +MaxTimeAttribute(int milliseconds) ``` -## Notes +| Parameter | Type | Description | +|-----------|------|-------------| +| `milliseconds` | `int` | The maximum elapsed time in milliseconds. If the test exceeds this time, it fails. | + +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ✅ | ❌ | ❌ | + +## Examples -1. Any assertion failures take precedence over the elapsed time check. +### Basic Usage + +[!code-csharp[MaxTimeBasic](~/snippets/Snippets.NUnit/Attributes/MaxTimeAttributeExamples.cs#MaxTimeBasic)] + +### Assertion Failures Take Precedence + +[!code-csharp[MaxTimeVsAssertions](~/snippets/Snippets.NUnit/Attributes/MaxTimeAttributeExamples.cs#MaxTimeVsAssertions)] + +## Notes -2. This attribute does not cancel the test if the time - is exceeded. It merely waits for the test to complete and then - compares the elapsed time to the specified maximum. If you want to - cancel long-running tests, see [CancelAfter Attribute](cancelafter.md). - The [Timeout Attribute](timeout.md) only works for .NET Framework and will give a test error if used for .NET. +1. Any assertion failures take precedence over the elapsed time check. If a test both fails an assertion and exceeds the time limit, the assertion failure is reported. +2. This attribute does **not** cancel or abort the test if the time is exceeded. It waits for the test to complete, then compares the elapsed time to the maximum. +3. For tests that need to be cancelled when they exceed a time limit, use [CancelAfter Attribute](xref:attribute-cancelafter) instead. +4. The timing includes the test method execution only, not `SetUp` or `TearDown` methods. +5. The [Timeout Attribute](xref:attribute-timeout) uses `Thread.Abort` and only works on .NET Framework. ## See Also -* [CancelAfter Attribute](./cancelafter.md) -* [Timeout Attribute](timeout.md) +* [CancelAfter Attribute](xref:attribute-cancelafter) +* [Timeout Attribute](xref:attribute-timeout) diff --git a/docs/articles/nunit/writing-tests/attributes/netplatform.md b/docs/articles/nunit/writing-tests/attributes/netplatform.md index d40f06d57..b1829bd16 100644 --- a/docs/articles/nunit/writing-tests/attributes/netplatform.md +++ b/docs/articles/nunit/writing-tests/attributes/netplatform.md @@ -1,11 +1,11 @@ --- -uid: netplatformattribute +uid: attribute-netplatform --- # NetPlatform The `NetPlatformAttribute` is used to specify platforms for which a test or fixture should be run. It is a modern -replacement for the [Platform](platform.md) attribute, using platform names based on the .NET `TargetFramework` +replacement for the [Platform](xref:attribute-platform) attribute, using platform names based on the .NET `TargetFramework` conventions as documented in [CA1416: Validate platform compatibility](https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1416). @@ -19,6 +19,30 @@ skipped. > This attribute was introduced in NUnit 4.6 and provides better alignment with .NET's built-in platform checking > mechanisms compared to the older `PlatformAttribute`. +## Constructors + +```csharp +NetPlatformAttribute() +NetPlatformAttribute(string platforms) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `platforms` | `string` | Comma-delimited list of included platforms. | + +## Properties + +| Property | Type | Description | Default | +|----------|------|-------------|---------| +| `Include` | `string` | Comma-delimited platform list that should run. | `null` | +| `Exclude` | `string` | Comma-delimited platform list that should be skipped. | `null` | + +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ✅ | ✅ | ✅ | + ## Test Fixture Syntax [!code-csharp[NetPlatformFixture](~/snippets/Snippets.NUnit/Attributes/NetPlatformAttributeExamples.cs#NetPlatformFixture)] @@ -80,6 +104,6 @@ Platform names can include version numbers to specify minimum version requiremen ## See Also -* [Platform Attribute](platform.md) -* [Culture Attribute](culture.md) +* [Platform Attribute](xref:attribute-platform) +* [Culture Attribute](xref:attribute-culture) * [CA1416: Validate platform compatibility](https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1416) diff --git a/docs/articles/nunit/writing-tests/attributes/nonparallelizable.md b/docs/articles/nunit/writing-tests/attributes/nonparallelizable.md index d319c63a1..f845e218b 100644 --- a/docs/articles/nunit/writing-tests/attributes/nonparallelizable.md +++ b/docs/articles/nunit/writing-tests/attributes/nonparallelizable.md @@ -1,14 +1,26 @@ +--- +uid: attribute-nonparallelizable +--- + # NonParallelizable -This attribute is used to indicate that the test on which it appears may not be run in parallel with any other tests. -The attribute takes no arguments and may be used at the assembly, class or method level. +`NonParallelizableAttribute` marks an assembly, fixture, or method so it is not run in parallel with anything else (`ParallelScope.None`). It inherits from `ParallelizableAttribute` and takes no constructor arguments. + +## Usage + +```csharp +[NonParallelizable] +``` + +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ✅ | ✅ | ✅ | -When used at the assembly level, its only effect is that execution begins on the non-parallel queue. Test suites, -fixtures and test cases will continue to run on the same thread unless a fixture or method is marked with the -[Parallelizable Attribute](parallelizable.md). +When used at assembly level, execution starts on the non-parallel queue; child suites or methods can still opt into parallelism with [Parallelizable](xref:attribute-parallelizable). -When used on a test fixture or method, that test will be queued on the non-parallel queue and will not run while other -tests marked as Parallelizable are being run. +When used on a fixture or method, that test queues on the non-parallel queue and does not overlap with concurrent parallel-eligible tests. ## Platform Support @@ -18,5 +30,5 @@ does not support parallelization. ## See Also -* [Parallelizable Attribute](parallelizable.md) -* [LevelOfParallelism Attribute](levelofparallelism.md) +* [Parallelizable Attribute](xref:attribute-parallelizable) +* [LevelOfParallelism Attribute](xref:attribute-levelofparallelism) diff --git a/docs/articles/nunit/writing-tests/attributes/nontestassembly.md b/docs/articles/nunit/writing-tests/attributes/nontestassembly.md index 7dfbe55d4..19003ad9d 100644 --- a/docs/articles/nunit/writing-tests/attributes/nontestassembly.md +++ b/docs/articles/nunit/writing-tests/attributes/nontestassembly.md @@ -1,23 +1,44 @@ --- -uid: nontestassembly +uid: attribute-nontestassembly --- # NonTestAssembly -This is an _assembly-level_ attribute, which may be used to specify that even though -the assembly refers to NUnit it does not contain any tests. This attribute can be -used in connection with the command line option `--skipnontestassemblies` of the -console to skip assemblies without failing. +`NonTestAssemblyAttribute` is used to mark an assembly that references NUnit but does not contain any tests. This is useful for third-party frameworks, extensions, or other software that depend on NUnit but should not be loaded as test assemblies. + +## Usage + +This is a parameterless attribute that can only be applied at the assembly level. + +```csharp +[assembly: NonTestAssembly] +``` + +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ❌ | ❌ | ✅ | + +Typically placed in `AssemblyInfo.cs` or a global usings file. ## Example -The following code, which might be placed in AssemblyInfo.cs, specifies that the -assembly does not contain any tests. +The following code, placed in `AssemblyInfo.cs`, marks the assembly as not containing tests: ```csharp +using NUnit.Framework; + [assembly: NonTestAssembly] ``` +## Notes + +1. Use this attribute when your assembly references `NUnit.Framework` but is not intended to be run as a test assembly (e.g., test utilities, custom assertions, or framework extensions). +2. When used with the console runner's `--skipnontestassemblies` option, assemblies marked with this attribute are skipped without generating an error. +3. Recognition of this attribute depends on the individual test runner. Not all runners may honor it. +4. This attribute is marked `[EditorBrowsable(EditorBrowsableState.Never)]` to reduce IntelliSense noise in typical test projects. + ## See Also * `--skipnontestassemblies` in [Console Command Line](xref:consolecommandline) diff --git a/docs/articles/nunit/writing-tests/attributes/notests.md b/docs/articles/nunit/writing-tests/attributes/notests.md index 6ac001164..68daa653b 100644 --- a/docs/articles/nunit/writing-tests/attributes/notests.md +++ b/docs/articles/nunit/writing-tests/attributes/notests.md @@ -1,5 +1,5 @@ --- -uid: notestsattribute +uid: attribute-notests --- # NoTests @@ -8,21 +8,40 @@ The `NoTestsAttribute` specifies the default status for a parameterized test met executable child tests. This is useful when test cases are generated dynamically and may sometimes produce an empty set. -By default, NUnit treats a `Theory` with no test cases as a failure. For other parameterized tests, the behavior may -vary. The `NoTestsAttribute` allows you to explicitly control what status should be reported when no test cases are -available. +By default, NUnit treats a `Theory` with no test cases as a failure. For other parameterized tests, behavior may +vary. `NoTestsAttribute` chooses the `TestStatus` reported when no executable child tests are produced. > [!NOTE] -> This attribute was introduced in NUnit 4.6. +> Introduced in **NUnit 4.6**. -## Usage +## Constructor -The attribute accepts a `TestStatus` value that determines how the test should be reported when no child tests exist: +```csharp +NoTestsAttribute(TestStatus defaultStatus) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `defaultStatus` | `TestStatus` | Result when no child tests exist (`Skipped`, `Inconclusive`, `Passed`, or `Failed`). | + +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ✅ | ✅ | ✅ | + +Most specific scope (method) wins over fixture and assembly. + +## TestStatus Values + +Typical uses: -* `TestStatus.Skipped` - The test is marked as skipped -* `TestStatus.Inconclusive` - The test is marked as inconclusive -* `TestStatus.Passed` - The test is marked as passed (use with caution) -* `TestStatus.Failed` - The test is marked as failed (default for Theory) +| Value | Meaning | +|-------|---------| +| `TestStatus.Skipped` | Marked skipped when no cases | +| `TestStatus.Inconclusive` | Indeterminate empty data | +| `TestStatus.Passed` | Passed with no cases (use carefully) | +| `TestStatus.Failed` | Default for `Theory` with no cases | ## Test Fixture Syntax @@ -46,63 +65,32 @@ Use `TestStatus.Inconclusive` when empty test cases indicate an indeterminate st ### Dynamic Test Data -When test cases come from external sources (databases, APIs, configuration files) that might be empty: +Typical when test cases come from a source that can legitimately be empty (a database, API, config file, or similar). -```csharp -[TestFixture] -[NoTests(TestStatus.Skipped)] -public class DataDrivenTests -{ - [TestCaseSource(typeof(ExternalDataSource))] - public void ProcessData(DataRecord record) - { - // Test implementation - } -} -``` +[!code-csharp[NoTestsDynamicData](~/snippets/Snippets.NUnit/Attributes/NoTestsAttributeExamples.cs#NoTestsDynamicData)] -### Conditional Test Execution +### Conditional Execution -When test cases are only available under certain conditions: +Typical when cases are only produced for some platforms, environments, or other prerequisites. -```csharp -[NoTests(TestStatus.Inconclusive)] -[TestCaseSource(nameof(GetPlatformSpecificCases))] -public void PlatformSpecificTest(string testCase) -{ - // Test only runs when platform-specific cases are available -} -``` +[!code-csharp[NoTestsConditionalExecution](~/snippets/Snippets.NUnit/Attributes/NoTestsAttributeExamples.cs#NoTestsConditionalExecution)] -### Feature Flag Testing +### Feature Flags -When tests depend on feature flags that may not be enabled: - -```csharp -[TestFixture] -[NoTests(TestStatus.Skipped)] -public class FeatureFlagTests -{ - [TestCaseSource(nameof(GetEnabledFeatures))] - public void TestFeature(string featureName) - { - // Tests features that are currently enabled - } -} -``` +Typical when data-driven cases depend on feature flags or rollout state and may sometimes yield none. -## Inheritance +[!code-csharp[NoTestsFeatureFlag](~/snippets/Snippets.NUnit/Attributes/NoTestsAttributeExamples.cs#NoTestsFeatureFlag)] -The `NoTestsAttribute` can be applied at the assembly, class, or method level: +## Scope Precedence -* **Assembly level**: Affects all parameterized tests in the assembly -* **Class level**: Affects all parameterized tests in the fixture -* **Method level**: Affects only the specific test method +* **Assembly** — parameterized tests across the assembly +* **Fixture (class)** — parameterized tests in that fixture +* **Method** — that method only -When multiple levels specify the attribute, the most specific level (method) takes precedence. +The most specific level wins when multiple attributes apply. ## See Also -* [TestCaseSource Attribute](testcasesource.md) -* [TestCase Attribute](testcase.md) -* [Theory Attribute](theory.md) +* [TestCaseSource Attribute](xref:attribute-testcasesource) +* [TestCase Attribute](xref:attribute-testcase) +* [Theory Attribute](xref:attribute-theory) diff --git a/docs/articles/nunit/writing-tests/attributes/onetimesetup.md b/docs/articles/nunit/writing-tests/attributes/onetimesetup.md index f60d2b68e..779ae3ae9 100644 --- a/docs/articles/nunit/writing-tests/attributes/onetimesetup.md +++ b/docs/articles/nunit/writing-tests/attributes/onetimesetup.md @@ -1,46 +1,68 @@ --- -uid: onetimesetup-attribute +uid: attribute-onetimesetup --- # OneTimeSetUp -This attribute is to identify methods that are called once prior to executing any of the tests in a fixture. It may -appear on methods of a TestFixture or a SetUpFixture. +`OneTimeSetUpAttribute` marks a method that runs **once** before any **child tests** in its suite execute. Put it on a +method inside a [`TestFixture`](xref:attribute-testfixture) or a [`SetUpFixture`](xref:attribute-setupfixture). -OneTimeSetUp methods may be either static or instance methods and you may define more than one of them in a fixture. -Normally, multiple OneTimeSetUp methods are only defined at different levels of an inheritance hierarchy, as explained -below. +Normally you define multiple `OneTimeSetUp` methods across an **inheritance chain** (base then derived). Defining several +on the **same class** is allowed, but **order is undefined**—avoid unless you truly do not rely on ordering. -If a OneTimeSetUp method fails or throws an exception, none of the tests in the fixture are executed and a failure or -error is reported. +## Static and instance methods -## Example +A `OneTimeSetUp` method may be **static** or an **instance** method on the fixture type. + +With the default fixture life cycle ([`LifeCycle.SingleInstance`](xref:attribute-fixturelifecycle)), an **instance** method runs on +the shared fixture instance created for that suite—so it can safely touch **instance fields** shared by every test. + +With [`FixtureLifeCycle(LifeCycle.InstancePerTestCase)`](xref:attribute-fixturelifecycle), `OneTimeSetUp` **must be static**. It runs +once for the fixture while each test gets its own instance; keeping it static avoids relying on fields that reset +between tests. + +Methods may be **async** (`Task` / `Task`): NUnit will wait for completion like other async test infrastructure. + +## Test fixture versus SetUp fixture + +* **`TestFixture`** — `OneTimeSetUp` runs **once before all tests declared in that fixture** (including parameterized + cases sourced from that class). Each concrete fixture class gets its own one-time setup for its subtree. +* **`SetUpFixture`** — `OneTimeSetUp` runs **once for the scope that setup fixture covers** (for example several fixtures + under the same namespace), as described in [SetUpFixture](xref:attribute-setupfixture). Use this pattern when costly initialization + should run **once** for that whole slice of the hierarchy instead of repeating it on every concrete fixture class. + +If `OneTimeSetUp` lives on an **abstract or concrete base test class**, NUnit invokes it **for every derived fixture +type** that inherits that hierarchy (along with setup on the descendants). When you truly need execution **exactly once +for many unrelated fixtures**, prefer **`SetUpFixture`** or **`static`** initialization instead of repeating base-class +`OneTimeSetUp` semantics. + +## Failures and exceptions + +If **`OneTimeSetUp` fails** — including an assertion failure (`Assert.*`) or **any thrown exception** — NUnit treats the +setup as unsuccessful. Tests that would run **under that suite** are **not executed** (they are skipped as descendants of +failed setup), and the run reports a **failure** or **error** for that setup/fixture subtree. NUnit still invokes +**`OneTimeTearDown`** for that scope afterward (unless execution is aborted), which allows shared resources created during +partial setup to be released; see [OneTimeTearDown](xref:attribute-onetimeteardown). + +## Usage + +This is a parameterless attribute that can only be applied to methods. ```csharp -namespace NUnit.Tests -{ - using System; - using NUnit.Framework; - - [TestFixture] - public class SuccessTests - { - [OneTimeSetUp] - public void Init() - { /* ... */ } - - [OneTimeTearDown] - public void Cleanup() - { /* ... */ } - - [Test] - public void Add() - { /* ... */ } - } -} +[OneTimeSetUp] ``` -### Inheritance +## Applies To + +| Lifecycle Methods | Test Methods | Test Fixtures (Classes) | Assembly | +|-------------------|--------------|--------------------------|----------| +| ✅ | ❌ | ❌ | ❌ | + +## Example + +[!code-csharp[OneTimeSetUpExample](~/snippets/Snippets.NUnit/Attributes/OneTimeSetUpAttributeExamples.cs#OneTimeSetUpExample)] + +## Inheritance The OneTimeSetUp attribute is inherited from any base class. Therefore, if a base class has defined a OneTimeSetUp method, that method will be called before any methods in the derived class. @@ -56,28 +78,15 @@ OneTimeSetUp methods before those in the derived classes. ## Notes -* Although it is possible to define multiple [`OneTimeSetUp`](xref:onetimesetup-attribute) methods in the same class, - you should rarely do so. Unlike methods defined in separate classes in the inheritance hierarchy, the order in which - they are executed is not guaranteed. - -* [`OneTimeSetUp`](xref:onetimesetup-attribute) methods may be async if running under .NET 4.0 or higher. - -* [`OneTimeSetUp`](xref:onetimesetup-attribute) methods run in the context of the - [`TestFixture`](xref:testfixtureattribute) or [`SetUpFixture`](xref:setupfixture-attribute), which is separate from - the context of any individual test cases. It's important to keep this in mind when using - [`TestContext`](xref:testcontext) methods and properties within the method. - -* When using [`FixtureLifeCycle`](xref:fixturelifecycleattribute) with `LifeCycle.InstancePerTestCase`, the - [`OneTimeSetUp`](xref:onetimesetup-attribute) method must be static and is only called once. This is required so that - the setup method does not access instance fields or properties that are reset for every test. - -* When set on a base class the method is invoked for each fixture that inherits from this base class and its invoked for - the base class too if its not abstract. Use [`SetUpFixture`](xref:setupfixture-attribute) if this only needs to be run - once or put the code in a static constructor. +1. **`TestContext`** — `OneTimeSetUp` executes in **fixture / setup-fixture** context, **not** the per-test-case context. + Be careful when calling [`TestContext`](xref:testcontext) APIs that assume an active test method. +2. Multiple `OneTimeSetUp` methods in the **same** class run in arbitrary order unless you constrain them logically. +3. Base-class `OneTimeSetUp` methods run **before** derived-class methods (see **Inheritance** above). ## See Also -* [SetUp Attribute](setup.md) -* [TearDown Attribute](teardown.md) -* [OneTimeTearDown Attribute](onetimeteardown.md) -* [FixtureLifeCycle Attribute](fixturelifecycle.md) +* [SetUp Attribute](xref:attribute-setup) +* [TearDown Attribute](xref:attribute-teardown) +* [OneTimeTearDown Attribute](xref:attribute-onetimeteardown) +* [SetUpFixture Attribute](xref:attribute-setupfixture) +* [FixtureLifeCycle Attribute](xref:attribute-fixturelifecycle) diff --git a/docs/articles/nunit/writing-tests/attributes/onetimeteardown.md b/docs/articles/nunit/writing-tests/attributes/onetimeteardown.md index d221f7f5f..ba8b87a7f 100644 --- a/docs/articles/nunit/writing-tests/attributes/onetimeteardown.md +++ b/docs/articles/nunit/writing-tests/attributes/onetimeteardown.md @@ -1,42 +1,76 @@ --- -uid: onetimeteardown-attribute +uid: attribute-onetimeteardown --- # OneTimeTearDown -This attribute is to identify methods that are called once after executing all the tests in a fixture. It may appear on -methods of a TestFixture or a SetUpFixture. +`OneTimeTearDownAttribute` marks a method that runs **once** after **every child test finished** under a suite—for that +fixture or setup-fixture scope. Pair it with [`OneTimeSetUp`](xref:attribute-onetimesetup). -OneTimeTearDown methods may be either static or instance methods and you may define more than one of them in a fixture. -Normally, multiple OneTimeTearDown methods are only defined at different levels of an inheritance hierarchy, as -explained below. +Put it on a method inside a [`TestFixture`](xref:attribute-testfixture) or a [`SetUpFixture`](xref:attribute-setupfixture). -## Example +Normally you declare multiple `OneTimeTearDown` methods spread across an **inheritance chain** (derived first at runtime, +then base—see **Inheritance** below). Putting several methods on the **same class** is allowed, but execution **order among +them is undefined** unless you constrain them logically. + +## Static and instance methods + +`OneTimeTearDown` may be **static** or an **instance** method. + +With [`LifeCycle.SingleInstance`](xref:attribute-fixturelifecycle), an **instance** method runs once on the same shared fixture instance +that held `OneTimeSetUp`/`SetUp`; use it for instance-field cleanup tied to shared setup. + +With [`FixtureLifeCycle(LifeCycle.InstancePerTestCase)`](xref:attribute-fixturelifecycle), `OneTimeTearDown` **must be static**. It runs +once after all tests despite each case having its **own** instance; instance teardown belongs in [`TearDown`](xref:attribute-teardown) +per test instead. + +Methods may be **async** (`Task` / `Task`); NUnit will wait for completion. + +## Test fixture versus SetUp fixture + +* **`TestFixture`** — teardown runs **after all tests declared in that fixture** (every parameterized case rooted there) +finish, failed or passed unless something aborts scheduling earlier. +* **`SetUpFixture`** — teardown runs once after everything under that [**SetUpFixture**](xref:attribute-setupfixture) slice finishes, +matching the broader “run once init / run once cleanup” workflow. + +Teardown semantics for **abstract or concrete bases** mirror setup: inheritance causes code to participate per derived +fixture type unless you refactor to **`SetUpFixture`** or **`static`** cleanup patterns when you truly need cross-suite +lifetime control. + +## When teardown runs relative to failures + +* **After [`OneTimeSetUp`](xref:attribute-onetimesetup) fails** — once children are skipped, NUnit typically still invokes +this fixture’s teardown chain so disposal paths can execute. See **[OneTimeSetUp — Failures and exceptions](xref:attribute-onetimesetup#failures-and-exceptions)**. + +* **`OneTimeTearDown` failures** — assertion failures or exceptions during teardown are recorded on the **fixture / suite** + result as teardown failures. Individual child test outcomes are usually left as they were, but runners still surface the + teardown problem. + +* **Cancellation / abort** — if execution ends in an **abort** state, teardown may not run (for example parallel stop). +Normal **stop-on-error** still lets scheduled teardown phases run unless the dispatcher aborts the run. + +NUnit schedules fixture teardown **after every direct child of that suite finishes** (runs, failures, or skips scheduled +from parent setup). Do not treat teardown as a synchronous callback you can trigger from inside an individual `[Test]` +method body. + +## Usage + +This is a parameterless attribute that can only be applied to methods. ```csharp -namespace NUnit.Tests -{ - using System; - using NUnit.Framework; - - [TestFixture] - public class SuccessTests - { - [OneTimeSetUp] - public void Init() - { /* ... */ } - - [OneTimeTearDown] - public void Cleanup() - { /* ... */ } - - [Test] - public void Add() - { /* ... */ } - } -} +[OneTimeTearDown] ``` +## Applies To + +| Lifecycle Methods | Test Methods | Test Fixtures (Classes) | Assembly | +|-------------------|--------------|--------------------------|----------| +| ✅ | ❌ | ❌ | ❌ | + +## Example + +[!code-csharp[OneTimeTearDownExample](~/snippets/Snippets.NUnit/Attributes/OneTimeTearDownAttributeExamples.cs#OneTimeTearDownExample)] + ## Inheritance The OneTimeTearDown attribute is inherited from any base class. Therefore, if a base class has defined a OneTimeTearDown @@ -53,25 +87,16 @@ OneTimeTearDown methods after those in the derived classes. ## Notes -* Although it is possible to define multiple `OneTimeTearDown` methods in the same class, you should rarely do so. - Unlike methods defined in separate classes in the inheritance hierarchy, the order in which they are executed is not - guaranteed. - -* `OneTimeTearDown` methods may be async if running under .NET 4.0 or higher. - -* `OneTimeTearDown` methods run in the context of the [`TestFixture`](xref:testfixtureattribute) or - [`SetUpFixture`](xref:setupfixture-attribute), which is separate from the context of any individual test cases. It's - important to keep this in mind when using [`TestContext`](xref:testcontext) methods and properties within the method. - -* When using [`FixtureLifeCycle`](xref:fixturelifecycleattribute) with `LifeCycle.InstancePerTestCase`, the - `OneTimeTearDown` method must be static and is only called once. This is required so that the teardown method does not - access instance fields or properties that are reset for every test. +1. **`TestContext`** — like `OneTimeSetUp`, `OneTimeTearDown` runs in **fixture / setup-fixture** context, **not** + per-test context. Exercise caution using [`TestContext`](xref:testcontext) APIs meant for `[Test]` methods. +2. Multiple `OneTimeTearDown` methods on the **same** declaration run without a guaranteed mutual order unless you arrange + them logically. +3. Across inheritance, **derived** `OneTimeTearDown` methods run **before** base-class teardowns when both apply (see **Inheritance**). ## See Also -* [SetUp Attribute](setup.md) -* [TearDown Attribute](teardown.md) -* [OneTimeSetUp Attribute](xref:onetimesetup-attribute) -* [TestFixture Attribute](xref:testfixtureattribute) -* [SetUpFixture Attribute](xref:setupfixture-attribute) -* [FixtureLifeCycle Attribute](xref:fixturelifecycleattribute) +* [SetUp Attribute](xref:attribute-setup) +* [TearDown Attribute](xref:attribute-teardown) +* [OneTimeSetUp Attribute](xref:attribute-onetimesetup) +* [SetUpFixture Attribute](xref:attribute-setupfixture) +* [FixtureLifeCycle Attribute](xref:attribute-fixturelifecycle) diff --git a/docs/articles/nunit/writing-tests/attributes/order.md b/docs/articles/nunit/writing-tests/attributes/order.md index 259d8c052..430843ce5 100644 --- a/docs/articles/nunit/writing-tests/attributes/order.md +++ b/docs/articles/nunit/writing-tests/attributes/order.md @@ -1,39 +1,54 @@ +--- +uid: attribute-order +--- + # Order -The **OrderAttribute** may be placed on a test method or fixture to specify the order in which tests are run within the -fixture or other suite in which they are contained. Ordering is given by the required `order` argument to the attribute, -an `int`. +`OrderAttribute` is used on test methods or fixtures to specify the order in which tests are run within their containing suite. Tests are started in ascending order of the `order` value. -## Example +## Constructor -The following tests will be run in the order: +```csharp +OrderAttribute(int order) +``` -* TestA -* TestB -* TestC +| Parameter | Type | Description | +|-----------|------|-------------| +| `order` | `int` | The order value. Tests are started in ascending order of this value. Lower values run first. | -```csharp -public class MyFixture -{ - [Test, Order(1)] - public void TestA() { /* ... */ } +## Applies To +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ✅ | ✅ | ❌ | - [Test, Order(2)] - public void TestB() { /* ... */ } +> [!NOTE] +> For fixtures, `Order` orders fixtures within their containing namespace. For test methods, it orders tests within their containing fixture. - [Test] - public void TestC() { /* ... */ } -} -``` +## Examples + +### Basic Ordering + +[!code-csharp[OrderBasic](~/snippets/Snippets.NUnit/Attributes/OrderAttributeExamples.cs#OrderBasic)] + +### Ordering Fixtures + +[!code-csharp[OrderOnFixtures](~/snippets/Snippets.NUnit/Attributes/OrderAttributeExamples.cs#OrderOnFixtures)] + +### Using Gaps for Future Insertions + +[!code-csharp[OrderWithGaps](~/snippets/Snippets.NUnit/Attributes/OrderAttributeExamples.cs#OrderWithGaps)] ## Notes -1. As stated, ordering is local to the test that contains the ordered tests. For test cases (methods) ordering applies - within the containing fixture. For fixtures it applies within the containing namespace. There is no facility in NUnit - to order tests globally. -2. Tests with an `OrderAttribute` argument are started before any tests without the attribute. -3. Ordered tests are started in ascending order of the `order` argument. -4. Among tests with the same `order` value or without the attribute, execution order is indeterminate. -5. Tests do not wait for prior tests to finish. If multiple threads are in use, a test may be started while some earlier - tests are still being run. +1. Ordering is **local** to the containing suite. For test methods, ordering applies within the fixture. For fixtures, it applies within the namespace. There is no facility to order tests globally. +2. Tests with `[Order]` are started **before** any tests without the attribute. +3. Ordered tests are started in **ascending** order of the `order` value. +4. Among tests with the same `order` value, or among tests without the attribute, execution order is indeterminate. +5. Tests do **not** wait for prior tests to finish. When using parallel execution, a test may start while earlier tests are still running. +6. Negative order values are valid and will run before positive values. + +## See Also + +* [Parallelizable Attribute](xref:attribute-parallelizable) +* [NonParallelizable Attribute](xref:attribute-nonparallelizable) diff --git a/docs/articles/nunit/writing-tests/attributes/pairwise.md b/docs/articles/nunit/writing-tests/attributes/pairwise.md index 15ed9037d..e53350221 100644 --- a/docs/articles/nunit/writing-tests/attributes/pairwise.md +++ b/docs/articles/nunit/writing-tests/attributes/pairwise.md @@ -1,30 +1,31 @@ --- -uid: pairwiseattribute +uid: attribute-pairwise --- # Pairwise -The **PairwiseAttribute** is used on a test to specify that NUnit should -generate test cases in such a way that all possible pairs of -values are used. This is a well-known approach for combatting -the combinatorial explosion of test cases when more than -two features (parameters) are involved. +`PairwiseAttribute` tells NUnit to generate test cases so all possible pairs of parameter values are covered, while using fewer cases than full combinatorial generation. + +## Usage + +This is a parameterless attribute that can only be applied to test methods. + +```csharp +[Pairwise] +``` + +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ✅ | ❌ | ❌ | ## Example Using the Combinatorial attribute, the following test would be executed 12 (3x2x2) times. With **Pairwise** it is executed only enough times so that each possible pair is covered.. -```csharp -[Test, Pairwise] -public void MyTest( - [Values("a", "b", "c")] string a, - [Values("+", "-")] string b, - [Values("x", "y")] string c) -{ - Console.WriteLine("{0} {1} {2}", a, b, c); -} -``` +[!code-csharp[PairwiseBasic](~/snippets/Snippets.NUnit/Attributes/PairwiseAttributeExamples.cs#PairwiseBasic)] For this test, NUnit currently calls the method six times, producing the following output: @@ -41,14 +42,13 @@ Note that this is not the optimal output. The pairs (-, x) and (+, y) appear twice. NUnit uses a heuristic algorithm to reduce the number of test cases as much as it can. Improvements may be made in the future. -## Limitations +## Notes -When used on a generic method the programmer must ensure that all -possible combinations of arguments are valid. When multiple parameters -use the same generic type (e.g.: T) this may not be possible and the -attribute may generate invalid test cases. +1. Pairwise generation is heuristic and may not produce the theoretical minimum number of test cases. +2. When used on generic methods, ensure generated combinations are valid for all type constraints. +3. Use `Combinatorial` when you need full coverage of all combinations. ## See Also -* [Sequential Attribute](sequential.md) -* [Combinatorial Attribute](combinatorial.md) +* [Sequential Attribute](xref:attribute-sequential) +* [Combinatorial Attribute](xref:attribute-combinatorial) diff --git a/docs/articles/nunit/writing-tests/attributes/parallelizable.md b/docs/articles/nunit/writing-tests/attributes/parallelizable.md index 1a41de906..b35a28772 100644 --- a/docs/articles/nunit/writing-tests/attributes/parallelizable.md +++ b/docs/articles/nunit/writing-tests/attributes/parallelizable.md @@ -1,27 +1,46 @@ --- -uid: parallelizableattribute +uid: attribute-parallelizable --- # Parallelizable -Added in **NUnit 3.7** +Added in **NUnit 3.7**. -The `ParallelizableAttribute` is used to indicate that a test and/or its descendants may be run in parallel with other -tests. By default, no parallel execution takes place. +The `ParallelizableAttribute` marks an assembly, fixture, or method (and optionally its descendants) as eligible for parallel execution. By default, tests are not parallel. -When used without an argument, `Parallelizable` causes the test fixture or method on which it is placed to be queued for -execution in parallel with other parallelizable tests. It may be used at the assembly, class or method level. +When used without an argument, scope defaults to `ParallelScope.Self`. + +## Constructors + +```csharp +ParallelizableAttribute() +ParallelizableAttribute(ParallelScope scope) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `scope` | `ParallelScope` | Controls what may run in parallel for this node and descendants. Defaults to `Self`. | + +## Properties + +| Property | Type | Description | Default | +|----------|------|-------------|---------| +| `Scope` | `ParallelScope` | Same as constructor `scope`. | `ParallelScope.Self` | + +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ✅ | ✅ | ✅ | > [!WARNING] > When tests are run in parallel, you are responsible for the thread safety of your tests. Tests that run at > the same time and modify instance fields or properties without locks will cause unexpected behavior as they would in > any multi-threaded program. If you are using fields or properties between parallel tests consider using the -> [`FixtureLifeCycleAttribute`](xref:fixturelifecycleattribute) to construct a new instance of a test fixture (class) +> [`FixtureLifeCycleAttribute`](xref:attribute-fixturelifecycle) to construct a new instance of a test fixture (class) > for each test that is run. -The constructor takes an optional `ParallelScope` enumeration argument (see below), which indicates whether the -attribute applies to the item itself, to its descendants or both. It defaults to `ParallelScope.Self`. The Scope may -also be specified using the constructor argument `scope:`, for example; +Named argument form: ```csharp [Parallelizable(scope: ParallelScope.All)] @@ -29,15 +48,14 @@ also be specified using the constructor argument `scope:`, for example; ## ParallelScope Enumeration -This is a **[Flags]** enumeration used to specify which tests may run in parallel. It applies to the test upon which it -appears and any subordinate tests. The following values are available to users: +`ParallelScope` is a **[Flags]** enumeration. It applies to the attributed test and its subordinates. User-visible values: - Value | Meaning | Valid On --------|---------|--------- -`ParallelScope.Self` | the test itself may be run in parallel with other tests | Classes, Methods -`ParallelScope.Children` | child tests may be run in parallel with one another | Assembly, Classes -`ParallelScope.Fixtures` | fixtures may be run in parallel with one another | Assembly, Classes -`ParallelScope.All` | the test and its descendants may be run in parallel with others at the same level | Classes, Methods +| Value | Meaning | Valid On | +| --- | --- | --- | +| `ParallelScope.Self` | the test itself may be run in parallel with other tests | Classes, Methods | +| `ParallelScope.Children` | child tests may be run in parallel with one another | Assembly, Classes | +| `ParallelScope.Fixtures` | fixtures may be run in parallel with one another | Assembly, Classes | +| `ParallelScope.All` | the test and its descendants may be run in parallel with others at the same level | Classes, Methods | ## Notes @@ -52,6 +70,6 @@ appears and any subordinate tests. The following values are available to users: ## See Also -* [FixtureLifeCycle Attribute](xref:fixturelifecycleattribute) -* [NonParallelizable Attribute](nonparallelizable.md) -* [LevelOfParallelism Attribute](levelofparallelism.md) +* [FixtureLifeCycle Attribute](xref:attribute-fixturelifecycle) +* [NonParallelizable Attribute](xref:attribute-nonparallelizable) +* [LevelOfParallelism Attribute](xref:attribute-levelofparallelism) diff --git a/docs/articles/nunit/writing-tests/attributes/platform.md b/docs/articles/nunit/writing-tests/attributes/platform.md index a23168a66..98c401a24 100644 --- a/docs/articles/nunit/writing-tests/attributes/platform.md +++ b/docs/articles/nunit/writing-tests/attributes/platform.md @@ -1,50 +1,56 @@ +--- +uid: attribute-platform +--- + # Platform -The Platform attribute is used to specify platforms for which a test or fixture should be run. Platforms are specified -using case-insensitive string values and may be either included or excluded from the run by use of the Include or -Exclude properties respectively. Platforms to be included may alternatively be specified as an argument to the -PlatformAttribute constructor. In either case, multiple comma-separated values may be specified. +`PlatformAttribute` specifies platforms on which a test, fixture, or assembly should run. Platform names are +case-insensitive. You can require platforms in any of these ways: -If a test or fixture with the Platform attribute does not satisfy the specified platform requirements it is skipped. The -test does not affect the outcome of the run at all: it is not considered as ignored and is not even counted in the total -number of tests. _[Ed.: Check this.]_ In the gui, the tree node for the test remains gray and the status bar color is -not affected. +* Pass a comma-separated list to the constructor (treated as **included** platforms). +* Set the `Include` property to a comma-separated list. +* Set the `Exclude` property to a comma-separated list. -## Test Fixture Syntax +You can combine `Include` and `Exclude` where that makes sense for your scenario. -```csharp -namespace NUnit.Tests -{ - using System; - using NUnit.Framework; - - [TestFixture] - [Platform("NET-2.0")] - public class DotNetTwoTests - { - // ... - } -} -``` +If the current environment does **not** satisfy the attribute, NUnit marks the test as **skipped** (`RunState.Skipped`) +with a skip reason—it does **not** mark it as ignored, and it does not fail the run. Skipped tests are omitted from the +normal pass/fail counts in the same way as other skipped work. How your test runner displays skipped tests (for example +in a tree view or status bar) depends on that runner. -## Test Syntax +Invalid or unrecognized platform names can make a test **not runnable** instead of skipped; see your runner output for +the reason. + +## Constructors ```csharp -namespace NUnit.Tests -{ - using System; - using NUnit.Framework; - - [TestFixture] - public class SuccessTests - { - [Test] - [Platform(Exclude="Win98,WinME")] - public void SomeTest() - { /* ... */ } -} +PlatformAttribute() +PlatformAttribute(string platforms) +PlatformAttribute(string[] includes) ``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `platforms` | `string` | Comma-delimited platform list to include. | +| `includes` | `string[]` | Platform identifiers to include. | + +## Properties + +| Property | Type | Description | Default | +|----------|------|-------------|---------| +| `Include` | `string` | Comma-delimited list of included platforms. | `null` | +| `Exclude` | `string` | Comma-delimited list of excluded platforms. | `null` | + +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ✅ | ✅ | ✅ | + +## Examples + +[!code-csharp[PlatformAttributeExamples](~/snippets/Snippets.NUnit/Attributes/PlatformAttributeExamples.cs#PlatformAttributeExamples)] + ## Platform Specifiers The following values are recognized as platform specifiers. They may be expressed in upper, lower or mixed case. diff --git a/docs/articles/nunit/writing-tests/attributes/property.md b/docs/articles/nunit/writing-tests/attributes/property.md index 43c47623a..2a262f26a 100644 --- a/docs/articles/nunit/writing-tests/attributes/property.md +++ b/docs/articles/nunit/writing-tests/attributes/property.md @@ -1,77 +1,71 @@ --- -uid: propertyattribute +uid: attribute-property --- # Property -**PropertyAttribute** provides a generalized approach to setting named -properties on any test case or fixture, using a name/value pair. -In the example below, the fixture class MathTests is given a Location -value of 723 while the test case AdditionTest is given a Severity -of "Critical" +`PropertyAttribute` provides a generalized approach to setting named properties on any test case or fixture, using a name/value pair. Properties can be used for test filtering, reporting, and custom test organization. -## Example +## Constructors ```csharp -namespace NUnit.Tests -{ - using System; - using NUnit.Framework; - - [TestFixture, Property("Location", 723)] - public class MathTests - { - [Test, Property("Severity", "Critical")] - public void AdditionTest() - { /* ... */ } - } -} +PropertyAttribute(string propertyName, string propertyValue) +PropertyAttribute(string propertyName, int propertyValue) +PropertyAttribute(string propertyName, double propertyValue) ``` -## Usage Note +| Parameter | Type | Description | +|-----------|------|-------------| +| `propertyName` | `string` | The name of the property. | +| `propertyValue` | `string`, `int`, or `double` | The value of the property. | -The PropertyAttribute is not currently used for any purpose by NUnit itself, other -than to display them in the XML output file and in the Test Properties -dialog of the gui. You may also use properties with the `--where` option on the -command-line in order to select tests to run. See [Test Selection Language](xref:testselectionlanguage). Note -that his filtering will only work for properties where the values have type string. +## Properties -User tests may access properties through the [TestContext](xref:testcontext) or by reflection. +| Property | Type | Description | +|----------|------|-------------| +| `Properties` | `IPropertyBag` | Gets the property dictionary for this attribute. | -## Custom Property Attributes +## Applies To -Users can define custom attributes that derive from **PropertyAttribute** -and have them recognized by NUnit. PropertyAttribute provides a protected constructor -that takes the value of the property and sets the property name to the -name of the derived class with the 'Attribute' suffix removed. +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ✅ | ✅ | ✅ | -Here's an example that creates a Severity property. It works -just like any other property, but has a simpler syntax and is type-safe. -A custom test reporting system might make use of the property to provide special reports. +> [!NOTE] +> When applied to a fixture or assembly, the property is applied to all tests contained within that fixture or assembly. -```csharp -public enum SeverityLevel -{ - Critical, - Major, - Normal, - Minor -} - -[AttributeUsage(AttributeTargets.Method, AllowMultiple=false)] -public class SeverityAttribute : PropertyAttribute -{ - public SeverityAttribute(SeverityLevel level) - : base(level.ToString()) {} -} - -... - -[Test, Severity(SeverityLevel.Critical)] -public void MyTest() -{ /*...*/ } -``` +Multiple `PropertyAttribute` instances can be applied to the same element (`AllowMultiple = true`). + +## Examples + +### Basic Usage + +[!code-csharp[BasicProperty](~/snippets/Snippets.NUnit/Attributes/PropertyAttributeExamples.cs#BasicProperty)] + +### Different Property Value Types + +[!code-csharp[PropertyTypes](~/snippets/Snippets.NUnit/Attributes/PropertyAttributeExamples.cs#PropertyTypes)] + +### Accessing Properties in Tests + +[!code-csharp[AccessingProperties](~/snippets/Snippets.NUnit/Attributes/PropertyAttributeExamples.cs#AccessingProperties)] + +### Custom Property Attributes + +You can define custom attributes that derive from `PropertyAttribute` for type-safe, domain-specific properties: + +[!code-csharp[CustomPropertyAttribute](~/snippets/Snippets.NUnit/Attributes/PropertyAttributeExamples.cs#CustomPropertyAttribute)] + +## Notes + +1. `PropertyAttribute` is not used by NUnit itself for test execution. Properties are displayed in XML output and the Test Properties dialog. +2. You can use properties with the `--where` option on the command-line to select tests to run. See [Test Selection Language](xref:testselectionlanguage). Filtering only works for properties with `string` values. +3. Tests can access properties through [TestContext](xref:testcontext) using `TestContext.CurrentContext.Test.Properties`. +4. When creating custom property attributes, the property name is derived from the class name with the "Attribute" suffix removed (e.g., `SeverityAttribute` becomes property name `"Severity"`). + +## See Also -A PropertyAttribute may contain -multiple name/value pairs. This capability is not exposed publicly -but may be used by derived property classes. +* [TestContext](xref:testcontext) +* [Test Selection Language](xref:testselectionlanguage) +* [Category Attribute](xref:attribute-category) +* [Description Attribute](xref:attribute-description) diff --git a/docs/articles/nunit/writing-tests/attributes/random.md b/docs/articles/nunit/writing-tests/attributes/random.md index dce5cfb10..fa56d3645 100644 --- a/docs/articles/nunit/writing-tests/attributes/random.md +++ b/docs/articles/nunit/writing-tests/attributes/random.md @@ -1,68 +1,95 @@ --- -uid: randomattribute +uid: attribute-random --- # Random -The **RandomAttribute** is used to specify a set of random values to be provided for an individual numeric parameter, or -`Guid` of a parameterized test method. Since NUnit combines the data provided for each parameter into a set of test -cases, data must be provided for all parameters if it is provided for any of them. +`RandomAttribute` is used to specify a set of random values to be provided for an individual parameter of a parameterized test method. It supports numeric types, `Guid`, and enums. -By default, NUnit creates test cases from all possible combinations of the datapoints provided on parameters - the -combinatorial approach. This default may be modified by use of specific attributes on the test method itself. +## Constructors -RandomAttribute supports the following constructors: +### Count Only (Auto-detect Type) ```csharp -public Random(int count); -public Random(int min, int max, int count); -public Random(uint min, uint max, int count); -public Random(long min, long max, int count); -public Random(ulong min, ulong max, int count); -public Random(short min, short max, int count); -public Random(ushort min, ushort max, int count); -public Random(byte min, byte max, int count); -public Random(sbyte min, sbyte max, int count); -public Random(double min, double max, int count); -public Random(float min, float max, int count); +RandomAttribute(int count) ``` -In the first form, without minimum and maximum values, the attribute automatically generates values of the appropriate -numeric Type or `Guid` for the argument provided, using the `Randomizer` object associated with the current context. See -[Randomizer Methods](xref:randomizermethods) for details. +| Parameter | Type | Description | +|-----------|------|-------------| +| `count` | `int` | The number of random values to generate. The type is inferred from the parameter. | -In general, the forms that specify a minimum and maximum should be used on arguments of the same type. However, the -following exceptions are supported: +### With Range (Type-specific) -* You may use an int range on arguments of type short, ushort, byte, sbyte and decimal. +```csharp +RandomAttribute(int min, int max, int count) +RandomAttribute(double min, double max, int count) +// Also available for: uint, long, ulong, short, ushort, byte, sbyte, float +``` -* You may use a double range on arguments of type decimal. +| Parameter | Type | Description | +|-----------|------|-------------| +| `min` | varies | The minimum value (inclusive). | +| `max` | varies | The maximum value (exclusive). | +| `count` | `int` | The number of random values to generate. | -Note that there is no constructor taking decimal values for min and max. This is because .NET does not support use of -decimal in an attribute constructor. +## Properties -> [!NOTE] -> `Guid` support for `RandomAttribute` is available from version 4.0 onwards. +| Property | Type | Description | Default | +|----------|------|-------------|---------| +| `Distinct` | `bool` | When `true`, no value will be repeated among the generated values. | `false` | -## Example +## Applies To -The following test will be executed fifteen times, three times for each value of x, each combined with 5 random doubles -from -1.0 to +1.0. +| Method Parameters | Test Methods | Test Fixtures (Classes) | Assembly | +|-------------------|--------------|--------------------------|----------| +| ✅ | ❌ | ❌ | ❌ | -```csharp -[Test] -public void MyTest( - [Values(1, 2, 3)] int x, - [Random(-1.0, 1.0, 5)] double d) -{ - ... -} -``` +## Supported Types + +| Type | Count-only | With Range | +|------|------------|------------| +| `int`, `uint`, `long`, `ulong` | Yes | Yes | +| `short`, `ushort`, `byte`, `sbyte` | Yes | Yes | +| `double`, `float` | Yes | Yes | +| `decimal` | Yes | No (use `int` or `double` range) | +| `Guid` | Yes | No | +| `enum` | Yes | No | + +## Examples + +### Basic Usage + +[!code-csharp[RandomBasic](~/snippets/Snippets.NUnit/Attributes/RandomAttributeExamples.cs#RandomBasic)] + +### With Range + +[!code-csharp[RandomWithRange](~/snippets/Snippets.NUnit/Attributes/RandomAttributeExamples.cs#RandomWithRange)] + +### Distinct Values + +[!code-csharp[RandomDistinct](~/snippets/Snippets.NUnit/Attributes/RandomAttributeExamples.cs#RandomDistinct)] + +### Random GUIDs + +[!code-csharp[RandomGuid](~/snippets/Snippets.NUnit/Attributes/RandomAttributeExamples.cs#RandomGuid)] + +### Combined with Other Attributes + +[!code-csharp[RandomCombined](~/snippets/Snippets.NUnit/Attributes/RandomAttributeExamples.cs#RandomCombined)] + +## Notes + +1. By default, NUnit creates test cases from all combinations of parameter values (combinatorial). Use `[Sequential]` to pair values in order instead. +2. There is no constructor for `decimal` min/max because .NET does not support decimal in attribute constructors. Use an `int` or `double` range instead - values will be converted. +3. `Guid` does not support min/max ranges - only the count-only constructor works. +4. When using `Distinct = true`, ensure the range is large enough to provide the requested number of distinct values. +5. `Guid` support was added in **NUnit 4.0**. ## See Also -* [Values Attribute](values.md) -* [Range Attribute](range.md) -* [Sequential Attribute](sequential.md) -* [Combinatorial Attribute](combinatorial.md) -* [Pairwise Attribute](pairwise.md) +* [Values Attribute](xref:attribute-values) +* [Range Attribute](xref:attribute-range) +* [Sequential Attribute](xref:attribute-sequential) +* [Combinatorial Attribute](xref:attribute-combinatorial) +* [Pairwise Attribute](xref:attribute-pairwise) +* [Randomizer Methods](xref:randomizermethods) diff --git a/docs/articles/nunit/writing-tests/attributes/range.md b/docs/articles/nunit/writing-tests/attributes/range.md index b831a6360..f827c3888 100644 --- a/docs/articles/nunit/writing-tests/attributes/range.md +++ b/docs/articles/nunit/writing-tests/attributes/range.md @@ -1,35 +1,53 @@ --- -uid: rangeattribute +uid: attribute-range --- # Range -The **RangeAttribute** is used to specify a range of values to be provided -for an individual parameter of a parameterized test method. Since -NUnit combines the data provided for each parameter into a set of -test cases, data must be provided for all parameters if it is -provided for any of them. +`RangeAttribute` supplies a sequence of values for **one parameter** on a parameterized test method. -By default, NUnit creates test cases from all possible combinations -of the datapoints provided on parameters - the combinatorial approach. -This default may be modified by use of specific attributes on the -test method itself. +Once you supply explicit data sources (such as `Range`, [`Values`](xref:attribute-values), [`Random`](xref:attribute-random), etc.) for **any** +parameter on that method, you must specify **sources for every parameter**—see [Parameterized Tests](xref:parameterizedtests). -RangeAttribute supports the following constructors: +By default, NUnit merges parameters **combinatorially** (every combination). Use [`Sequential`](xref:attribute-sequential), +[`Pairwise`](xref:attribute-pairwise), or another combining strategy on the **method** to change pairing behavior. + +## Constructors ```csharp -public RangeAttribute(int from, int to); -public RangeAttribute(int from, int to, int step); -public RangeAttribute(long from, long to, long step); -public RangeAttribute(float from, float to, float step); -public RangeAttribute(double from, double to, double step); +RangeAttribute(int from, int to) +RangeAttribute(uint from, uint to) +RangeAttribute(long from, long to) +RangeAttribute(ulong from, ulong to) +RangeAttribute(int from, int to, int step) +RangeAttribute(uint from, uint to, uint step) +RangeAttribute(long from, long to, long step) +RangeAttribute(ulong from, ulong to, ulong step) +RangeAttribute(float from, float to, float step) +RangeAttribute(double from, double to, double step) ``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `from` | numeric | First yielded value | +| `to` | numeric | End of the progression; yielded while stepping **toward** this bound without crossing it | +| `step` | numeric | Increment between values (**required** for `float`/`double`; when omitted on signed integral types `from`/`to`, NUnit uses **1 or −1**, matching whether `from` < `to` or `from` > `to`) | + +Unsigned `uint` / `ulong` ranges require **`to` ≥ `from`** and a **positive** `step` (no automatic downward ranges). +Floating-point generators stop at the **last** value reached before arithmetic would overshoot `to`; if `from`/`to`/step +produce no exact landing on `to`, **`to` itself might not appear**. + +## Applies To + +| Method Parameters | Test Methods | Test Fixtures (Classes) | Assembly | +|-------------------|--------------|--------------------------|----------| +| ✅ | ❌ | ❌ | ❌ | + ## Example The following test will be executed nine times. -[!code-csharp[RangeAttributeExample](~/snippets/Snippets.NUnit/AttributeExamples.cs#RangeAttributeExample)] +[!code-csharp[RangeAttributeExample](~/snippets/Snippets.NUnit/Attributes/RangeAttributeExamples.cs#RangeAttributeExample)] The MyTest method is called nine times, as follows: @@ -45,10 +63,19 @@ MyTest(3, 0.4) MyTest(3, 0.6) ``` +## Notes + +1. Annotate **`[Range]` directly on the method parameter**. `AllowMultiple` is **true**, so repeat the attribute if you want + several disjoint spans merged for the same argument. +2. **Signed** integral two-argument constructors pick default step **`+1` or −1**, so **`[Range(5, 1)]`** yields a descending sequence. + **Unsigned** constructors throw if `from` > `to`. +3. Resulting Cartesian products still depend on whichever combining attributes appear on the test method (**Combinatorial** by default). +4. `float`/`double` overloads always require an explicit **`step`**; there is **no two-argument** floating-point shortcut. + ## See Also -* [Values Attribute](values.md) -* [Random Attribute](random.md) -* [Sequential Attribute](sequential.md) -* [Combinatorial Attribute](combinatorial.md) -* [Pairwise Attribute](pairwise.md) +* [Values Attribute](xref:attribute-values) +* [Random Attribute](xref:attribute-random) +* [Sequential Attribute](xref:attribute-sequential) +* [Combinatorial Attribute](xref:attribute-combinatorial) +* [Pairwise Attribute](xref:attribute-pairwise) diff --git a/docs/articles/nunit/writing-tests/attributes/repeat.md b/docs/articles/nunit/writing-tests/attributes/repeat.md index 536c0c560..4a7343b95 100644 --- a/docs/articles/nunit/writing-tests/attributes/repeat.md +++ b/docs/articles/nunit/writing-tests/attributes/repeat.md @@ -1,25 +1,55 @@ +--- +uid: attribute-repeat +--- + # Repeat -**RepeatAttribute** is used on a test method to specify that it should be -executed multiple times. +`RepeatAttribute` is used on a test method to specify that it should be executed multiple times. By default, the test repeats until a failure occurs or all repetitions complete successfully. + +## Constructors + +```csharp +RepeatAttribute(int count) +RepeatAttribute(int count, bool stopOnFailure) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `count` | `int` | The number of times to run the test. | +| `stopOnFailure` | `bool` | Whether to stop repeating when a test fails. Default is `true`. | + +## Properties + +| Property | Type | Description | Default | +|----------|------|-------------|---------| +| `StopOnFailure` | `bool` | Whether to stop repeating when a test fails. When `false`, all repetitions run regardless of failures. | `true` | -By default, the test is repeated until a failure occurs. If no failures occur, it runs for the specified number of repetitions. +> [!NOTE] +> The `StopOnFailure` property was added in **NUnit 4.3.0**. + +## Applies To -You can change this behavior in case of a failure, so that it continues to run after the failure by setting the property `StopOnFailure` to `false`. (From version 4.3.0) +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ✅ | ❌ | ❌ | ## Examples -### The default behavior +### Default Behavior (Stop on Failure) [!code-csharp[RepeatDefaultAttributeExample](~/snippets/Snippets.NUnit/Attributes/RepeatAttributeExample.cs#RepeatDefaultAttributeExample)] -### Run all regardless of failures +### Continue on Failure [!code-csharp[RepeatWithFaultAttributeExample](~/snippets/Snippets.NUnit/Attributes/RepeatAttributeExample.cs#RepeatWithFaultAttributeExample)] -> [!WARNING] -> There is currently (as of 4.4.0) a [bug](https://github.com/nunit/nunit/issues/5031) which causes only the last successful console statement to be output. Also, in case of failures, only the latest failure is shown. -> [!NOTE] -> If RepeatAttribute is used on a parameterized method, -> each individual test case created for that method is repeated. -> It is not currently possible to use RepeatAttribute on a TestFixture or any higher level suite. Only test cases may be repeated. +## Notes + +1. When `StopOnFailure` is `true` (default), the test stops at the first failure. +2. When `StopOnFailure` is `false`, all repetitions run and all failures are collected. +3. If `RepeatAttribute` is used on a parameterized method, each individual test case is repeated. +4. It is not currently possible to use `RepeatAttribute` on a `TestFixture` or any higher level suite. Only test methods may be repeated. + +## See Also + +* [Retry Attribute](xref:attribute-retry) diff --git a/docs/articles/nunit/writing-tests/attributes/requiresthread.md b/docs/articles/nunit/writing-tests/attributes/requiresthread.md index 73f524002..09c7a8003 100644 --- a/docs/articles/nunit/writing-tests/attributes/requiresthread.md +++ b/docs/articles/nunit/writing-tests/attributes/requiresthread.md @@ -1,46 +1,53 @@ +--- +uid: attribute-requiresthread +--- + # RequiresThread -The **RequiresThreadAttribute** is used to indicate that a test method, class or assembly should be run on a separate -thread. Optionally, the desired apartment for the thread may be specified in the constructor. +`RequiresThreadAttribute` is used to indicate that a test method, class, or assembly should always run on a separate thread. Optionally, the desired apartment state for the thread may be specified. + +## Constructors + +```csharp +RequiresThreadAttribute() +RequiresThreadAttribute(ApartmentState apartment) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `apartment` | `ApartmentState` | The apartment state for the thread. Must be `STA` or `MTA` (not `Unknown`). | + +## Applies To -> [!NOTE] -> This attribute, used with or without an ApartmentState argument will **always** result in creation of a new -> thread. To create a thread **only** if the current ApartmentState is not appropriate, use the **ApartmentAttribute**. +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ✅ | ✅ | ✅ | ## Examples +### Fixture Level + +[!code-csharp[RequiresThreadFixture](~/snippets/Snippets.NUnit/Attributes/RequiresThreadAttributeExamples.cs#RequiresThreadFixture)] + +### Method Level with Apartment State + +[!code-csharp[RequiresThreadMethod](~/snippets/Snippets.NUnit/Attributes/RequiresThreadAttributeExamples.cs#RequiresThreadMethod)] + +### Assembly Level + ```csharp -// A thread will be created and used to run -// all the tests in the assembly -[assembly:RequiresThread] - -/* ... */ - -// TestFixture requiring a separate thread -[TestFixture, RequiresThread] -public class FixtureOnThread -{ - // A separate thread will be created and all - // tests in the fixture will run on it. -} - -[TestFixture] -public class AnotherFixture -{ - [Test, RequiresThread] - public void TestRequiringThread() - { - // A separate thread will be created for this test - } - - [Test, RequiresThread(ApartmentState.STA)] - public void TestRequiringSTAThread() - { - // A separate STA thread will be created for this test. - } -} +// All tests in this assembly will run on separate threads +[assembly: RequiresThread] ``` +## Notes + +1. This attribute **always** creates a new thread, regardless of the current thread's apartment state. +2. To create a thread **only** when the current apartment state is not appropriate, use the `[Apartment]` attribute instead. +3. When used without an `ApartmentState` argument, the thread uses the default apartment state (MTA). +4. This attribute is useful for tests that modify thread-local state or require isolation from other tests. + ## See Also -* [Apartment Attribute](apartment.md) +* [Apartment Attribute](xref:attribute-apartment) +* [SingleThreaded Attribute](xref:attribute-singlethreaded) diff --git a/docs/articles/nunit/writing-tests/attributes/retry.md b/docs/articles/nunit/writing-tests/attributes/retry.md index 33426d0fd..c2ca4a749 100644 --- a/docs/articles/nunit/writing-tests/attributes/retry.md +++ b/docs/articles/nunit/writing-tests/attributes/retry.md @@ -1,18 +1,51 @@ +--- +uid: attribute-retry +--- + # Retry -RetryAttribute is used on a test method to specify that it should be rerun if it fails, up to a maximum number of times. +`RetryAttribute` is used on a test method to specify that it should be rerun on failure up to a maximum number of times. -[!code-csharp[Retry](~/snippets/Snippets.NUnit/Attributes/RetryAttributeExamples.cs#Retry)] +## Constructor + +```csharp +RetryAttribute(int tryCount) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `tryCount` | `int` | The maximum number of times the test should be run if it fails. This is the total number of attempts, **not** the number of retries after an initial failure. Therefore, `[Retry(1)]` does nothing and should not be used. | -Notes: +## Properties -1. The argument you specify is the total number of attempts and __not__ the number of retries after an initial failure. - So `[Retry(1)]` does nothing and should not be used. -2. It is not currently possible to use `RetryAttribute` on a `TestFixture` or any other type of test suite. - Only single tests may be repeated. -3. If a test has an unexpected exception, an error result is returned and it is not retried. +| Property | Type | Description | Default | +|----------|------|-------------|---------| +| `RetryExceptions` | `Type[]` | An array of exception types that trigger a retry when thrown. These are in addition to the normal behavior of retrying only on an assertion failure. | `[]` (empty array) | - From NUnit 4.5.0 you can enable retry on an expected exception such as `TimeoutException` - by setting the `RetryExceptions` property. The value of this property is an array of anticipated exceptions that should be retried. +> [!NOTE] +> The `RetryExceptions` property was added in **NUnit 4.5.0**. + +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ✅ | ❌ | ❌ | + +## Example + +[!code-csharp[Retry](~/snippets/Snippets.NUnit/Attributes/RetryAttributeExamples.cs#Retry)] + +### Using RetryExceptions + +When you need to retry on specific exception types (such as `TimeoutException` or `OperationCanceledException`), you can set the `RetryExceptions` property: [!code-csharp[RetryWithRetryExceptions](~/snippets/Snippets.NUnit/Attributes/RetryAttributeExamples.cs#RetryWithRetryExceptions)] + +## Notes + +1. It is not currently possible to use `RetryAttribute` on a `TestFixture` or any other type of test suite. Only single test methods may be retried. +2. If a test has an unexpected exception, an error result is returned and it is not retried — unless that exception type is specified in the `RetryExceptions` property. + +## See Also + +* [Repeat Attribute](xref:attribute-repeat) diff --git a/docs/articles/nunit/writing-tests/attributes/sequential.md b/docs/articles/nunit/writing-tests/attributes/sequential.md index 1bbc5146c..d862b1afb 100644 --- a/docs/articles/nunit/writing-tests/attributes/sequential.md +++ b/docs/articles/nunit/writing-tests/attributes/sequential.md @@ -1,30 +1,35 @@ --- -uid: sequentialattribute +uid: attribute-sequential --- # Sequential -The **SequentialAttribute** is used on a test to specify that NUnit should generate test cases by selecting individual -data items provided for the parameters of the test, without generating additional combinations. +`SequentialAttribute` tells NUnit to generate test cases by matching parameter values by index rather than creating additional combinations. + +## Usage + +This is a parameterless attribute that can only be applied to test methods. + +```csharp +[Sequential] +``` + +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ✅ | ❌ | ❌ | > [!NOTE] > If parameter data is provided by multiple attributes, the order in which NUnit uses the data items is not > guaranteed. However, it can be expected to remain constant for a given runtime and operating system. For best results -with **SequentialAttribute** use only one data attribute on each parameter. +> with **SequentialAttribute** use only one data attribute on each parameter. ## Example -The following test will be executed three times. +The following test is executed three times. -```csharp -[Test, Sequential] -public void MyTest( - [Values(1, 2, 3)] int x, - [Values("A", "B")] string s) -{ - /* ... */ -} -``` +[!code-csharp[SequentialBasic](~/snippets/Snippets.NUnit/Attributes/SequentialAttributeExamples.cs#SequentialBasic)] MyTest is called three times, as follows: @@ -34,7 +39,14 @@ MyTest(2, "B") MyTest(3, null) ``` -## See also +## Notes + +1. `Sequential` pairs values from each parameter by position (`index 0` with `index 0`, and so on). +2. If parameter data lengths differ, missing entries are filled using the default value for that parameter type. +3. Prefer one data-providing attribute per parameter when using `Sequential` to avoid ordering ambiguities. + +## See Also -* [Combinatorial Attribute](combinatorial.md) -* [Pairwise Attribute](pairwise.md) +* [Combinatorial Attribute](xref:attribute-combinatorial) +* [Pairwise Attribute](xref:attribute-pairwise) +* [Values Attribute](xref:attribute-values) diff --git a/docs/articles/nunit/writing-tests/attributes/setculture.md b/docs/articles/nunit/writing-tests/attributes/setculture.md index c41179128..b3cce3d99 100644 --- a/docs/articles/nunit/writing-tests/attributes/setculture.md +++ b/docs/articles/nunit/writing-tests/attributes/setculture.md @@ -1,33 +1,55 @@ +--- +uid: attribute-setculture +--- + # SetCulture -The SetCulture attribute is used to set the current Culture for the duration -of a test. It may be specified at the level of a test, fixture or assembly. The culture -remains set until the test or fixture completes and is then reset to its original -value. If you wish to use the current culture setting to decide whether to run -a test, use the Culture attribute instead of this one. +`SetCultureAttribute` is used to set the current `CultureInfo.CurrentCulture` for the duration of a test. The culture remains set until the test or fixture completes and is then reset to its original value. -Only one culture may be specified. Running a test under -multiple cultures is a planned future enhancement. At this time, you can -achieve the same result by factoring out your test code into a private method -that is called by each individual test method. +This attribute affects formatting operations such as number formatting, date formatting, and string comparisons that depend on culture settings. -## Examples +## Constructor ```csharp -namespace NUnit.Tests -{ - using System; - using NUnit.Framework; - - [TestFixture] - [SetCulture("fr-FR")] - public class FrenchCultureTests - { - // ... - } -} +SetCultureAttribute(string culture) ``` -## See also +| Parameter | Type | Description | +|-----------|------|-------------| +| `culture` | `string` | The name of the culture to use (e.g., `"fr-FR"`, `"de-DE"`, `"en-US"`). Must be a valid culture name recognized by `CultureInfo`. | + +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ✅ | ✅ | ✅ | + +> [!NOTE] +> If `SetCultureAttribute` is applied at fixture or assembly level, the culture setting applies to all contained tests. + +When applied at multiple levels, the most specific level takes precedence. The attribute is inherited by derived test fixtures. + +## Examples + +### Setting Culture on a Fixture + +[!code-csharp[SetCultureOnFixture](~/snippets/Snippets.NUnit/Attributes/SetCultureAttributeExamples.cs#SetCultureOnFixture)] + +### Setting Culture on Individual Methods + +[!code-csharp[SetCultureOnMethod](~/snippets/Snippets.NUnit/Attributes/SetCultureAttributeExamples.cs#SetCultureOnMethod)] + +### Combining with SetUICulture + +[!code-csharp[SetCultureWithSetUICulture](~/snippets/Snippets.NUnit/Attributes/SetCultureAttributeExamples.cs#SetCultureWithSetUICulture)] + +## Notes + +1. Only one culture may be specified per attribute. To test with multiple cultures, create separate test methods or use parameterized tests. +2. `SetCulture` affects `CultureInfo.CurrentCulture`, which controls formatting operations. Use `SetUICulture` to control `CultureInfo.CurrentUICulture` for resource loading. +3. If you need to conditionally run tests based on the current culture (rather than setting it), use the `Culture` attribute instead. + +## See Also -* [Culture Attribute](culture.md) +* [SetUICulture Attribute](xref:attribute-setuiculture) +* [Culture Attribute](xref:attribute-culture) diff --git a/docs/articles/nunit/writing-tests/attributes/setuiculture.md b/docs/articles/nunit/writing-tests/attributes/setuiculture.md index 32e53ec21..a3e02ff36 100644 --- a/docs/articles/nunit/writing-tests/attributes/setuiculture.md +++ b/docs/articles/nunit/writing-tests/attributes/setuiculture.md @@ -1,34 +1,57 @@ +--- +uid: attribute-setuiculture +--- + # SetUICulture -The SetUICulture attribute is used to set the current UI Culture for the duration -of a test. It may be specified at the level of a test or a fixture. The UI culture -remains set until the test or fixture completes and is then reset to its original -value. If you wish to use the current culture setting to decide whether to run -a test, use the Culture attribute instead of this one. +`SetUICultureAttribute` is used to set the current `CultureInfo.CurrentUICulture` for the duration of a test. The UI culture remains set until the test or fixture completes and is then reset to its original value. -Only one culture may be specified. Running a test under -multiple cultures is a planned future enhancement. At this time, you can -achieve the same result by factoring out your test code into a private method -that is called by each individual test method. +This attribute affects resource loading operations. When your application uses `ResourceManager` to load localized strings, images, or other resources, it uses `CurrentUICulture` to determine which localized resources to load. -## Examples +## Constructor ```csharp -namespace NUnit.Tests -{ - using System; - using NUnit.Framework; - - [TestFixture] - [SetUICulture("fr-FR")] - public class FrenchCultureTests - { - // ... - } -} +SetUICultureAttribute(string culture) ``` -## See also +| Parameter | Type | Description | +|-----------|------|-------------| +| `culture` | `string` | The name of the UI culture to use (e.g., `"fr-FR"`, `"de-DE"`, `"en-US"`). Must be a valid culture name recognized by `CultureInfo`. | + +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ✅ | ✅ | ✅ | + +> [!NOTE] +> If `SetUICultureAttribute` is applied at fixture or assembly level, the UI culture setting applies to all contained tests. + +When applied at multiple levels, the most specific level takes precedence. The attribute is inherited by derived test fixtures. + +## Examples + +### Setting UI Culture on a Fixture + +[!code-csharp[SetUICultureOnFixture](~/snippets/Snippets.NUnit/Attributes/SetUICultureAttributeExamples.cs#SetUICultureOnFixture)] + +### Setting UI Culture on Individual Methods + +[!code-csharp[SetUICultureOnMethod](~/snippets/Snippets.NUnit/Attributes/SetUICultureAttributeExamples.cs#SetUICultureOnMethod)] + +### Using Both SetCulture and SetUICulture + +Use both attributes when you need to test with different formatting and UI cultures: + +[!code-csharp[BothCultures](~/snippets/Snippets.NUnit/Attributes/SetUICultureAttributeExamples.cs#BothCultures)] + +## Notes + +1. Only one UI culture may be specified per attribute. To test with multiple cultures, create separate test methods or use parameterized tests. +2. `SetUICulture` affects `CultureInfo.CurrentUICulture`, which controls resource loading. It does **not** affect `CultureInfo.CurrentCulture` (formatting). Use `SetCulture` for formatting operations. +3. If you need to conditionally run tests based on the current culture (rather than setting it), use the `Culture` attribute instead. + +## See Also -* [Culture Attribute](culture.md)] -* [SetCulture Attribute](setculture.md) +* [SetCulture Attribute](xref:attribute-setculture) +* [Culture Attribute](xref:attribute-culture) diff --git a/docs/articles/nunit/writing-tests/attributes/setup.md b/docs/articles/nunit/writing-tests/attributes/setup.md index e4aff2f22..6aac83a0e 100644 --- a/docs/articles/nunit/writing-tests/attributes/setup.md +++ b/docs/articles/nunit/writing-tests/attributes/setup.md @@ -1,20 +1,55 @@ --- -uid: setup-attribute +uid: attribute-setup --- # SetUp -This attribute is used inside a [TestFixture](xref:testfixtureattribute) to provide a common set of functions that are -performed just before each test method is called. +`SetUpAttribute` marks a method NUnit calls **immediately before each** `[Test]`, `[TestCase]`, `[Theory]`, etc. in the +fixture. Use it to reset or prepare **per-test** instance state that should not leak between cases. -SetUp methods may be either static or instance methods and you may define more than one of them in a fixture. Normally, -multiple SetUp methods are only defined at different levels of an inheritance hierarchy, as explained below. +The method lives on your [`TestFixture`](xref:attribute-testfixture) (or fixture base classes in the inheritance chain). Typical use is +alongside **[`TearDown`](xref:attribute-teardown)** for symmetrical cleanup afterward. -If a SetUp method fails or throws an exception, the test is not executed and a failure or error is reported. +Normally you scatter **multiple** `[SetUp]` methods across inheritance levels (**base**, then **derived**). Declaring several +marked methods on **one class** is allowed, but mutual **order among them is undefined** unless you constrain them logically. + +## Static and instance methods + +`SetUp` may be **`static`** or an **instance** method. Instance methods execute on **`context.TestObject`**, meaning the **same +fixture instance** that receives the imminent test (`LifeCycle.SingleInstance`) or **a freshly constructed instance** before +every test when [`LifeCycle.InstancePerTestCase`](xref:attribute-fixturelifecycle) is in effect. + +Prefer **instance** `SetUp` for fields on the test object; use **`static`** only when the preparation truly applies without a +specific instance (be careful with shared static state under parallel runs). + +Methods may be **`async`** (`Task` / `Task`); NUnit awaits them like other async test infrastructure. + +## Failures and assumptions + +If `SetUp` throws or an assertion fails, the **test method body is not run**; the result reflects a **setup** failure +(`FailureSite.SetUp`). [`TearDown`](xref:attribute-teardown) for that same per-test scope **still runs afterwards** in normal operation +so you can release partially initialized resources—unless the run is **aborted** before teardown is reached. + +If you use **`Assume.That(...)`** in `SetUp`, a failed assumption also prevents the test body from running (treated like a +setup outcome). Teardown behavior matches the normal path above. + +## Usage + +This is a parameterless attribute that can only be applied to methods. + +```csharp +[SetUp] +``` + +## Applies To + +| Lifecycle Methods | Test Methods | Test Fixtures (Classes) | Assembly | +|-------------------|--------------|--------------------------|----------| +| ✅ | ❌ | ❌ | ❌ | ## Example -[!code-csharp[SetUpTearDownExample](~/snippets/Snippets.NUnit/AttributeExamples.cs#SetUpTearDownExample)] +[!code-csharp[SetUpExample](~/snippets/Snippets.NUnit/Attributes/SetUpAttributeExamples.cs#SetUpExample)] ## Inheritance @@ -31,14 +66,14 @@ methods before those in the derived classes. ## Notes -1. Although it is possible to define multiple SetUp methods in the same class, you should rarely do so. Unlike methods - defined in separate classes in the inheritance hierarchy, the order in which they are executed is not guaranteed. - -2. You may specify an async method (`async` keyword in c#) if necessary, when running under .NET 4.0 or higher. +1. **`TestContext`** — `SetUp` runs in **per-test** context; most `TestContext` APIs reflect the **about-to-run** test. +2. Multiple `SetUp` methods on the **same** declaration have **no guaranteed** relative order. +3. Base-class `SetUp` runs **before** derived-class `SetUp` (see **Inheritance**). -## See also +## See Also -* [TearDown Attribute](teardown.md) -* [OneTimeSetUp Attribute](onetimesetup.md) -* [OneTimeTearDown Attribute](onetimeteardown.md) -* [testfixture attribute](testfixture.md) +* [TearDown Attribute](xref:attribute-teardown) +* [OneTimeSetUp Attribute](xref:attribute-onetimesetup) +* [OneTimeTearDown Attribute](xref:attribute-onetimeteardown) +* [FixtureLifeCycle Attribute](xref:attribute-fixturelifecycle) +* [TestFixture Attribute](xref:attribute-testfixture) diff --git a/docs/articles/nunit/writing-tests/attributes/setupfixture.md b/docs/articles/nunit/writing-tests/attributes/setupfixture.md index 472a6af0f..5fc167b6e 100644 --- a/docs/articles/nunit/writing-tests/attributes/setupfixture.md +++ b/docs/articles/nunit/writing-tests/attributes/setupfixture.md @@ -1,15 +1,26 @@ --- -uid: setupfixture-attribute +uid: attribute-setupfixture --- # SetUpFixture -This is the attribute that marks a class that contains the one-time -setup or teardown methods for all the test fixtures in a given -namespace including nested namespaces below, within an assembly. +`SetUpFixtureAttribute` marks a class that provides one-time setup/teardown for all fixtures in a namespace (including nested namespaces) within an assembly. -The class may contain at most one method marked with the -OneTimeSetUpAttribute and one method marked with the OneTimeTearDownAttribute. +The class may contain at most one `[OneTimeSetUp]` and one `[OneTimeTearDown]` method. + +## Usage + +This is a parameterless attribute that can only be applied to classes. + +```csharp +[SetUpFixture] +``` + +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | Helper Classes | +|--------------|--------------------------|----------|----------------| +| ❌ | ❌ | ❌ | ✅ | There are a few restrictions on a class that is used as a setup fixture. @@ -26,7 +37,7 @@ individual or fixture teardowns have completed execution. Multiple SetUpFixtures may be created in a given namespace. The order of execution of such fixtures is indeterminate. -## Notes +## Scope * The scope of a SetUpFixture is limited to an assembly. * A SetUpFixture in a namespace will apply to all tests in that namespace and all contained namespaces within the assembly. @@ -34,29 +45,7 @@ of such fixtures is indeterminate. ## Example -```csharp -using System; -using NUnit.Framework; - -namespace NUnit.Tests -{ - [SetUpFixture] - public class MySetUpClass - { - [OneTimeSetUp] - public void RunBeforeAnyTests() - { - // ... - } - - [OneTimeTearDown] - public void RunAfterAnyTests() - { - // ... - } - } -} -``` +[!code-csharp[SetUpFixtureExample](~/snippets/Snippets.NUnit/Attributes/SetUpFixtureAttributeExamples.cs#SetUpFixtureExample)] ## Detailed explanation @@ -80,18 +69,15 @@ The defined order is as follows... ## Notes -1. About filtering on `SetUpFixture`s: - A `SetUpFixture` is normally not used for filtering tests. However, if that is done, one should be aware that a - `SetUpFixture` encapsulates all tests to which it belongs. - If placed in a namespace it will encapsulate all tests in that namespace and contained namespaces. - If placed on the assembly level, it will encapsulate all tests in the assembly. - -2. Prior to NUnit 3.0, `SetUpFixture` used the `SetUp` and `TearDown` attributes rather than `OneTimeSetUp` and - `OneTimeTearDown`. The older attributes are no longer supported in SetUpFixtures in NUnit 3.0 and later. +1. `SetUpFixture` classes must be public and have a default constructor (or be static). +2. `SetUp` and `TearDown` attributes are not valid inside a `SetUpFixture`. +3. A setup fixture outside any namespace applies to the entire assembly. +4. Multiple setup fixtures at the same namespace level execute in indeterminate order. +5. Prior to NUnit 3.0, setup fixtures used `SetUp`/`TearDown`; NUnit 3+ uses `OneTimeSetUp`/`OneTimeTearDown`. -## See also +## See Also -* [SetUp Attribute](setup.md) -* [TearDown Attribute](teardown.md) -* [OneTimeSetUp Attribute](onetimesetup.md) -* [OneTimeTearDown Attribute](onetimeteardown.md) +* [SetUp Attribute](xref:attribute-setup) +* [TearDown Attribute](xref:attribute-teardown) +* [OneTimeSetUp Attribute](xref:attribute-onetimesetup) +* [OneTimeTearDown Attribute](xref:attribute-onetimeteardown) diff --git a/docs/articles/nunit/writing-tests/attributes/singlethreaded.md b/docs/articles/nunit/writing-tests/attributes/singlethreaded.md index a2d25247b..55610272e 100644 --- a/docs/articles/nunit/writing-tests/attributes/singlethreaded.md +++ b/docs/articles/nunit/writing-tests/attributes/singlethreaded.md @@ -1,6 +1,39 @@ +--- +uid: attribute-singlethreaded +--- + # SingleThreaded -`SingleThreadedAttribute` is used on a TestFixture and indicates that the OneTimeSetUp, OneTimeTearDown and all the -child tests must run on the same thread. +`SingleThreadedAttribute` is used on a test fixture to ensure that `OneTimeSetUp`, `OneTimeTearDown`, and all child tests run on the same thread. This forces all child tests to be run sequentially on the current thread. + +## Usage + +This is a parameterless attribute that can only be applied to test fixture classes. + +```csharp +[SingleThreaded] +``` + +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ❌ | ✅ | ❌ | + +## Example + +[!code-csharp[SingleThreadedExample](~/snippets/Snippets.NUnit/Attributes/SingleThreadedAttributeExamples.cs#SingleThreadedExample)] + +## Notes + +1. When this attribute is applied, any `ParallelScope` setting on the fixture or its child tests is ignored. +2. This attribute is inherited by derived test fixture classes. +3. Use this attribute when your tests share resources that have thread affinity, such as database connections, COM objects, or UI components. +4. This attribute only affects the fixture it is applied to. Other fixtures in the same assembly can still run in parallel with this fixture (unless assembly-level parallelization is disabled). + +## See Also -When using this attribute, any `ParallelScope` setting is ignored. +* [Parallelizable Attribute](xref:attribute-parallelizable) +* [NonParallelizable Attribute](xref:attribute-nonparallelizable) +* [RequiresThread Attribute](xref:attribute-requiresthread) +* [Apartment Attribute](xref:attribute-apartment) diff --git a/docs/articles/nunit/writing-tests/attributes/teardown.md b/docs/articles/nunit/writing-tests/attributes/teardown.md index 47fd269d3..7c22e52ab 100644 --- a/docs/articles/nunit/writing-tests/attributes/teardown.md +++ b/docs/articles/nunit/writing-tests/attributes/teardown.md @@ -1,42 +1,58 @@ --- -uid: teardown-attribute +uid: attribute-teardown --- # TearDown -This attribute is used inside a [TestFixture](xref:testfixtureattribute) to provide a common set of functions that are -performed after each test method. +`TearDownAttribute` marks a method NUnit calls **immediately after each** test case finishes under a +[`TestFixture`](xref:attribute-testfixture). Pair it with [`SetUp`](xref:attribute-setup) to release **per-test** resources (files, handles, mock +substitutions, etc.). -TearDown methods may be either static or instance methods and you may define more than one of them in a fixture. -Normally, multiple TearDown methods are only defined at different levels of an inheritance hierarchy, as explained -below. +Like `SetUp`, you usually place tear-down helpers on **base classes** and **derived fixtures** rather than stacking many +methods on a single class (allowed, but **order among them is undefined**). -So long as any SetUp method runs without error, the TearDown method is guaranteed to run. For example, it is not -guaranteed to run if a SetUp method fails or throws an exception. +## Static and instance methods -## Example +`TearDown` may be **`static`** or an **instance** method and runs on the **same logical fixture object** NUnit used for that +test’s `SetUp` and test body (including a **new** instance per test when +[`LifeCycle.InstancePerTestCase`](xref:attribute-fixturelifecycle) applies). + +**`async`** `Task` / `Task` methods are supported. + +## When TearDown runs + +* **After a successful `SetUp` and test** — always in normal execution (unless the run is **aborted** before teardown is + dispatched). +* **After `SetUp` fails** — `TearDown` **still runs** so partially constructed state can be unwound. The **test method is + skipped** and the result shows a **setup** failure, but teardown for that level is **not** skipped solely because setup + failed. +* **After the test throws or fails** — `TearDown` still runs; the framework records the test failure **and** any teardown + exception separately if both occur. + +The only broad exception is an **abort** (`TestExecutionStatus.AbortRequested`), where NUnit may omit the teardown callback +entirely—mirroring the behavior described for [`OneTimeTearDown`](xref:attribute-onetimeteardown). + +Teardown failures or assertions are attached to the test result as **teardown** issues (`FailureSite.TearDown`) while +preserving the original test outcome when possible. + +## Usage + +This is a parameterless attribute that can only be applied to methods. ```csharp -namespace NUnit.Tests -{ - using System; - using NUnit.Framework; - - [TestFixture] - public class SuccessTests - { - [SetUp] public void Init() - { /* ... */ } - - [TearDown] public void Cleanup() - { /* ... */ } - - [Test] public void Add() - { /* ... */ } - } -} +[TearDown] ``` +## Applies To + +| Lifecycle Methods | Test Methods | Test Fixtures (Classes) | Assembly | +|-------------------|--------------|--------------------------|----------| +| ✅ | ❌ | ❌ | ❌ | + +## Example + +[!code-csharp[TearDownExample](~/snippets/Snippets.NUnit/Attributes/TearDownAttributeExamples.cs#TearDownExample)] + ## Inheritance The TearDown attribute is inherited from any base class. Therefore, if a base class has defined a TearDown method, that @@ -53,15 +69,14 @@ methods after those in the derived classes. ## Notes -1. Although it is possible to define multiple TearDown methods in the same class, you should rarely do so. Unlike - methods defined in separate classes in the inheritance hierarchy, the order in which they are executed is not - guaranteed. - -2. TearDown methods may be async if running under .NET 4.0 or higher. +1. **`TestContext`** — still **per-test** scope, but executed **after** the test method returns or throws. +2. Multiple `TearDown` methods on the **same** class are unordered relative to one another. +3. **Derived** `TearDown` runs **before** base-class `TearDown` when both apply (see **Inheritance**). -## See also +## See Also -* [SetUp Attribute](setup.md) -* [OneTimeSetUp Attribute](onetimesetup.md) -* [OneTimeTearDown Attribute](onetimeteardown.md) -* [TestFixture Attribute](testfixture.md) +* [SetUp Attribute](xref:attribute-setup) +* [OneTimeSetUp Attribute](xref:attribute-onetimesetup) +* [OneTimeTearDown Attribute](xref:attribute-onetimeteardown) +* [FixtureLifeCycle Attribute](xref:attribute-fixturelifecycle) +* [TestFixture Attribute](xref:attribute-testfixture) diff --git a/docs/articles/nunit/writing-tests/attributes/test.md b/docs/articles/nunit/writing-tests/attributes/test.md index 52eca6efc..85fb29220 100644 --- a/docs/articles/nunit/writing-tests/attributes/test.md +++ b/docs/articles/nunit/writing-tests/attributes/test.md @@ -1,68 +1,57 @@ +--- +uid: attribute-test +--- + # Test -The `Test` attribute is one way of marking a method inside a TestFixture class as a test. It is normally used for simple -(non-parameterized) tests but may also be applied to parameterized tests without causing any extra test cases to be -generated. See [Parameterized Tests](xref:parameterizedtests) for more info. +The `Test` attribute marks a method inside a test fixture as a test. It is normally used for simple (non-parameterized) +tests but may also be applied to parameterized tests without causing extra test cases to be generated. See +[Parameterized Tests](xref:parameterizedtests) for more information. The test method may be either an instance or a static method. -Test methods targeting .Net 4.0 or higher may be marked as **async** and NUnit will wait for the method to complete -before recording the result and moving on to the next test. Async test methods must return `Task` if no value is -returned, or `Task` if a value of type T is returned. - -If the programmer marks a test method that does not have the correct signature it will be considered as not runnable. - -If the test method returns a value, you must pass in the `ExpectedResult` named parameter to the Test attribute. This -expected return value will be checked for equality with the return value of the test method. +Test methods may be **async**; NUnit waits for the method to complete before recording the result. Async test methods +must return `Task` or `Task`. -The test `Description` may be specified as a named parameter. This is exactly equivalent to using the -`DescriptionAttribute` on the test. +If a test method does not have a valid signature, it is treated as not runnable. -## Examples +## Usage ```csharp -namespace NUnit.Tests -{ - using System; - using NUnit.Framework; - - [TestFixture] - public class SuccessTests - { - // A simple test - [Test] - public void Add() - { /* ... */ } - - // A test with a description property - [Test(Description="My really cool test")] - public void Add() - { /* ... */ } - - // Alternate way to specify description as a separate attribute - [Test, Description("My really really cool test")] - public void Add() - { /* ... */ } - - // A simple async test - [Test] - public async Task AddAsync() - { /* ... */ } - - // Test with an expected result - [Test(ExpectedResult = 4)] - public int TestAdd() - { - return 2 + 2; - } - - // Async test with an expected result - [Test(ExpectedResult = 4)] - public async Task TestAdd() - { - await ... - return 2 + 2; - } - } -} +[Test] ``` + +Use **named parameters** (properties on the attribute) for metadata and for checking a return value. + +## Properties + +| Property | Type | Description | Default | +|----------|------|-------------|---------| +| `Description` | `string?` | Descriptive text for the test. Equivalent to applying [`Description`](xref:attribute-description). | `null` | +| `Author` | `string?` | Author metadata. Equivalent to applying [`Author`](xref:attribute-author). | `null` | +| `TestOf` | `Type?` | Type under test. Equivalent to applying [`TestOf`](xref:attribute-testof). | `null` | +| `ExpectedResult` | `object?` | Expected return value; NUnit compares it to the method result. **Not valid** if the test method has parameters. | (unset) | + +If the test method returns a value and you set `ExpectedResult`, NUnit checks equality with the return value. + +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ✅ | ❌ | ❌ | + +## Example + +[!code-csharp[BasicTest](~/snippets/Snippets.NUnit/Attributes/TestAttributeExamples.cs#BasicTest)] + +[!code-csharp[TestWithDescription](~/snippets/Snippets.NUnit/Attributes/TestAttributeExamples.cs#TestWithDescription)] + +[!code-csharp[AsyncTest](~/snippets/Snippets.NUnit/Attributes/TestAttributeExamples.cs#AsyncTest)] + +[!code-csharp[ExpectedResultTest](~/snippets/Snippets.NUnit/Attributes/TestAttributeExamples.cs#ExpectedResultTest)] + +## See Also + +* [TestCase Attribute](xref:attribute-testcase) +* [TestCaseSource Attribute](xref:attribute-testcasesource) +* [Theory Attribute](xref:attribute-theory) diff --git a/docs/articles/nunit/writing-tests/attributes/testassemblydirectoryresolve.md b/docs/articles/nunit/writing-tests/attributes/testassemblydirectoryresolve.md index a7d4933e9..f44e6467b 100644 --- a/docs/articles/nunit/writing-tests/attributes/testassemblydirectoryresolve.md +++ b/docs/articles/nunit/writing-tests/attributes/testassemblydirectoryresolve.md @@ -1,5 +1,5 @@ --- -uid: testassemblydirectoryresolveattribute +uid: attribute-testassemblydirectoryresolve --- # TestAssemblyDirectoryResolve @@ -31,24 +31,15 @@ Apply the attribute at the assembly level in your test project: This is typically placed in a file like `AssemblyInfo.cs` or a dedicated assembly attributes file. -## Example - -### AssemblyInfo.cs - -```csharp -using NUnit.Framework; - -[assembly: TestAssemblyDirectoryResolve] -``` +## Applies To -### Or in a dedicated file (AssemblyAttributes.cs) +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ❌ | ❌ | ✅ | -```csharp -using NUnit.Framework; +## Example -// Enable explicit assembly directory resolution for this test assembly -[assembly: TestAssemblyDirectoryResolve] -``` +[!code-csharp[VerifyAttributeExists](~/snippets/Snippets.NUnit/Attributes/TestAssemblyDirectoryResolveAttributeExamples.cs#VerifyAttributeExists)] ## How It Works @@ -103,5 +94,5 @@ public class PluginTests ## See Also -* [NonTestAssembly Attribute](nontestassembly.md) +* [NonTestAssembly Attribute](xref:attribute-nontestassembly) * [.NET Assembly Loading](https://learn.microsoft.com/en-us/dotnet/framework/deployment/how-the-runtime-locates-assemblies) diff --git a/docs/articles/nunit/writing-tests/attributes/testcase.md b/docs/articles/nunit/writing-tests/attributes/testcase.md index 8bee50492..756f55a71 100644 --- a/docs/articles/nunit/writing-tests/attributes/testcase.md +++ b/docs/articles/nunit/writing-tests/attributes/testcase.md @@ -1,101 +1,145 @@ --- -uid: testcaseattribute +uid: attribute-testcase --- # TestCase -`TestCaseAttribute` serves the dual purpose of marking a method with parameters as a test method and providing inline -data to be used when invoking that method. Here is an example of a test being run three times, with three different sets -of data: +`TestCaseAttribute` marks a method with parameters as a test and supplies **inline arguments** for individual cases. You may apply the attribute multiple times to create several cases from one method. [!code-csharp[BasicTestCase](~/snippets/Snippets.NUnit/Attributes/TestCaseAttributeExamples.cs#BasicTestCase)] +The three `[TestCase(...)]` lines above yield **three** invocations—one set of arguments per attribute. + > [!NOTE] -> Because arguments to .NET attributes are limited in terms of the Types that may be used, NUnit will make some -> attempt to convert the supplied values using `Convert.ChangeType()` before supplying it to the test. +> Because arguments to .NET attributes are limited in terms of the types that may be used, NUnit attempts to convert literal values using `Convert.ChangeType()` before passing them into the method. + +**`TestCaseAttribute`** may appear one or more times on a test method, which may also carry other data-providing attributes. Once **any** parameter has explicit data (`[TestCase]`, `[Values]`, `[Range]`, …), **every** parameter must have a data source—see [Parameterized Tests](xref:parameterizedtests). The method may optionally be marked with the [Test attribute](xref:attribute-test) as well. + +## Constructors + +NUnit supplies arguments to the test method from the **positional** constructor parameters. You may repeat the attribute on the same method to provide multiple cases. + +```csharp +TestCaseAttribute(params object?[]? arguments) +TestCaseAttribute(object? arg) +TestCaseAttribute(object? arg1, object? arg2) +TestCaseAttribute(object? arg1, object? arg2, object? arg3) +``` + +On **.NET 6+**, generic forms such as `TestCaseAttribute` offer compile-time typed arguments (see **Generic TestCase Attributes** below). + +Use **named parameters** on the attribute for per-case metadata (`ExpectedResult`, `Ignore`, `Explicit`, etc.). + +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ✅ | ❌ | ❌ | -**TestCaseAttribute** may appear one or more times on a test method, which may also carry other attributes providing -test data. The method may optionally be marked with the [Test Attribute](test.md) as well. +## Expected result -By using the named parameter `ExpectedResult` this test set may be simplified further: +When the method returns a value, `ExpectedResult` lets NUnit compare the return value instead of asserting inside the body: [!code-csharp[TestCaseWithExpectedResult](~/snippets/Snippets.NUnit/Attributes/TestCaseAttributeExamples.cs#TestCaseWithExpectedResult)] -In the above example, NUnit checks that the return value of the method is equal to the expected result provided on the -attribute. +For those cases NUnit asserts that the **return value** equals the **`ExpectedResult`** specified on that attribute instance (rather than inspecting the attribute value inside the body). -TestCaseAttribute supports a number of additional named parameters: +## Named parameters overview -* **Author** sets the author of the test. -* **Category** provides a comma-delimited list of categories for this test. -* **Description** sets the description property of the test. -* **ExcludePlatform** specifies a comma-delimited list of platforms on which the test should not run. -* **ExpectedResult** sets the expected result to be returned from the method, which must have a compatible return type. -* **Explicit** is set to true in order to make the individual test case Explicit. Use **Reason** to explain why. -* **Ignore** causes the test case to be ignored and specifies the reason. -* **IgnoreReason** causes this test case to be ignored and specifies the reason. -* **IncludePlatform** specifies a comma-delimited list of platforms on which the test should run. -* **Reason** specifies the reason for not running this test case. Use in conjunction with **Explicit**. -* **TestName** provides a name for the test. If not specified, a name is generated based on the method name and the - arguments provided. See [Template Based Test Naming](xref:templatebasedtestnaming). -* **TestOf** specifies the Type that this test is testing (this is not used within NUnit during test execution, - but may serve a purpose for the test author) -* **TypeArgs** specifies the `Type`s to be used when targeting a generic test method. (_NUnit 4.1+_) +Beyond arguments and `ExpectedResult`, each `TestCase` can set metadata and filters: -## Be aware of mixing the syntax for named parameters and attributes with the same name +| Named parameter | Role | +|-----------------|------| +| `Author` | Author metadata for this **case**. | +| `Category` | Comma-separated categories for this **case** only (not the whole fixture). | +| `Description` | Case description surfaced in runners and XML. | +| `ExcludePlatform` | Comma-separated platform identifiers to skip this case—see [Platform](xref:attribute-platform). | +| `ExpectedResult` | Expected return value; method must declare a compatible return type. | +| `Explicit` | Makes this single case explicit; pair with **`Reason`** for messaging. | +| `Ignore` / `IgnoreReason` | Ignores just this case; both set the skip reason (**`Ignore`** is an alias setter). | +| `IncludePlatform` | Comma-separated identifiers where this **case** is allowed—see [Platform](xref:attribute-platform). | +| `Reason` | Explanation for **`Explicit`** (or propagated as skip-reason metadata). | +| `TestName` | Custom template for this case display name—see [Template Based Test Naming](xref:templatebasedtestnaming). | +| `TestOf` | Documents the tested type (metadata only; not enforced by runners). | +| `TypeArgs` | Explicit generic type arguments (**NUnit 4.1+**). | +| `Until` | Time-boxed ignore; requires **`IgnoreReason`**—after the instant passes, the case runs normally (same rules as [`Ignore(..., Until = ...)`](xref:attribute-ignore)). | -### Correct `Ignore` Attribute Usage, by Example +Sections below reference **runnable** snippets for most switches. Some parameters (`Ignore`, `Explicit`, **`Category`**) are easy to misapply as **separate** attributes on the fixture—see **Naming collisions** after the examples. -> [!WARNING] -> When using the `Ignore` parameter (and others, see below), note that this has to be a named parameter. It is easy to accidentally add another `Ignore` attribute after the `TestCase` attribute. That will be the same as adding it separately, and it will apply to the complete fixture. This may apply to other named parameters, with names equal to other attributes, like the `Explicit` and `Category` parameters. +### Description, `Author`, and `TestOf` -Correct example usage: +[!code-csharp[TestCaseWithDescriptionAuthorTestOf](~/snippets/Snippets.NUnit/Attributes/TestCaseAttributeExamples.cs#TestCaseWithDescriptionAuthorTestOf)] -[!code-csharp[TestCaseWithIgnore](~/snippets/Snippets.NUnit/Attributes/TestCaseAttributeExamples.cs#TestCaseWithIgnore)] +### Include / exclude platforms -![TestCaseIgnoreDoneCorrect](../../../../images/TestCaseIgnoreDoneCorrect.png) +Per-case platform filters mirror the [Platform](xref:attribute-platform) attribute. The sample uses **`ExcludePlatform`** so it keeps running on typical desktops; an `IncludePlatform` idea appears in a comment because it can legitimately skip hosts that lack a moniker: -> [!WARNING] -> **Wrong way!** Below, we demonstrate an incorrect approach. -> -> (1) Adding it on the same line is the same as adding it on a separate line (3), both results in the fixture being ignored (2). +[!code-csharp[TestCaseWithPlatforms](~/snippets/Snippets.NUnit/Attributes/TestCaseAttributeExamples.cs#TestCaseWithPlatforms)] -![TestCaseIgnoreGoneWrong](../../../../images/TestCaseIgnoreGoneWrong.png) +### Custom `TestName` templates - -_Thanks to [Geir Marius Gjul](https://github.com/GeirMG) for raising this question again._ +Use template tokens such as `{m}`, `{c}`, `{a}`, `{0}`—see [Template Based Test Naming](xref:templatebasedtestnaming): -### Correct `Explicit` Attribute Usage, by Example +[!code-csharp[TestCaseWithTestName](~/snippets/Snippets.NUnit/Attributes/TestCaseAttributeExamples.cs#TestCaseWithTestName)] -`Explicit`, used correctly, looks like the following: +### `Ignore`, `Explicit`, and `Category` (named parameters) -[!code-csharp[TestCaseWithExplicit](~/snippets/Snippets.NUnit/Attributes/TestCaseAttributeExamples.cs#TestCaseWithExplicit)] +> [!WARNING] +> `Ignore`, `Explicit`, and `Category` **must appear as named properties on `[TestCase(...)]`.** A separate `[Ignore]` / `[Explicit]` line still decorates the **entire fixture**. See **Naming collisions** below. -Note that adding the `Reason` is optional, and Visual Studio TestExplorer will not even show it. +[!code-csharp[TestCaseWithIgnore](~/snippets/Snippets.NUnit/Attributes/TestCaseAttributeExamples.cs#TestCaseWithIgnore)] -### Correct `Category` Attribute Usage, by Example +[!code-csharp[TestCaseWithExplicit](~/snippets/Snippets.NUnit/Attributes/TestCaseAttributeExamples.cs#TestCaseWithExplicit)] -Categories can be applied to a single `TestCase` the same way, as a named parameter. Otherwise, it will apply to the whole fixture. Be sure what you're asking for! +**`Reason`** is optional alongside `Explicit = true`; some runners omit or obscure explicit reasons—for example Visual Studio Test Explorer often does **not** show the explanatory text even when supplied. [!code-csharp[TestCaseWithCategory](~/snippets/Snippets.NUnit/Attributes/TestCaseAttributeExamples.cs#TestCaseWithCategory)] +Putting **`[Category]`** on the fixture (or elsewhere on the test type) assigns categories to **all** tests under that fixture, whereas **`Category = "..."`** on `[TestCase]` scopes the category **to that generated case**. + +### `Until` with `IgnoreReason` + +`Until` follows the same constraints as [`Ignore(Until = ...)`](xref:attribute-ignore): **`IgnoreReason` is mandatory**—without it, NUnit marks the metadata invalid. + +[!code-csharp[TestCaseWithIgnoreUntil](~/snippets/Snippets.NUnit/Attributes/TestCaseAttributeExamples.cs#TestCaseWithIgnoreUntil)] + +### `TypeArgs` for generic test methods + +Runtime type substitution works on [.NET Framework](https://learn.microsoft.com/dotnet/standard/frameworks) and modern [.NET](https://learn.microsoft.com/dotnet/core/introduction): + +[!code-csharp[TestCaseWithTypeArgs](~/snippets/Snippets.NUnit/Attributes/TestCaseAttributeExamples.cs#TestCaseWithTypeArgs)] + +### Choosing `TypeArgs` vs generic `[TestCase<…>]` + +[!code-csharp[TypeArgsComparedToGenericAttribute](~/snippets/Snippets.NUnit/Attributes/TestCaseGenericExamples.cs#TypeArgsComparedToGenericAttribute)] + +**`TypeArgs`** keeps samples working on **.NET Framework** hosts. **`[TestCase(…)]`** (through five type parameters) needs **.NET 6+** generic attribute support (**NUnit 4.6+**). + +## Naming collisions + +Adding a **second** `[Ignore]` _attribute_ beside `[TestCase]` binds to the enclosing fixture—even if visually on the same or next line—as if you ignored the entire class. + +![Correct TestCase Ignore usage](../../../../images/TestCaseIgnoreDoneCorrect.png) + +The wrong layouts below show how easy it is to ignore the fixture by accident: _(1)_ an extra `[Ignore]` on the **same line** after `[TestCase]`, _(2)_ the fixture disappears as ignored tests, _(3)_ a separate `[Ignore]` line behaves the same as _(1)._ + +![Wrong TestCase Ignore usage](../../../../images/TestCaseIgnoreGoneWrong.png) + + +_Thanks to [Geir Marius Gjul](https://github.com/GeirMG) for raising this question again._ + ## Order of Execution -Individual test cases are executed in the order in which NUnit discovers them. This order does **not** necessarily -follow the lexical order of the attributes and will often vary between different compilers or different versions of the -CLR. +Individual test cases are executed in the order in which NUnit discovers them. This order does **not** necessarily follow the lexical order of the attributes and will often vary between different compilers or different versions of the CLR. -As a result, when **TestCaseAttribute** appears multiple times on a method or when other data-providing attributes are -used in combination with **TestCaseAttribute**, the order of the test cases is undefined. +As a result, when **TestCaseAttribute** appears multiple times on a method or when other data-providing attributes are used in combination with **TestCaseAttribute**, the order of the test cases is undefined. ## Generic TestCase Attributes -NUnit provides generic versions of `TestCaseAttribute` that offer compile-time type safety for test arguments. These are -available as `TestCaseAttribute` through `TestCaseAttribute`, supporting up to 5 type parameters. +NUnit provides generic versions of `TestCaseAttribute` that offer compile-time type safety for test arguments. These are available as `TestCaseAttribute` through `TestCaseAttribute`, supporting up to five type parameters. > [!NOTE] -> From NUnit 4.6 -> Generic TestCase attributes are only available on .NET 6.0 and later. They are not supported on .NET Framework. +> From NUnit **4.6**, generic **`TestCase<>`** attributes require runtimes with generic attribute support (**not** classic **.NET Framework**). Use **`TypeArgs`** there instead. ### Single Type Parameter @@ -124,21 +168,13 @@ You can mix generic and regular `TestCase` attributes on the same method: * **Clearer intent**: The expected types are explicit in the attribute declaration * **Refactoring safety**: Type changes are caught by the compiler -### Comparison with TypeArgs - -The `TypeArgs` named parameter provides similar functionality but is specified at runtime: - -```csharp -// Using TypeArgs (runtime type specification) -[TestCase(42, TypeArgs = new[] { typeof(int) })] -public void TestWithTypeArgs(T value) { } - -// Using generic attribute (compile-time type specification) -[TestCase(42)] -public void TestWithGenericAttribute(T value) { } -``` - -Both approaches are valid; choose based on your needs: +## See Also -* Use **generic attributes** when you want compile-time type safety -* Use **TypeArgs** when you need to specify types dynamically or when targeting .NET Framework +* [Test Attribute](xref:attribute-test) +* [Values Attribute](xref:attribute-values) +* [Range Attribute](xref:attribute-range) +* [Random Attribute](xref:attribute-random) +* [Platform Attribute](xref:attribute-platform) +* [Ignore Attribute](xref:attribute-ignore) +* [Explicit Attribute](xref:attribute-explicit) +* [TestCaseSource Attribute](xref:attribute-testcasesource) diff --git a/docs/articles/nunit/writing-tests/attributes/testcasesource.md b/docs/articles/nunit/writing-tests/attributes/testcasesource.md index c3644a62a..11c3b562e 100644 --- a/docs/articles/nunit/writing-tests/attributes/testcasesource.md +++ b/docs/articles/nunit/writing-tests/attributes/testcasesource.md @@ -1,5 +1,5 @@ --- -uid: testcasesourceattribute +uid: attribute-testcasesource --- # TestCaseSource @@ -9,6 +9,51 @@ arguments will be provided. The attribute additionally identifies the method as from the test itself and may be used by multiple test methods. See [Parameterized Tests](xref:parameterizedtests) for a general introduction to tests with arguments. +## Constructors + +```csharp +TestCaseSourceAttribute(string sourceName) +TestCaseSourceAttribute(string sourceName, object?[]? methodParams) +TestCaseSourceAttribute(Type sourceType, string sourceName) +TestCaseSourceAttribute(Type sourceType, string sourceName, object?[]? methodParams) +TestCaseSourceAttribute(Type sourceType) +``` + +See **Usage** below for when to use each form. + +## Properties + +| Property | Type | Description | +|----------|------|-------------| +| `Category` | `string?` | Assigns categories to **every** test case produced from this source. | +| `SourceName` | `string?` | Resolved source member name (if applicable). | +| `SourceType` | `Type?` | External type supplying the source (if applicable). | +| `MethodParams` | `object?[]?` | Arguments forwarded to a parameterized source method. | + +## Named parameters + +Besides the positional constructor arguments, **`TestCaseSource`** exposes **`Category`** as its main **writable** named +argument. Assign it inline on the **`[TestCaseSource(...)]`** clause—**do not** add a sibling `[Category]` attribute +expecting case-level tagging; that attaches to the **fixture** metadata instead (similar caveats apply as on +[TestCase named parameters](xref:attribute-testcase#named-parameters-overview)). + +```csharp +[TestCaseSource(nameof(MyCases), Category = "Fast,Smoke")] +``` + +* Separate multiple entries with commas, following the usual **[Category attribute](xref:attribute-category)** rules (`"Smoke,Integration"`). +* **Every generated test** from **that `[TestCaseSource]` application** inherits the supplied categories—you cannot cherry-pick categories per yielded row unless you bake them into **`TestCaseData`** / **`TestCaseParameters`** inside the enumerator. + +[!code-csharp[TestCaseSourceWithCategory](~/snippets/Snippets.NUnit/TestCaseSourceExamples.cs#TestCaseSourceWithCategory)] + +`SourceName`, `SourceType`, and **`MethodParams`** are **constructor outputs** surfaced as read-only properties for introspection—they are **not** set manually in everyday tests. + +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ✅ | ❌ | ❌ | + ## Usage Consider a test of the divide operation, taking three arguments: the numerator, the denominator and the expected result. @@ -31,8 +76,6 @@ It has the following characteristics: * It **must** be static. This is a change from NUnit 2.x. * It must return an `IEnumerable` or a type that implements `IEnumerable`. For fields an array is generally used. For properties and methods, you may return an array or implement your own iterator. - * Methods may also return an `IAsyncEnumerable` or a type that implements `IAsyncEnumerable`. (_NUnit 4+_) - * Methods may be async by wrapping the return type in a `Task`. (_NUnit 3.14+_) * The individual items returned by the enumerator must be compatible with the signature of the method on which the attribute appears. See the **Test Case Construction** section below for details. @@ -55,8 +98,6 @@ characteristics: * It **must** be static. This is a change from NUnit 2.x. * It must return an `IEnumerable` or a type that implements `IEnumerable`. For fields an array is generally used. For properties and methods, you may return an array or implement your own iterator. - * Methods may also return an `IAsyncEnumerable` or a type that implements `IAsyncEnumerable`. (_NUnit 4+_) - * Methods may be async by wrapping the return type in a `Task`. (_NUnit 3.14+_) * The individual items returned by the enumerator must be compatible with the signature of the method on which the attribute appears. See the **Test Case Construction** section below for details. @@ -72,7 +113,12 @@ the attribute appears. See the **Test Case Construction** section below for deta Note that it is not possible to pass parameters to the source, even if the source is a method. -## Sources with expected result using TestCaseData +## Using TestCaseData + +The `TestCaseData` class provides a fluent API for defining test cases with additional metadata such as expected +results, categories, and explicit type arguments. See [TestCaseData](xref:testcasedata) for complete documentation. + +### Expected results As of NUnit 3.12, it is possible to use a typed source with an expected result. This is done by using the `TestCaseSource` attribute on a method that returns a `TestCaseData` object. The `TestCaseData` object can be @@ -80,9 +126,7 @@ constructed with the expected result as a parameter. [!code-csharp[TypedSourceWithExpectedResult](~/snippets/Snippets.NUnit/TestCaseDataExample.cs#TestCaseDataExample)] -See [TestCaseData](xref:testcasedata) for more information on the `TestCaseData` class. - -## Sources for generic methods using TestCaseData +### Generic methods with TypeArgs As of NUnit 4.1, it is possible to explicitly specify the generic types to be used for a generic method. This may be useful when any of the test case arguments differ from the desired generic types. When omitted, NUnit will @@ -90,15 +134,26 @@ infer the generic type arguments based on the passed values from the `TestCaseSo [!code-csharp[TypedSourceWithExplicitGenericTypes](~/snippets/Snippets.NUnit/TestCaseDataExample.cs#TestCaseDataTypeArgsExample)] -See [TestCaseData](xref:testcasedata) for more information on the `TestCaseData` class. +### Generic TestCaseData variants + +As of NUnit 4.1, you can also use generic `TestCaseData` variants that automatically set the `TypeArgs` property +based on their type parameters. This provides a more concise syntax when working with generic test methods: + +* `TestCaseData` - for single type parameter +* `TestCaseData` - for two type parameters +* `TestCaseData` - for three type parameters +* `TestCaseData` - for four type parameters +* `TestCaseData` - for five type parameters -## Examples using TestCaseSource with Typed data and expected results +[!code-csharp[GenericTestCaseData](~/snippets/Snippets.NUnit/TestCaseDataExample.cs#GenericTestCaseDataExample)] + +### Typed data without TestCaseData It may seem from the examples above that TestCaseSource can only be used with simple data types or the base Object type. This is not the case. TestCaseSource can be used with typed data and also including expected results, also without using TestCaseData. -In the example below the test method takes a single argument of a an anonymous tuple type with `Person` and an expected +In the example below the test method takes a single argument of an anonymous tuple type with `Person` and an expected value of type `bool`. It can of course be any type, if that makes sense for the test. The TestCaseSource method returns an `IEnumerable<>` of the anonymous tuple type. @@ -109,11 +164,35 @@ shown in the example below. [!code-csharp[TypedValuesWithExpectedInWrapperClass](~/snippets/Snippets.NUnit/TestCaseSourceExamples.cs#TypedValuesWithExpectedInWrapperClass)] -## Named Parameters +## Advanced Source Features + +### Async and IAsyncEnumerable sources + +Source methods can return async types for scenarios where test data needs to be fetched asynchronously (e.g., from a +database or API): + +* `IAsyncEnumerable` - for async iteration (_NUnit 4+_) +* `Task>` - for async initialization (_NUnit 3.14+_) + +[!code-csharp[AsyncEnumerableSource](~/snippets/Snippets.NUnit/TestCaseSourceExamples.cs#AsyncEnumerableSource)] + +### Optional parameters with default values + +When a test method has optional parameters with default values, the `TestCaseSource` can provide fewer arguments +than the method signature requires. NUnit will use the default values for any parameters not supplied by the +test case data. + +[!code-csharp[OptionalParameters](~/snippets/Snippets.NUnit/TestCaseSourceExamples.cs#OptionalParameters)] + +### CancellationToken support + +When using `[CancelAfter]` with `TestCaseSource`, NUnit automatically injects a `CancellationToken` as the last +parameter of the test method. The test case source should **not** include the `CancellationToken` in its data—NUnit +provides it automatically. -TestCaseSourceAttribute supports one named parameter: +[!code-csharp[CancellationTokenSupport](~/snippets/Snippets.NUnit/TestCaseSourceExamples.cs#CancellationTokenSupport)] -* **Category** is used to assign one or more categories to every test case returned from this source. +See [CancelAfter](xref:attribute-cancelafter) for more information on cancellation token handling. ## Test Case Construction @@ -142,6 +221,10 @@ In constructing tests, NUnit uses each item returned by the enumerator as follow in the current release. 3. The GetEnumerator method may use yield statements or simply return the enumerator for an array or other collection held by the class. +4. If the source member is not static (i.e., an instance field, property, or method), NUnit will report an error + indicating that the source must be static. +5. If the source throws an exception during enumeration, NUnit catches the exception and reports it as a test error, + showing which test cases were successfully loaded before the failure occurred. ### Order of Execution diff --git a/docs/articles/nunit/writing-tests/attributes/testfixture.md b/docs/articles/nunit/writing-tests/attributes/testfixture.md index 79d862e36..3f68f7225 100644 --- a/docs/articles/nunit/writing-tests/attributes/testfixture.md +++ b/docs/articles/nunit/writing-tests/attributes/testfixture.md @@ -1,11 +1,28 @@ --- -uid: testfixtureattribute +uid: attribute-testfixture --- # TestFixture This is the attribute that marks a class that contains tests and, optionally, setup or teardown methods. +## Constructors + +```csharp +TestFixtureAttribute() +TestFixtureAttribute(params object?[]? arguments) +``` + +The `arguments` overload supplies constructor arguments and/or leading `System.Type` values used as generic type +arguments for the fixture. Named parameters on the attribute (such as **Ignore**, **Category**, **TypeArgs**) are covered +below. + +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ❌ | ✅ | ❌ | + Most restrictions on a class that is used as a test fixture have now been eliminated. A test fixture class: * May be public, protected, private or internal. diff --git a/docs/articles/nunit/writing-tests/attributes/testfixturesetup.md b/docs/articles/nunit/writing-tests/attributes/testfixturesetup.md index 39633bf89..38ccfb073 100644 --- a/docs/articles/nunit/writing-tests/attributes/testfixturesetup.md +++ b/docs/articles/nunit/writing-tests/attributes/testfixturesetup.md @@ -1,4 +1,25 @@ +--- +uid: attribute-testfixturesetup +--- + # TestFixtureSetUp > [!IMPORTANT] -> The TestFixtureSetUp attribute has been deprecated. Use [OneTimeSetUp Attribute](onetimesetup.md) instead. +> The TestFixtureSetUp attribute has been deprecated. Use [OneTimeSetUp Attribute](xref:attribute-onetimesetup) instead. + +`TestFixtureSetUpAttribute` was used in older NUnit versions for one-time setup before tests in a fixture. + +## Usage + +This legacy attribute is deprecated and should be replaced with `[OneTimeSetUp]`. + +## Applies To + +| Lifecycle Methods | Test Methods | Test Fixtures (Classes) | Assembly | +|-------------------|--------------|--------------------------|----------| +| ✅ | ❌ | ❌ | ❌ | + +## See Also + +* [OneTimeSetUp Attribute](xref:attribute-onetimesetup) +* [SetUp Attribute](xref:attribute-setup) diff --git a/docs/articles/nunit/writing-tests/attributes/testfixturesource.md b/docs/articles/nunit/writing-tests/attributes/testfixturesource.md index 62f75c88d..9674e7a85 100644 --- a/docs/articles/nunit/writing-tests/attributes/testfixturesource.md +++ b/docs/articles/nunit/writing-tests/attributes/testfixturesource.md @@ -1,9 +1,39 @@ +--- +uid: attribute-testfixturesource +--- + # TestFixtureSource `TestFixtureSourceAttribute` is used on a parameterized fixture to identify the source from which the required constructor arguments will be provided. The data is kept separate from the fixture itself and may be used by multiple fixtures. See [Parameterized Tests](xref:parameterizedtests) for a general introduction to tests with arguments. +## Constructors + +```csharp +TestFixtureSourceAttribute(string sourceName) +TestFixtureSourceAttribute(Type sourceType, string sourceName) +TestFixtureSourceAttribute(Type sourceType) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `sourceName` | `string` | Name of the source member used to provide fixture arguments. | +| `sourceType` | `Type` | Type containing the source member, or implementing `IEnumerable` in form 3. | + +## Properties + +| Property | Type | Description | Default | +|----------|------|-------------|---------| +| `Category` | `string` | Category (or comma-separated categories) applied to each generated fixture. | `null` | +| `TypeArgs` | `Type[]` | Explicit generic type arguments for generated fixture instances. | `null` | + +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ❌ | ✅ | ❌ | + ## Usage Consider a test fixture class taking two parameters in its constructor, a string and an int. We can specify the test and diff --git a/docs/articles/nunit/writing-tests/attributes/testfixtureteardown.md b/docs/articles/nunit/writing-tests/attributes/testfixtureteardown.md index e3543c76f..69e7b370f 100644 --- a/docs/articles/nunit/writing-tests/attributes/testfixtureteardown.md +++ b/docs/articles/nunit/writing-tests/attributes/testfixtureteardown.md @@ -1,4 +1,25 @@ +--- +uid: attribute-testfixtureteardown +--- + # TestFixtureTearDown > [!IMPORTANT] -> The TextFixtureTearDown attribute has been deprecated. Use [OneTimeTearDown Attribute](onetimeteardown.md) instead. +> The TestFixtureTearDown attribute has been deprecated. Use [OneTimeTearDown Attribute](xref:attribute-onetimeteardown) instead. + +`TestFixtureTearDownAttribute` was used in older NUnit versions for one-time teardown after all tests in a fixture. + +## Usage + +This legacy attribute is deprecated and should be replaced with `[OneTimeTearDown]`. + +## Applies To + +| Lifecycle Methods | Test Methods | Test Fixtures (Classes) | Assembly | +|-------------------|--------------|--------------------------|----------| +| ✅ | ❌ | ❌ | ❌ | + +## See Also + +* [OneTimeTearDown Attribute](xref:attribute-onetimeteardown) +* [TearDown Attribute](xref:attribute-teardown) diff --git a/docs/articles/nunit/writing-tests/attributes/testof.md b/docs/articles/nunit/writing-tests/attributes/testof.md index 43051478d..25a054f02 100644 --- a/docs/articles/nunit/writing-tests/attributes/testof.md +++ b/docs/articles/nunit/writing-tests/attributes/testof.md @@ -1,33 +1,61 @@ +--- +uid: attribute-testof +--- + # TestOf -The `TestOf` attribute adds information about the class that is being tested. It can be applied to test fixtures and to tests. +`TestOfAttribute` is used to specify the class or type that a test fixture or test method is testing. This metadata helps document the relationship between tests and the code under test, and can be used by test runners and reporting tools to organize test results. -The constructor takes the string name or the type of the class being tested. TestOf can also be specified on -a TestFixture or Test attribute. +## Constructors ```csharp -[TestFixture] -[TestOf(typeof(MyClass))] -public class MyTests -{ - [Test] - public void Test1() { /* ... */ } - - [Test] - [TestOf(nameof(MySubClass))] - public void Test2() { /* ... */ } -} +TestOfAttribute(Type type) +TestOfAttribute(string typeName) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `type` | `Type` | The type that is being tested. The full type name is stored. | +| `typeName` | `string` | The name of the type that is being tested. | + +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ✅ | ✅ | ✅ | +## Alternative Syntax + +`TestOf` can also be specified as a named parameter on `[TestFixture]` or `[Test]` attributes: + +```csharp [TestFixture(TestOf = typeof(MyClass))] -public class MyOtherTests -{ - [Test] - public void Test1() { /* ... */ } - - [Test(TestOf = typeof(MySubClass))] - public void Test2() { /* ... */ } -} +[Test(TestOf = typeof(MyClass))] ``` -> [!NOTE] -> You can currently only have one TestOf attribute per fixture or test. +## Examples + +### Using the Attribute + +[!code-csharp[TestOfBasic](~/snippets/Snippets.NUnit/Attributes/TestOfAttributeExamples.cs#TestOfBasic)] + +### Using String Names + +[!code-csharp[TestOfString](~/snippets/Snippets.NUnit/Attributes/TestOfAttributeExamples.cs#TestOfString)] + +### Using Named Parameter Syntax + +[!code-csharp[TestOfNamedParameter](~/snippets/Snippets.NUnit/Attributes/TestOfAttributeExamples.cs#TestOfNamedParameter)] + +## Notes + +1. This attribute inherits from `PropertyAttribute` and sets the `TestOf` property with the full type name. +2. Using `typeof()` is preferred over string names as it provides compile-time type checking. +3. For string names, consider using `nameof()` for compile-time safety when the type is accessible. +4. Multiple `TestOf` attributes can be applied to the same element when a test covers multiple types. + +## See Also + +* [Property Attribute](xref:attribute-property) +* [Description Attribute](xref:attribute-description) +* [Category Attribute](xref:attribute-category) diff --git a/docs/articles/nunit/writing-tests/attributes/theory.md b/docs/articles/nunit/writing-tests/attributes/theory.md index 77c7a4c72..a0f9a122d 100644 --- a/docs/articles/nunit/writing-tests/attributes/theory.md +++ b/docs/articles/nunit/writing-tests/attributes/theory.md @@ -1,5 +1,5 @@ --- -uid: theoryattribute +uid: attribute-theory --- # Theory @@ -16,10 +16,26 @@ Tests](xref:parameterizedtests) at first glance. However, a Theory incorporates arguments and allows special processing for assumptions about that data. The key difference, though, is that theories make general statements and are more than just a set of examples. +## Constructor + +```csharp +TheoryAttribute(bool searchInDeclaringTypes = false) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `searchInDeclaringTypes` | `bool` | When `true`, datapoints are resolved on declaring types as well. Default is `false`. | + +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ✅ | ❌ | ❌ | + ## Data for Theories -The primary source of data for a **Theory** is the [Datapoint Attribute](datapoint.md) or [DatapointSource -Attribute](datapointsource.md). NUnit will use any class members of the required types, which are annotated with one of +The primary source of data for a **Theory** is the [Datapoint Attribute](xref:attribute-datapoint) or [DatapointSource +Attribute](xref:attribute-datapointsource). NUnit will use any class members of the required types, which are annotated with one of these attributes, to provide data for each parameter of the Theory. NUnit assembles the values for individual arguments combinatorially to provide test cases for the theory. @@ -109,6 +125,6 @@ public class TheorySampleTestsGeneric ## See also -* [Datapoint Attribute](datapoint.md) -* [DatapointSource Attribute](datapointsource.md) +* [Datapoint Attribute](xref:attribute-datapoint) +* [DatapointSource Attribute](xref:attribute-datapointsource) * [Parameterized Tests](xref:parameterizedtests) diff --git a/docs/articles/nunit/writing-tests/attributes/timeout.md b/docs/articles/nunit/writing-tests/attributes/timeout.md index d50620695..b7bf57c38 100644 --- a/docs/articles/nunit/writing-tests/attributes/timeout.md +++ b/docs/articles/nunit/writing-tests/attributes/timeout.md @@ -1,59 +1,75 @@ -# Timeout - -> [!NOTE] -> Starting from .NET 5, due to limitations in the runtime, the Timeout attribute works only partially. It will cancel the test -> for the purposes of test results reporting and scheduling of further tests, but the test's code will continue to run on the test's -> thread in the background. Starting from NUnit version 4.5, usage of Timeout attribute at all on .NET 5 or higher is reported -> as a failure. +--- +uid: attribute-timeout +--- -## Alternatives to the Timeout attribute for .NET 5 and above +# Timeout -If you want to cancel the Test in the same manner, use the [CancelAfter Attribute](./cancelafter.md). -It is cooperative cancelling, so your test needs to handle the CancellationToken. +> [!WARNING] +> This attribute is **obsolete on .NET 5 and later**. Starting from NUnit 4.5, usage of the Timeout attribute on .NET 5+ is reported as a test failure. Use [CancelAfter](xref:attribute-cancelafter) or [MaxTime](xref:attribute-maxtime) instead. -If you just want to be informed of tests that have run over an expected time, use the [MaxTime Attribute](./maxtime.md). +`TimeoutAttribute` is used to specify a timeout value in milliseconds for a test case. If the test runs longer than the specified time, it is immediately cancelled and reported as a failure. -If you want to cancel the whole test run use the `dotnet test --blame-hang-timeout `. -Any test that use more than the TIMESPAN will abort the run. -See [dotnet test docs](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-test-vstest). +## Constructor -### Reason +```csharp +TimeoutAttribute(int timeout) +``` -The Timeout attribute uses the `Thread.Abort()` method to kill tests. `Thread.Abort()` was removed in .NET 5 and replaced with -cooperative cancellation. +| Parameter | Type | Description | +|-----------|------|-------------| +| `timeout` | `int` | The timeout value in milliseconds. | -## For projects that target .NET Framework only +## Applies To -Normally, NUnit simply runs tests and waits for them to terminate -- the test is allowed to run indefinitely. For -certain kinds of tests, however, it may be desirable to specify a timeout value. +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ✅ | ✅ | ✅ | -The **TimeoutAttribute** is used to specify a timeout value in milliseconds for a test case. If the test case runs -longer than the time specified it is immediately cancelled and reported as a failure, with a message indicating that the -timeout was exceeded. +## .NET 5+ Alternatives -The specified timeout value covers the test setup and teardown as well as the test method itself. Before and after -actions may also be included, depending on where they were specified. Since the timeout may occur during any of these -execution phases, no guarantees can be made as to what will be run and any of these phases of execution may be -incomplete. If only used on a test, once a test has timed out, its teardown methods are executed. +Since `Thread.Abort()` was removed in .NET 5, this attribute no longer works reliably. Use these alternatives: -The attribute may also be specified on a fixture or assembly, in which case it indicates the default timeout for any -subordinate test cases. When using the console runner, it is also possible to specify a default timeout on the -command-line. +| Alternative | Description | +|-------------|-------------| +| [CancelAfter](xref:attribute-cancelafter) | Cooperative cancellation via `CancellationToken`. Your test must handle the token. | +| [MaxTime](xref:attribute-maxtime) | Reports tests that exceed expected time, but doesn't cancel them. | +| `dotnet test --blame-hang-timeout` | Aborts the entire test run if any test exceeds the timeout. | -## Example +## Example (.NET Framework Only) ```csharp [Test, Timeout(2000)] public void PotentiallyLongRunningTest() { - /* ... */ + // Test will be cancelled if it runs longer than 2 seconds +} + +[TestFixture, Timeout(5000)] +public class TimeSensitiveTests +{ + [Test] + public void Test1() + { + // Inherits 5 second timeout from fixture + } + + [Test, Timeout(1000)] + public void QuickTest() + { + // Overrides fixture timeout with 1 second + } } ``` -> [!NOTE] -> When debugging a unit test, i.e. when a debugger is attached to the process, then the timeout is not enforced. +## Notes + +1. **Deprecated on .NET 5+**: This attribute uses `Thread.Abort()`, which was removed in .NET 5. On .NET 5+, the test will be cancelled for reporting purposes, but the code continues running in the background. +2. The timeout covers setup, teardown, and the test method itself. Before/after actions may also be included depending on where they were specified. +3. When a timeout occurs during execution, no guarantees can be made about which phases completed. +4. When debugging (debugger attached), the timeout is not enforced. +5. A default timeout can also be set via the console runner's `--timeout` option or in a `.runsettings` file when using `dotnet test`. ## See Also -* [MaxTime Attribute](./maxtime.md) -* [CancelAfter Attribute](./cancelafter.md) +* [CancelAfter Attribute](xref:attribute-cancelafter) +* [MaxTime Attribute](xref:attribute-maxtime) diff --git a/docs/articles/nunit/writing-tests/attributes/unhandledexceptionhandling.md b/docs/articles/nunit/writing-tests/attributes/unhandledexceptionhandling.md index 9d2dc9079..3a87f7d5d 100644 --- a/docs/articles/nunit/writing-tests/attributes/unhandledexceptionhandling.md +++ b/docs/articles/nunit/writing-tests/attributes/unhandledexceptionhandling.md @@ -1,5 +1,5 @@ --- -uid: unhandledexceptionhandlingattribute +uid: attribute-unhandledexceptionhandling --- @@ -28,6 +28,12 @@ The attribute accepts an `UnhandledExceptionHandling` enum value: | `Ignore` | Unhandled exceptions are ignored and do not affect the test result | | `Default` | Same as `Error` | +## Applies To + +| Test Methods | Test Fixtures (Classes) | Assembly | +|--------------|--------------------------|----------| +| ✅ | ✅ | ✅ | + ## Basic Usage ### Error Mode (Default) @@ -154,5 +160,5 @@ When multiple levels specify the attribute, they are combined - each level's con ## See Also -* [Assert.Throws](../assertions/classic-assertions/Assert.Throws.md) -* [Assert.ThrowsAsync](../assertions/classic-assertions/Assert.ThrowsAsync.md) +* [Assert.Throws](xref:classic-assert-throws) +* [Assert.ThrowsAsync](xref:classic-assert-throws-async) diff --git a/docs/articles/nunit/writing-tests/attributes/values.md b/docs/articles/nunit/writing-tests/attributes/values.md index 47a20ddba..119485b94 100644 --- a/docs/articles/nunit/writing-tests/attributes/values.md +++ b/docs/articles/nunit/writing-tests/attributes/values.md @@ -1,23 +1,39 @@ --- -uid: valuesattribute +uid: attribute-values --- # Values -The `ValuesAttribute` is used to specify a set of values to be provided -for an individual parameter of a parameterized test method. Since -NUnit combines the data provided for each parameter into a set of -test cases, data must be provided for all parameters if it is -provided for any of them. +`ValuesAttribute` specifies literal values for a parameter of a parameterized test method. -By default, NUnit creates test cases from all possible combinations -of the data values provided on parameters - the combinatorial approach. -This default may be modified by use of specific attributes on the -test method itself. +By default, NUnit combines values across parameters combinatorially unless the method is marked with a different combining attribute. + +> [!NOTE] +> Once **any** parameter on a parameterized test specifies data (`[Values]`, `[Range]`, `[TestCase]`, …), **every** parameter must have a data source—the framework builds Cartesian products (or pairwise/sequential variants) across parameters. See [Parameterized Tests](xref:parameterizedtests). + +## Constructors + +```csharp +ValuesAttribute() +ValuesAttribute(object arg1) +ValuesAttribute(object arg1, object arg2) +ValuesAttribute(object arg1, object arg2, object arg3) +ValuesAttribute(params object[] args) +``` + +| Parameter | Type | Description | +|-----------|-------------|--------------------------------------------| +| `args` | `object[]` | Literal values supplied for the parameter. | + +## Applies To + +| Method Parameters | Test Methods | Test Fixtures (Classes) | Assembly | +|-------------------|--------------|--------------------------|----------| +| ✅ | ❌ | ❌ | ❌ | ## Example -[!code-csharp[ValuesAttributeExample](~/snippets/Snippets.NUnit/AttributeExamples.cs#ValuesAttributeExample)] +[!code-csharp[ValuesAttributeExample](~/snippets/Snippets.NUnit/Attributes/ValuesAttributeExamples.cs#ValuesAttributeExample)] The above test will be executed six times, as follows: @@ -30,24 +46,29 @@ MyTest(3, "A") MyTest(3, "B") ``` -## Values with Enum or Boolean +## Values with enum or bool -The values attribute works in a special way with Enums and Boolean parameters. +Parameterless **`[Values]`** expands enums and Booleans differently from other parameter types: When used without any arguments, the **[Values]** attribute on an enum parameter will automatically include all possible values of the enumeration. -[!code-csharp[ValuesAttributeEnumExample](~/snippets/Snippets.NUnit/AttributeExamples.cs#ValuesAttributeEnumExample)] +[!code-csharp[ValuesAttributeEnumExample](~/snippets/Snippets.NUnit/Attributes/ValuesAttributeExamples.cs#ValuesAttributeEnumExample)] + +For **`bool`**, the same mechanism supplies **`false`** then **`true`**. For **`bool?`**, NUnit adds **`null`** alongside those flags. For **`Nullable` enums**, every enum constant **plus null** are generated. + +[!code-csharp[ValuesAttributeBoolExample](~/snippets/Snippets.NUnit/Attributes/ValuesAttributeExamples.cs#ValuesAttributeBoolExample)] -There is the same support for Boolean values. Add the **[Values]** attribute to a bool -and the method will be run with true and false. +## Notes -[!code-csharp[ValuesAttributeBoolExample](~/snippets/Snippets.NUnit/AttributeExamples.cs#ValuesAttributeBoolExample)] +1. **`Values()`** with **no positional arguments** only auto-expands enums, Booleans (including **`bool?`**), and nullable enums; for other parameter types it yields nothing useful until you supply explicit values. +2. Use method-level `Combinatorial`, `Sequential`, or `Pairwise` to control how values from multiple parameters combine. +3. Values you pass to **`[Values(...)]`** are converted to the parameter type with the same attribute-argument conversion rules as **`[TestCase]`** (including **`Convert.ChangeType`** where applicable); see the opening note on **[TestCase](xref:attribute-testcase)**. ## See also -* [Range Attribute](range.md) -* [Random Attribute](random.md) -* [Sequential Attribute](sequential.md) -* [Combinatorial Attribute](combinatorial.md) -* [Pairwise Attribute](pairwise.md) +* [Range Attribute](xref:attribute-range) +* [Random Attribute](xref:attribute-random) +* [Sequential Attribute](xref:attribute-sequential) +* [Combinatorial Attribute](xref:attribute-combinatorial) +* [Pairwise Attribute](xref:attribute-pairwise) diff --git a/docs/articles/nunit/writing-tests/attributes/valuesource.md b/docs/articles/nunit/writing-tests/attributes/valuesource.md index 4b3c1ee26..a64e67b01 100644 --- a/docs/articles/nunit/writing-tests/attributes/valuesource.md +++ b/docs/articles/nunit/writing-tests/attributes/valuesource.md @@ -1,31 +1,39 @@ --- -uid: valuesource +uid: attribute-valuesource --- # ValueSource -**ValueSourceAttribute** is used on individual parameters of a test method to identify a named source for the argument -values to be supplied. The attribute has two public constructors. +`ValueSourceAttribute` is used on individual parameters of a test method to identify a named data source for argument values. + +## Constructors ```csharp -ValueSourceAttribute(Type sourceType, string sourceName); -ValueSourceAttribute(string sourceName); +ValueSourceAttribute(Type sourceType, string sourceName) +ValueSourceAttribute(string sourceName) ``` -If **sourceType** is specified, it represents the class that provides the data. +| Parameter | Type | Description | +|-----------|------|-------------| +| `sourceType` | `Type` | Type that provides the source member. Optional. | +| `sourceName` | `string` | Name of source field, property, or method. | + +## Applies To + +| Method Parameters | Test Methods | Test Fixtures (Classes) | Assembly | +|-------------------|--------------|--------------------------|----------| +| ✅ | ❌ | ❌ | ❌ | -If **sourceType** is not specified, the class containing the test method is used. +## Example -The **sourceName**, represents the name of the source that will provide the arguments. It should have the following -characteristics: +[!code-csharp[ValueSourceBasic](~/snippets/Snippets.NUnit/Attributes/ValueSourceAttributeExamples.cs#ValueSourceBasic)] -* It may be a field, a non-indexed property or a method taking no arguments. -* It must be a static member. -* It must return an `IEnumerable` or a type that implements `IEnumerable`. - * Methods may also return an `IAsyncEnumerable` or a type that implements `IAsyncEnumerable`. (_NUnit 4+_) - * Methods may be async by wrapping the return type in a `Task`. (_NUnit 3.14+_) -* The individual items returned from the enumerator must be compatible with the type of the parameter on which the - attribute appears. +## Source Requirements + +- Source may be a field, non-indexed property, or parameterless method. +- Source member must be static. +- Source must return `IEnumerable` (or async forms supported by NUnit). +- Returned items must be compatible with the annotated parameter type. ## Order of Execution @@ -48,3 +56,8 @@ If the data source is in the test fixture itself, the object is created using th fixture parameters provided on the **TestFixtureAttribute**, or the default constructor if no parameters were specified. Since this object is destroyed before the tests are run, no communication is possible between these two phases - or between different runs - except through the parameters themselves. + +## See Also + +* [TestCaseSource Attribute](xref:attribute-testcasesource) +* [Values Attribute](xref:attribute-values) diff --git a/docs/articles/nunit/writing-tests/constraints/EqualConstraint.md b/docs/articles/nunit/writing-tests/constraints/EqualConstraint.md index 600ab0d2f..907f3b358 100644 --- a/docs/articles/nunit/writing-tests/constraints/EqualConstraint.md +++ b/docs/articles/nunit/writing-tests/constraints/EqualConstraint.md @@ -509,5 +509,5 @@ But was: "89031" ## See also -* [Assert.AreEqual](../assertions/classic-assertions/Assert.AreEqual.md) -* [DefaultFloatingPointTolerance Attribute](../attributes/defaultfloatingpointtolerance.md) +* [Assert.AreEqual](xref:classic-assert-are-equal) +* [DefaultFloatingPointTolerance Attribute](xref:attribute-defaultfloatingpointtolerance) diff --git a/docs/articles/nunit/writing-tests/setup-teardown/SetUp-and-TearDown-Changes.md b/docs/articles/nunit/writing-tests/setup-teardown/SetUp-and-TearDown-Changes.md index af5517186..5ac6a370f 100644 --- a/docs/articles/nunit/writing-tests/setup-teardown/SetUp-and-TearDown-Changes.md +++ b/docs/articles/nunit/writing-tests/setup-teardown/SetUp-and-TearDown-Changes.md @@ -29,13 +29,13 @@ function clearer. ## Attribute Usage -* [SetUpAttribute](xref:setup-attribute) is now used exclusively for per-test setup. -* [TearDownAttribute](xref:teardown-attribute) is now used exclusively for per-test teardown. -* [OneTimeSetUpAttribute](xref:onetimesetup-attribute) is used for one-time setup per test-run. If you run _n_ tests, +* [SetUpAttribute](xref:attribute-setup) is now used exclusively for per-test setup. +* [TearDownAttribute](xref:attribute-teardown) is now used exclusively for per-test teardown. +* [OneTimeSetUpAttribute](xref:attribute-onetimesetup) is used for one-time setup per test-run. If you run _n_ tests, this event will only occur once. -* [OneTimeTearDownAttribute](xref:onetimeteardown-attribute) is used for one-time teardown per test-run. If you run _n_ +* [OneTimeTearDownAttribute](xref:attribute-onetimeteardown) is used for one-time teardown per test-run. If you run _n_ tests, this event will only occur once -* [SetUpFixtureAttribute](xref:setupfixture-attribute) continues to be used as at before, but with changed method +* [SetUpFixtureAttribute](xref:attribute-setupfixture) continues to be used as at before, but with changed method attributes. ### Attribute Usage by Fixture Type diff --git a/docs/articles/nunit/writing-tests/setup-teardown/index.md b/docs/articles/nunit/writing-tests/setup-teardown/index.md index 4a9b792c9..08fb8b043 100644 --- a/docs/articles/nunit/writing-tests/setup-teardown/index.md +++ b/docs/articles/nunit/writing-tests/setup-teardown/index.md @@ -2,13 +2,13 @@ ## Attribute Usage -* [SetUpAttribute](../attributes/setup.md) is now used exclusively for per-test setup. -* [TearDownAttribute](../attributes/teardown.md) is now used exclusively for per-test teardown. -* [OneTimeSetUpAttribute](../attributes/onetimesetup.md) is used for one-time setup per test-run. If you run _n_ tests, +* [SetUpAttribute](xref:attribute-setup) is now used exclusively for per-test setup. +* [TearDownAttribute](xref:attribute-teardown) is now used exclusively for per-test teardown. +* [OneTimeSetUpAttribute](xref:attribute-onetimesetup) is used for one-time setup per test-run. If you run _n_ tests, this event will only occur once. -* [OneTimeTearDownAttribute](../attributes/onetimeteardown.md) is used for one-time teardown per test-run. If you run +* [OneTimeTearDownAttribute](xref:attribute-onetimeteardown) is used for one-time teardown per test-run. If you run _n_ tests, this event will only occur once -* [SetUpFixtureAttribute](../attributes/setupfixture.md) continues to be used as at before, but with changed method +* [SetUpFixtureAttribute](xref:attribute-setupfixture) continues to be used as at before, but with changed method attributes. ### Attribute Usage by Fixture Type diff --git a/docs/articles/vs-test-adapter/Tips-And-Tricks.md b/docs/articles/vs-test-adapter/Tips-And-Tricks.md index 4c22862d7..3b8059746 100644 --- a/docs/articles/vs-test-adapter/Tips-And-Tricks.md +++ b/docs/articles/vs-test-adapter/Tips-And-Tricks.md @@ -115,7 +115,7 @@ see the [NUnit Tracelevel documentation](xref:internaltracespec) #### NumberOfTestWorkers -This setting is sent to NUnit to determine how [parallelization](xref:parallelizableattribute) should be performed. +This setting is sent to NUnit to determine how [parallelization](xref:attribute-parallelizable) should be performed. Note in particular that NUnit can either run directly or for parallel runs use queue of threads. Set to 0, it will run directly, set to 1 it will use a queue with a single thread. @@ -287,7 +287,7 @@ are: `Passed`, `Failed` or `Skipped`. If the attribute `NonTestAssembly` is added in an assembly, it will be skipped from further testing. If [RTD](https://devblogs.microsoft.com/dotnet/real-time-test-discovery/) is enabled in Visual Studio, the tests will be displayed, but running will skip them. -See explanation for the [NonTestAssembly Attribute](xref:nontestassembly), and [Issue explanation +See explanation for the [NonTestAssembly Attribute](xref:attribute-nontestassembly), and [Issue explanation here](https://github.com/nunit/nunit3-vs-adapter/issues/758). (From version 3.17.0) (Default changed to true from 4.0.0) diff --git a/docs/snippets/Snippets.NUnit/Attributes/ApartmentAttributeExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/ApartmentAttributeExamples.cs new file mode 100644 index 000000000..385d6308e --- /dev/null +++ b/docs/snippets/Snippets.NUnit/Attributes/ApartmentAttributeExamples.cs @@ -0,0 +1,42 @@ +using System.Threading; +using NUnit.Framework; + +namespace Snippets.NUnit.Attributes +{ + public class ApartmentAttributeExamples + { + #region ApartmentFixture + [TestFixture] + [Apartment(ApartmentState.STA)] + public class WinFormsTests + { + [Test] + public void TestRunsInSTA() + { + // All tests in this fixture run in the STA + Assert.That(Thread.CurrentThread.GetApartmentState(), Is.EqualTo(ApartmentState.STA)); + } + } + #endregion + + #region ApartmentMethod + [TestFixture] + public class MixedApartmentTests + { + [Test] + [Apartment(ApartmentState.STA)] + public void TestRequiringSTA() + { + Assert.That(Thread.CurrentThread.GetApartmentState(), Is.EqualTo(ApartmentState.STA)); + } + + [Test] + [Apartment(ApartmentState.MTA)] + public void TestRequiringMTA() + { + Assert.That(Thread.CurrentThread.GetApartmentState(), Is.EqualTo(ApartmentState.MTA)); + } + } + #endregion + } +} diff --git a/docs/snippets/Snippets.NUnit/Attributes/CancelAfterAttributeExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/CancelAfterAttributeExamples.cs index 5b3a5a536..3f34d8235 100644 --- a/docs/snippets/Snippets.NUnit/Attributes/CancelAfterAttributeExamples.cs +++ b/docs/snippets/Snippets.NUnit/Attributes/CancelAfterAttributeExamples.cs @@ -30,5 +30,16 @@ public void TestCaseSourceWithCancellationToken(int a, CancellationToken cancell } } #endregion + + #region TestCaseWithCancellationToken + [CancelAfter(2000)] + [TestCase("http://example.com/1")] + [TestCase("http://example.com/2")] + public async Task PotentiallyLongRunningTest(string uri, CancellationToken token) + { + await Task.Delay(10, token); + Assert.That(uri, Does.StartWith("http://")); + } + #endregion } } diff --git a/docs/snippets/Snippets.NUnit/Attributes/CombinatorialAttributeExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/CombinatorialAttributeExamples.cs new file mode 100644 index 000000000..7e5ef1864 --- /dev/null +++ b/docs/snippets/Snippets.NUnit/Attributes/CombinatorialAttributeExamples.cs @@ -0,0 +1,19 @@ +using NUnit.Framework; + +namespace Snippets.NUnit.Attributes +{ + public class CombinatorialAttributeExamples + { + #region CombinatorialBasic + [Test] + [Combinatorial] + public void MyTest( + [Values(1, 2, 3)] int x, + [Values("A", "B")] string s) + { + Assert.That(x, Is.GreaterThan(0)); + Assert.That(s, Is.Not.Null); + } + #endregion + } +} diff --git a/docs/snippets/Snippets.NUnit/Attributes/CultureAttributeExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/CultureAttributeExamples.cs new file mode 100644 index 000000000..5f41698fd --- /dev/null +++ b/docs/snippets/Snippets.NUnit/Attributes/CultureAttributeExamples.cs @@ -0,0 +1,96 @@ +using System.Globalization; +using NUnit.Framework; + +namespace Snippets.NUnit.Attributes +{ + public class CultureAttributeExamples + { + #region CultureInclude + [TestFixture] + public class FrenchOnlyTests + { + [Test] + [Culture("fr-FR")] + public void TestForFrenchCulture() + { + // This test only runs when current culture is fr-FR + Assert.That(CultureInfo.CurrentCulture.Name, Is.EqualTo("fr-FR")); + } + + [Test] + [Culture("fr-FR,fr-CA")] + public void TestForFrenchCultures() + { + // This test runs when current culture is fr-FR or fr-CA + Assert.That(CultureInfo.CurrentCulture.TwoLetterISOLanguageName, Is.EqualTo("fr")); + } + + [Test] + [Culture("fr")] + public void TestForAnyFrenchCulture() + { + // Using neutral culture matches any French variant (fr-FR, fr-CA, etc.) + Assert.That(CultureInfo.CurrentCulture.TwoLetterISOLanguageName, Is.EqualTo("fr")); + } + } + #endregion + + #region CultureExclude + [TestFixture] + public class ExcludeCultureTests + { + [Test] + [Culture(Exclude = "en")] + public void TestExcludingEnglish() + { + // This test runs on any culture EXCEPT English variants + Assert.That(CultureInfo.CurrentCulture.TwoLetterISOLanguageName, Is.Not.EqualTo("en")); + } + + [Test] + [Culture(Exclude = "en,de")] + public void TestExcludingEnglishAndGerman() + { + // This test is skipped when culture is English or German + var lang = CultureInfo.CurrentCulture.TwoLetterISOLanguageName; + Assert.That(lang, Is.Not.EqualTo("en").And.Not.EqualTo("de")); + } + } + #endregion + + #region CultureOnFixture + [TestFixture] + [Culture("en-US,en-GB")] + public class EnglishCultureTests + { + [Test] + public void Test1() + { + // All tests in this fixture only run on en-US or en-GB + Assert.That(CultureInfo.CurrentCulture.Name, + Is.EqualTo("en-US").Or.EqualTo("en-GB")); + } + + [Test] + public void Test2() + { + Assert.That(CultureInfo.CurrentCulture.TwoLetterISOLanguageName, Is.EqualTo("en")); + } + } + #endregion + + #region CultureWithReason + [TestFixture] + public class CultureWithReasonTests + { + [Test] + [Culture(Include = "ja-JP", Reason = "This test uses Japanese-specific date formatting")] + public void TestJapaneseDateFormat() + { + // The reason is shown when the test is skipped + Assert.That(CultureInfo.CurrentCulture.Name, Is.EqualTo("ja-JP")); + } + } + #endregion + } +} diff --git a/docs/snippets/Snippets.NUnit/Attributes/DatapointAttributeExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/DatapointAttributeExamples.cs new file mode 100644 index 000000000..00fd427fc --- /dev/null +++ b/docs/snippets/Snippets.NUnit/Attributes/DatapointAttributeExamples.cs @@ -0,0 +1,139 @@ +using System.Collections.Generic; +using NUnit.Framework; + +namespace Snippets.NUnit.Attributes +{ + public class DatapointAttributeExamples + { + #region DatapointBasic + [TestFixture] + public class SquareRootTests + { + // Individual datapoints for double arguments + [Datapoint] + public double Zero = 0; + + [Datapoint] + public double Positive = 1; + + [Datapoint] + public double Negative = -1; + + [Datapoint] + public double Max = double.MaxValue; + + [Theory] + public void SquareRootIsPositive(double value) + { + // NUnit will call this theory with each datapoint: 0, 1, -1, MaxValue + Assume.That(value >= 0); + Assert.That(Math.Sqrt(value), Is.GreaterThanOrEqualTo(0)); + } + } + #endregion + + #region DatapointWithEnum + public enum Color + { + Red, + Green, + Blue + } + + [TestFixture] + public class EnumTheoryTests + { + // No need to define datapoints for enums - NUnit supplies them automatically + [Theory] + public void ColorIsValid(Color color) + { + // NUnit automatically tests with Red, Green, and Blue + Assert.That(Enum.IsDefined(typeof(Color), color), Is.True); + } + + // Override automatic enum values with specific datapoints + [Datapoint] + public Color OnlyRed = Color.Red; + + [Theory] + public void TestOnlyRed(Color color) + { + // When datapoints are defined, automatic enum values are suppressed + Assert.That(color, Is.EqualTo(Color.Red)); + } + } + #endregion + + #region DatapointSource + [TestFixture] + public class PrimeNumberTests + { + // DatapointSource on a field returning an array + [DatapointSource] + public int[] SmallPrimes = { 2, 3, 5, 7, 11, 13 }; + + // DatapointSource on a property returning IEnumerable + [DatapointSource] + public IEnumerable MorePrimes + { + get + { + yield return 17; + yield return 19; + yield return 23; + } + } + + // DatapointSource on a method + [DatapointSource] + public int[] GetPrimesUnder100() + { + return new[] { 29, 31, 37, 41, 43, 47 }; + } + + [Theory] + public void PrimeIsOddOrTwo(int prime) + { + // NUnit combines all datapoint sources for int type + Assert.That(prime == 2 || prime % 2 != 0); + } + } + #endregion + + #region DatapointMultipleTypes + [TestFixture] + public class MultipleTypeTests + { + // Datapoints for string arguments + [Datapoint] + public string Empty = ""; + + [Datapoint] + public string NonEmpty = "hello"; + + // Datapoints for int arguments + [Datapoint] + public int Zero2 = 0; + + [Datapoint] + public int Positive2 = 42; + + [Theory] + public void StringLengthMatchesCount(string value) + { + // Only uses string datapoints + Assume.That(value, Is.Not.Null); + Assert.That(value.Length, Is.GreaterThanOrEqualTo(0)); + } + + [Theory] + public void IntIsNonNegative(int value) + { + // Only uses int datapoints + Assume.That(value >= 0); + Assert.That(value, Is.GreaterThanOrEqualTo(0)); + } + } + #endregion + } +} diff --git a/docs/snippets/Snippets.NUnit/Attributes/DefaultFloatingPointToleranceAttributeExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/DefaultFloatingPointToleranceAttributeExamples.cs new file mode 100644 index 000000000..654a73cd0 --- /dev/null +++ b/docs/snippets/Snippets.NUnit/Attributes/DefaultFloatingPointToleranceAttributeExamples.cs @@ -0,0 +1,40 @@ +using NUnit.Framework; + +namespace Snippets.NUnit.Attributes +{ + public class DefaultFloatingPointToleranceAttributeExamples + { + #region DefaultFloatingPointToleranceFixture + [TestFixture] + [DefaultFloatingPointTolerance(1)] + public class ToleranceFixtureTests + { + [Test] + public void ComparisonUsingFixtureDefaultTolerance() + { + Assert.That(1f, Is.EqualTo(2)); + } + + [Test] + public void ExplicitToleranceOverridesDefault() + { + Assert.That(1f, Is.EqualTo(1.2f).Within(0.3)); + } + } + #endregion + + #region DefaultFloatingPointToleranceMethodOverride + [TestFixture] + [DefaultFloatingPointTolerance(1)] + public class ToleranceMethodOverrideTests + { + [Test] + [DefaultFloatingPointTolerance(2)] + public void MethodToleranceOverridesFixtureTolerance() + { + Assert.That(2f, Is.EqualTo(4)); + } + } + #endregion + } +} diff --git a/docs/snippets/Snippets.NUnit/Attributes/DescriptionAttributeExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/DescriptionAttributeExamples.cs new file mode 100644 index 000000000..160d51706 --- /dev/null +++ b/docs/snippets/Snippets.NUnit/Attributes/DescriptionAttributeExamples.cs @@ -0,0 +1,52 @@ +using NUnit.Framework; + +namespace Snippets.NUnit.Attributes +{ + public class DescriptionAttributeExamples + { + #region DescriptionFixture + [TestFixture] + [Description("Tests for the shopping cart functionality")] + public class ShoppingCartTests + { + [Test] + public void AddItem_EmptyCart_ItemAdded() + { + Assert.Pass(); + } + } + #endregion + + #region DescriptionMethod + [TestFixture] + public class PaymentTests + { + [Test] + [Description("Verifies that valid credit card payments are processed successfully")] + public void ProcessPayment_ValidCard_ReturnsSuccess() + { + Assert.Pass(); + } + + [Test] + [Description("Ensures expired cards are rejected with appropriate error")] + public void ProcessPayment_ExpiredCard_ReturnsError() + { + Assert.Pass(); + } + } + #endregion + + #region DescriptionNamedParameter + [TestFixture(Description = "Integration tests for the user registration flow")] + public class UserRegistrationTests + { + [Test(Description = "Tests complete registration with all required fields")] + public void Register_AllFieldsValid_CreatesUser() + { + Assert.Pass(); + } + } + #endregion + } +} diff --git a/docs/snippets/Snippets.NUnit/Attributes/ExplicitAttributeExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/ExplicitAttributeExamples.cs new file mode 100644 index 000000000..53570a9a7 --- /dev/null +++ b/docs/snippets/Snippets.NUnit/Attributes/ExplicitAttributeExamples.cs @@ -0,0 +1,29 @@ +using NUnit.Framework; + +namespace Snippets.NUnit.Attributes +{ + public class ExplicitAttributeExamples + { + #region ExplicitFixtureExample + [TestFixture] + [Explicit("Manual verification fixture")] + public class ExplicitFixture + { + [Test] + public void FixtureExplicitTest() + { + Assert.Pass(); + } + } + #endregion + + #region ExplicitTestExample + [Test] + [Explicit("Run only when explicitly selected")] + public void ExplicitTest() + { + Assert.Pass(); + } + #endregion + } +} diff --git a/docs/snippets/Snippets.NUnit/Attributes/IgnoreAttributeExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/IgnoreAttributeExamples.cs new file mode 100644 index 000000000..9e7243bf1 --- /dev/null +++ b/docs/snippets/Snippets.NUnit/Attributes/IgnoreAttributeExamples.cs @@ -0,0 +1,38 @@ +using NUnit.Framework; + +namespace Snippets.NUnit.Attributes +{ + public class IgnoreAttributeExamples + { + #region IgnoreFixtureExample + [TestFixture] + [Ignore("Ignored until dependency issue is resolved")] + public class IgnoredFixture + { + [Test] + public void FixtureTest() + { + Assert.Fail("Ignored fixture should not execute."); + } + } + #endregion + + #region IgnoreTestExample + [Test] + [Ignore("Temporarily ignored while bug fix is in progress")] + public void IgnoredTest() + { + Assert.Fail("Ignored test should not execute."); + } + #endregion + + #region IgnoreUntilExample + [Test] + [Ignore("Waiting for external fix", Until = "2099-12-31 00:00:00Z")] + public void IgnoredUntilDate() + { + Assert.Fail("Test remains ignored until the specified date."); + } + #endregion + } +} diff --git a/docs/snippets/Snippets.NUnit/Attributes/MaxTimeAttributeExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/MaxTimeAttributeExamples.cs new file mode 100644 index 000000000..35b94111c --- /dev/null +++ b/docs/snippets/Snippets.NUnit/Attributes/MaxTimeAttributeExamples.cs @@ -0,0 +1,54 @@ +using System.Threading.Tasks; +using NUnit.Framework; + +namespace Snippets.NUnit.Attributes +{ + public class MaxTimeAttributeExamples + { + #region MaxTimeBasic + [TestFixture] + public class PerformanceTests + { + [Test] + [MaxTime(1000)] + public void OperationCompletesWithinOneSecond() + { + // This test fails if it takes more than 1000ms + var result = PerformQuickCalculation(); + Assert.That(result, Is.Not.Null); + } + + [Test] + [MaxTime(5000)] + public async Task AsyncOperationCompletesWithinFiveSeconds() + { + // MaxTime also works with async tests + await Task.Delay(100); + Assert.Pass(); + } + + private object PerformQuickCalculation() + { + // Simulate a quick calculation + return new object(); + } + } + #endregion + + #region MaxTimeVsAssertions + [TestFixture] + public class MaxTimeVsAssertionTests + { + [Test] + [MaxTime(2000)] + public void AssertionFailuresTakePrecedence() + { + // If both assertion fails AND time exceeds, + // the assertion failure is reported + var result = 2 + 2; + Assert.That(result, Is.EqualTo(4)); + } + } + #endregion + } +} diff --git a/docs/snippets/Snippets.NUnit/Attributes/NoTestsAttributeExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/NoTestsAttributeExamples.cs index 273f3834d..eafc0c988 100644 --- a/docs/snippets/Snippets.NUnit/Attributes/NoTestsAttributeExamples.cs +++ b/docs/snippets/Snippets.NUnit/Attributes/NoTestsAttributeExamples.cs @@ -1,3 +1,5 @@ +using System.Collections; +using System.Collections.Generic; using NUnit.Framework; using NUnit.Framework.Interfaces; @@ -83,4 +85,61 @@ public void VerifyNoTestsAttributeBehavior() } #endregion } + + #region NoTestsDynamicData + [TestFixture] + [NoTests(TestStatus.Skipped)] + public class DataDrivenTests + { + [TestCaseSource(typeof(ExternalDataSource))] + public void ProcessData(int recordId) + { + Assert.That(recordId, Is.GreaterThan(0)); + } + } + + public sealed class ExternalDataSource : IEnumerable + { + public IEnumerator GetEnumerator() + { + yield break; + } + } + #endregion + + [TestFixture] + public class NoTestsConditionalExamples + { + #region NoTestsConditionalExecution + [NoTests(TestStatus.Inconclusive)] + [TestCaseSource(nameof(GetPlatformSpecificCases))] + public void PlatformSpecificTest(string testCase) + { + Assert.That(testCase, Is.Not.Empty); + } + + private static IEnumerable GetPlatformSpecificCases() + { + yield break; + } + #endregion + } + + #region NoTestsFeatureFlag + [TestFixture] + [NoTests(TestStatus.Skipped)] + public class FeatureFlagTests + { + [TestCaseSource(nameof(GetEnabledFeatures))] + public void TestFeature(string featureName) + { + Assert.That(featureName, Is.Not.Empty); + } + + private static IEnumerable GetEnabledFeatures() + { + yield break; + } + } + #endregion } diff --git a/docs/snippets/Snippets.NUnit/Attributes/OneTimeSetUpAttributeExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/OneTimeSetUpAttributeExamples.cs new file mode 100644 index 000000000..f090cd32c --- /dev/null +++ b/docs/snippets/Snippets.NUnit/Attributes/OneTimeSetUpAttributeExamples.cs @@ -0,0 +1,24 @@ +using NUnit.Framework; + +namespace Snippets.NUnit.Attributes +{ + [TestFixture] + public class OneTimeSetUpAttributeExamples + { + private static int _sharedValue; + + #region OneTimeSetUpExample + [OneTimeSetUp] + public void Init() + { + _sharedValue = 42; + } + + [Test] + public void UsesInitializedState() + { + Assert.That(_sharedValue, Is.EqualTo(42)); + } + #endregion + } +} diff --git a/docs/snippets/Snippets.NUnit/Attributes/OneTimeTearDownAttributeExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/OneTimeTearDownAttributeExamples.cs new file mode 100644 index 000000000..5eef71f04 --- /dev/null +++ b/docs/snippets/Snippets.NUnit/Attributes/OneTimeTearDownAttributeExamples.cs @@ -0,0 +1,25 @@ +using NUnit.Framework; + +namespace Snippets.NUnit.Attributes +{ + [TestFixture] + public class OneTimeTearDownAttributeExamples + { + private static bool _hasRun; + + #region OneTimeTearDownExample + [Test] + public void Add() + { + _hasRun = true; + Assert.That(2 + 2, Is.EqualTo(4)); + } + + [OneTimeTearDown] + public void Cleanup() + { + Assert.That(_hasRun, Is.True); + } + #endregion + } +} diff --git a/docs/snippets/Snippets.NUnit/Attributes/OrderAttributeExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/OrderAttributeExamples.cs new file mode 100644 index 000000000..896c1c504 --- /dev/null +++ b/docs/snippets/Snippets.NUnit/Attributes/OrderAttributeExamples.cs @@ -0,0 +1,79 @@ +using NUnit.Framework; + +namespace Snippets.NUnit.Attributes +{ + public class OrderAttributeExamples + { + #region OrderBasic + [TestFixture] + public class OrderedTests + { + private static int _executionOrder; + + [OneTimeSetUp] + public void Setup() => _executionOrder = 0; + + [Test, Order(1)] + public void FirstTest() + { + _executionOrder++; + Assert.That(_executionOrder, Is.EqualTo(1)); + } + + [Test, Order(2)] + public void SecondTest() + { + _executionOrder++; + Assert.That(_executionOrder, Is.EqualTo(2)); + } + + [Test, Order(3)] + public void ThirdTest() + { + _executionOrder++; + Assert.That(_executionOrder, Is.EqualTo(3)); + } + + [Test] + public void UnorderedTest() + { + // Tests without Order run after all ordered tests + _executionOrder++; + Assert.That(_executionOrder, Is.EqualTo(4)); + } + } + #endregion + + #region OrderOnFixtures + [TestFixture, Order(1)] + public class FirstFixture + { + [Test] + public void Test() => Assert.Pass(); + } + + [TestFixture, Order(2)] + public class SecondFixture + { + [Test] + public void Test() => Assert.Pass(); + } + #endregion + + #region OrderWithGaps + [TestFixture] + public class OrderWithGapsTests + { + // Using gaps allows inserting tests later without renumbering + [Test, Order(10)] + public void InitializationTest() => Assert.Pass(); + + [Test, Order(20)] + public void ProcessingTest() => Assert.Pass(); + + [Test, Order(30)] + public void CleanupTest() => Assert.Pass(); + } + #endregion + } +} diff --git a/docs/snippets/Snippets.NUnit/Attributes/PairwiseAttributeExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/PairwiseAttributeExamples.cs new file mode 100644 index 000000000..8b9782575 --- /dev/null +++ b/docs/snippets/Snippets.NUnit/Attributes/PairwiseAttributeExamples.cs @@ -0,0 +1,21 @@ +using NUnit.Framework; + +namespace Snippets.NUnit.Attributes +{ + public class PairwiseAttributeExamples + { + #region PairwiseBasic + [Test] + [Pairwise] + public void MyTest( + [Values("a", "b", "c")] string a, + [Values("+", "-")] string b, + [Values("x", "y")] string c) + { + Assert.That(a, Is.Not.Null); + Assert.That(b, Is.Not.Null); + Assert.That(c, Is.Not.Null); + } + #endregion + } +} diff --git a/docs/snippets/Snippets.NUnit/Attributes/PlatformAttributeExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/PlatformAttributeExamples.cs new file mode 100644 index 000000000..20d22be60 --- /dev/null +++ b/docs/snippets/Snippets.NUnit/Attributes/PlatformAttributeExamples.cs @@ -0,0 +1,21 @@ +using NUnit.Framework; + +namespace Snippets.NUnit.Attributes +{ + public class PlatformAttributeExamples + { + #region PlatformAttributeExamples + [TestFixture] + [Platform("Win, Linux, MacOsX")] + public class PortableTests + { + [Test] + [Platform(Exclude = "Win98,WinME")] + public void SomeTest() + { + Assert.Pass("Runs only on supported platforms."); + } + } + #endregion + } +} diff --git a/docs/snippets/Snippets.NUnit/Attributes/PropertyAttributeExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/PropertyAttributeExamples.cs new file mode 100644 index 000000000..c25331228 --- /dev/null +++ b/docs/snippets/Snippets.NUnit/Attributes/PropertyAttributeExamples.cs @@ -0,0 +1,104 @@ +using System; +using NUnit.Framework; + +namespace Snippets.NUnit.Attributes +{ + public class PropertyAttributeExamples + { + #region BasicProperty + [TestFixture] + [Property("Location", 723)] + public class MathTests + { + [Test] + [Property("Severity", "Critical")] + public void AdditionTest() + { + Assert.That(2 + 2, Is.EqualTo(4)); + } + + [Test] + [Property("Severity", "Normal")] + [Property("Author", "John Doe")] + public void SubtractionTest() + { + // Multiple properties can be applied to a single test + Assert.That(5 - 3, Is.EqualTo(2)); + } + } + #endregion + + #region PropertyTypes + [TestFixture] + public class PropertyTypesTests + { + [Test] + [Property("StringProp", "value")] + [Property("IntProp", 42)] + [Property("DoubleProp", 3.14)] + public void TestWithDifferentPropertyTypes() + { + // Properties can be string, int, or double + Assert.Pass(); + } + } + #endregion + + #region AccessingProperties + [TestFixture] + public class AccessingPropertiesTests + { + [Test] + [Property("Priority", "High")] + public void TestAccessingProperty() + { + // Access properties via TestContext + var priority = TestContext.CurrentContext.Test.Properties.Get("Priority"); + Assert.That(priority, Is.EqualTo("High")); + } + } + #endregion + + #region CustomPropertyAttribute + // Define a custom severity level enum + public enum SeverityLevel + { + Critical, + Major, + Normal, + Minor + } + + // Create a custom property attribute + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)] + public class SeverityAttribute : PropertyAttribute + { + public SeverityAttribute(SeverityLevel level) + : base(level.ToString()) + { + } + } + + [TestFixture] + public class CustomPropertyTests + { + [Test] + [Severity(SeverityLevel.Critical)] + public void CriticalTest() + { + // The property name is "Severity" (derived from attribute name) + var severity = TestContext.CurrentContext.Test.Properties.Get("Severity"); + Assert.That(severity, Is.EqualTo("Critical")); + } + + [Test] + [Severity(SeverityLevel.Minor)] + public void MinorTest() + { + var severity = TestContext.CurrentContext.Test.Properties.Get("Severity"); + Assert.That(severity, Is.EqualTo("Minor")); + } + } + #endregion + } +} diff --git a/docs/snippets/Snippets.NUnit/Attributes/RandomAttributeExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/RandomAttributeExamples.cs new file mode 100644 index 000000000..b3400d726 --- /dev/null +++ b/docs/snippets/Snippets.NUnit/Attributes/RandomAttributeExamples.cs @@ -0,0 +1,92 @@ +using System; +using NUnit.Framework; + +namespace Snippets.NUnit.Attributes +{ + public class RandomAttributeExamples + { + #region RandomBasic + [TestFixture] + public class RandomBasicTests + { + [Test] + public void TestWithRandomInts([Random(5)] int value) + { + // Generates 5 random int values across the full int range + TestContext.Out.WriteLine($"Testing with value: {value}"); + Assert.That(value, Is.TypeOf()); + } + + [Test] + public void TestWithRandomDoubles([Random(3)] double value) + { + // Generates 3 random doubles between 0.0 and 1.0 + TestContext.Out.WriteLine($"Testing with value: {value}"); + Assert.That(value, Is.InRange(0.0, 1.0)); + } + } + #endregion + + #region RandomWithRange + [TestFixture] + public class RandomRangeTests + { + [Test] + public void TestWithIntRange([Random(1, 100, 5)] int value) + { + // Generates 5 random ints between 1 and 100 (exclusive) + Assert.That(value, Is.InRange(1, 99)); + } + + [Test] + public void TestWithDoubleRange([Random(-1.0, 1.0, 3)] double value) + { + // Generates 3 random doubles between -1.0 and 1.0 + Assert.That(value, Is.InRange(-1.0, 1.0)); + } + } + #endregion + + #region RandomDistinct + [TestFixture] + public class RandomDistinctTests + { + [Test] + public void TestWithDistinctValues([Random(1, 10, 5, Distinct = true)] int value) + { + // Generates 5 distinct random ints - no value will repeat + Assert.That(value, Is.InRange(1, 9)); + } + } + #endregion + + #region RandomGuid + [TestFixture] + public class RandomGuidTests + { + [Test] + public void TestWithRandomGuid([Random(3)] Guid value) + { + // Generates 3 random GUIDs + // Note: Guid does not support min/max range + Assert.That(value, Is.Not.EqualTo(Guid.Empty)); + } + } + #endregion + + #region RandomCombined + [TestFixture] + public class RandomCombinedTests + { + [Test] + public void TestWithMultipleRandomParams( + [Values(1, 2, 3)] int x, + [Random(-1.0, 1.0, 2)] double d) + { + // Creates 6 test cases: 3 x values * 2 random doubles + Assert.That(d, Is.InRange(-1.0, 1.0)); + } + } + #endregion + } +} diff --git a/docs/snippets/Snippets.NUnit/Attributes/RangeAttributeExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/RangeAttributeExamples.cs new file mode 100644 index 000000000..804cc98ed --- /dev/null +++ b/docs/snippets/Snippets.NUnit/Attributes/RangeAttributeExamples.cs @@ -0,0 +1,18 @@ +using NUnit.Framework; + +namespace Snippets.NUnit.Attributes +{ + public class RangeAttributeExamples + { + #region RangeAttributeExample + [Test] + public void MyTest( + [Values(1, 2, 3)] int x, + [Range(0.2, 0.6, 0.2)] double d) + { + Assert.That(x, Is.GreaterThan(0)); + Assert.That(d, Is.GreaterThan(0.0)); + } + #endregion + } +} diff --git a/docs/snippets/Snippets.NUnit/Attributes/RepeatAttributeExample.cs b/docs/snippets/Snippets.NUnit/Attributes/RepeatAttributeExample.cs index 8002c72c5..9ca0532b8 100644 --- a/docs/snippets/Snippets.NUnit/Attributes/RepeatAttributeExample.cs +++ b/docs/snippets/Snippets.NUnit/Attributes/RepeatAttributeExample.cs @@ -16,11 +16,10 @@ public void TestMethod1() private int count1; #region RepeatWithFaultAndOutputAttributeExample - [Test, Explicit("Issue 5031 must be fixed")] + [Test, Explicit("Demonstrates failure collection - intentionally fails on iterations 3 and 4")] [Repeat(5, StopOnFailure = false)] public void TestMethod2() { - TestContext.Out.WriteLine(count1); count1++; Assert.That(count1, Is.Not.EqualTo(3).And.Not.EqualTo(4)); diff --git a/docs/snippets/Snippets.NUnit/Attributes/RequiresThreadAttributeExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/RequiresThreadAttributeExamples.cs new file mode 100644 index 000000000..e42c8764e --- /dev/null +++ b/docs/snippets/Snippets.NUnit/Attributes/RequiresThreadAttributeExamples.cs @@ -0,0 +1,52 @@ +using System.Threading; +using NUnit.Framework; + +namespace Snippets.NUnit.Attributes +{ + public class RequiresThreadAttributeExamples + { + #region RequiresThreadFixture + [TestFixture] + [RequiresThread] + public class FixtureOnSeparateThread + { + [Test] + public void TestRunsOnSeparateThread() + { + // All tests in this fixture run on a dedicated thread + Assert.That(Thread.CurrentThread.IsThreadPoolThread, Is.False); + } + } + #endregion + + #region RequiresThreadMethod + [TestFixture] + public class MixedThreadTests + { + [Test] + [RequiresThread] + public void TestOnSeparateThread() + { + // This test runs on a separate thread + Assert.Pass(); + } + + [Test] + [RequiresThread(ApartmentState.STA)] + public void TestOnSTAThread() + { + // This test runs on a separate STA thread + Assert.That(Thread.CurrentThread.GetApartmentState(), Is.EqualTo(ApartmentState.STA)); + } + + [Test] + [RequiresThread(ApartmentState.MTA)] + public void TestOnMTAThread() + { + // This test runs on a separate MTA thread + Assert.That(Thread.CurrentThread.GetApartmentState(), Is.EqualTo(ApartmentState.MTA)); + } + } + #endregion + } +} diff --git a/docs/snippets/Snippets.NUnit/Attributes/SequentialAttributeExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/SequentialAttributeExamples.cs new file mode 100644 index 000000000..42896c896 --- /dev/null +++ b/docs/snippets/Snippets.NUnit/Attributes/SequentialAttributeExamples.cs @@ -0,0 +1,19 @@ +using NUnit.Framework; + +namespace Snippets.NUnit.Attributes +{ + public class SequentialAttributeExamples + { + #region SequentialBasic + [Test] + [Sequential] + public void MyTest( + [Values(1, 2, 3)] int x, + [Values("A", "B")] string s) + { + Assert.That(x, Is.GreaterThan(0)); + Assert.That(s is null || s.Length > 0); + } + #endregion + } +} diff --git a/docs/snippets/Snippets.NUnit/Attributes/SetCultureAttributeExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/SetCultureAttributeExamples.cs new file mode 100644 index 000000000..6dbaeeec1 --- /dev/null +++ b/docs/snippets/Snippets.NUnit/Attributes/SetCultureAttributeExamples.cs @@ -0,0 +1,84 @@ +using System; +using System.Globalization; +using NUnit.Framework; + +namespace Snippets.NUnit.Attributes +{ + public class SetCultureAttributeExamples + { + #region SetCultureOnFixture + [TestFixture] + [SetCulture("fr-FR")] + public class FrenchCultureTests + { + [Test] + public void TestDateFormatting() + { + // This test runs with French culture + var date = new DateTime(2024, 12, 25); + string formatted = date.ToString("d"); + + // French date format: dd/MM/yyyy + Assert.That(CultureInfo.CurrentCulture.Name, Is.EqualTo("fr-FR")); + } + + [Test] + public void TestNumberFormatting() + { + // French uses comma as decimal separator + double value = 1234.56; + string formatted = value.ToString("N2"); + + Assert.That(formatted, Does.Contain(",")); + } + } + #endregion + + #region SetCultureOnMethod + [TestFixture] + public class MixedCultureTests + { + [Test] + [SetCulture("de-DE")] + public void TestWithGermanCulture() + { + // Only this test runs with German culture + Assert.That(CultureInfo.CurrentCulture.Name, Is.EqualTo("de-DE")); + } + + [Test] + [SetCulture("ja-JP")] + public void TestWithJapaneseCulture() + { + // Only this test runs with Japanese culture + Assert.That(CultureInfo.CurrentCulture.Name, Is.EqualTo("ja-JP")); + } + + [Test] + public void TestWithDefaultCulture() + { + // This test runs with the system's default culture + Assert.That(CultureInfo.CurrentCulture, Is.Not.Null); + } + } + #endregion + + #region SetCultureWithSetUICulture + [TestFixture] + public class CombinedCultureTests + { + [Test] + [SetCulture("fr-FR")] + [SetUICulture("de-DE")] + public void TestWithDifferentCultures() + { + // Culture affects formatting (numbers, dates) + Assert.That(CultureInfo.CurrentCulture.Name, Is.EqualTo("fr-FR")); + + // UICulture affects resource loading (UI strings) + Assert.That(CultureInfo.CurrentUICulture.Name, Is.EqualTo("de-DE")); + } + } + #endregion + } +} diff --git a/docs/snippets/Snippets.NUnit/Attributes/SetUICultureAttributeExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/SetUICultureAttributeExamples.cs new file mode 100644 index 000000000..c0d4a8777 --- /dev/null +++ b/docs/snippets/Snippets.NUnit/Attributes/SetUICultureAttributeExamples.cs @@ -0,0 +1,83 @@ +using System.Globalization; +using NUnit.Framework; + +namespace Snippets.NUnit.Attributes +{ + public class SetUICultureAttributeExamples + { + #region SetUICultureOnFixture + [TestFixture] + [SetUICulture("fr-FR")] + public class FrenchUITests + { + private CultureInfo _originalCulture = null!; + + [OneTimeSetUp] + public void SaveOriginalCulture() + { + _originalCulture = CultureInfo.CurrentCulture; + } + + [Test] + public void TestResourceLoading() + { + // UI Culture affects resource manager lookups + // e.g., ResourceManager will look for French resources + Assert.That(CultureInfo.CurrentUICulture.Name, Is.EqualTo("fr-FR")); + } + + [Test] + public void CurrentCultureUnchanged() + { + // SetUICulture does NOT affect CurrentCulture + // Formatting operations use CurrentCulture, not CurrentUICulture + Assert.That(CultureInfo.CurrentUICulture.Name, Is.EqualTo("fr-FR")); + Assert.That(CultureInfo.CurrentCulture, Is.EqualTo(_originalCulture)); + } + } + #endregion + + #region SetUICultureOnMethod + [TestFixture] + public class MixedUITests + { + [Test] + [SetUICulture("de-DE")] + public void TestWithGermanUI() + { + Assert.That(CultureInfo.CurrentUICulture.Name, Is.EqualTo("de-DE")); + } + + [Test] + [SetUICulture("es-ES")] + public void TestWithSpanishUI() + { + Assert.That(CultureInfo.CurrentUICulture.Name, Is.EqualTo("es-ES")); + } + } + #endregion + + #region BothCultures + [TestFixture] + public class LocalizationTests + { + [Test] + [SetCulture("en-US")] + [SetUICulture("fr-FR")] + public void TestWithDifferentCultures() + { + // CurrentCulture: affects formatting (numbers, dates, currency) + Assert.That(CultureInfo.CurrentCulture.Name, Is.EqualTo("en-US")); + + // CurrentUICulture: affects resource loading (UI strings, messages) + Assert.That(CultureInfo.CurrentUICulture.Name, Is.EqualTo("fr-FR")); + + // Example: Format a number using CurrentCulture (en-US) + double price = 1234.56; + string formatted = price.ToString("C"); // Uses en-US currency format + Assert.That(formatted, Does.Contain("$")); + } + } + #endregion + } +} diff --git a/docs/snippets/Snippets.NUnit/Attributes/SetUpAttributeExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/SetUpAttributeExamples.cs new file mode 100644 index 000000000..a34087371 --- /dev/null +++ b/docs/snippets/Snippets.NUnit/Attributes/SetUpAttributeExamples.cs @@ -0,0 +1,24 @@ +using NUnit.Framework; + +namespace Snippets.NUnit.Attributes +{ + public class SetUpAttributeExamples + { + private int _counter; + + #region SetUpExample + [SetUp] + public void Init() + { + _counter = 0; + } + + [Test] + public void TestMethod() + { + _counter++; + Assert.That(_counter, Is.EqualTo(1)); + } + #endregion + } +} diff --git a/docs/snippets/Snippets.NUnit/Attributes/SetUpFixtureAttributeExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/SetUpFixtureAttributeExamples.cs new file mode 100644 index 000000000..d8b0c50ce --- /dev/null +++ b/docs/snippets/Snippets.NUnit/Attributes/SetUpFixtureAttributeExamples.cs @@ -0,0 +1,20 @@ +using NUnit.Framework; + +namespace Snippets.NUnit.Attributes.SampleNamespace +{ + #region SetUpFixtureExample + [SetUpFixture] + public class MySetUpClass + { + [OneTimeSetUp] + public void RunBeforeAnyTests() + { + } + + [OneTimeTearDown] + public void RunAfterAnyTests() + { + } + } + #endregion +} diff --git a/docs/snippets/Snippets.NUnit/Attributes/SingleThreadedAttributeExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/SingleThreadedAttributeExamples.cs new file mode 100644 index 000000000..63da219a6 --- /dev/null +++ b/docs/snippets/Snippets.NUnit/Attributes/SingleThreadedAttributeExamples.cs @@ -0,0 +1,53 @@ +using NUnit.Framework; + +namespace Snippets.NUnit.Attributes +{ + public class SingleThreadedAttributeExamples + { + #region SingleThreadedExample + [TestFixture] + [SingleThreaded] + public class DatabaseTests + { + private DbConnection? _connection; + + [OneTimeSetUp] + public void OneTimeSetUp() + { + // Connection created on this thread + _connection = new DbConnection(); + _connection.Open(); + } + + [Test] + public void Test1() + { + // Guaranteed to run on the same thread as OneTimeSetUp + _connection!.Execute("SELECT 1"); + } + + [Test] + public void Test2() + { + // Also runs on the same thread + _connection!.Execute("SELECT 2"); + } + + [OneTimeTearDown] + public void OneTimeTearDown() + { + // Runs on the same thread, safe to close connection + _connection?.Close(); + } + } + + // Simple stub classes for the example + private class DbConnection + { + public void Open() { } + public void Execute(string sql) { } + public void Close() { } + } + #endregion + } +} diff --git a/docs/snippets/Snippets.NUnit/Attributes/TearDownAttributeExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/TearDownAttributeExamples.cs new file mode 100644 index 000000000..624f73386 --- /dev/null +++ b/docs/snippets/Snippets.NUnit/Attributes/TearDownAttributeExamples.cs @@ -0,0 +1,30 @@ +using NUnit.Framework; + +namespace Snippets.NUnit.Attributes +{ + public class TearDownAttributeExamples + { + private bool _testRan; + + #region TearDownExample + [SetUp] + public void Init() + { + _testRan = false; + } + + [TearDown] + public void Cleanup() + { + Assert.That(_testRan, Is.True); + } + + [Test] + public void Add() + { + _testRan = true; + Assert.That(2 + 2, Is.EqualTo(4)); + } + #endregion + } +} diff --git a/docs/snippets/Snippets.NUnit/Attributes/TestAttributeExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/TestAttributeExamples.cs new file mode 100644 index 000000000..e0df81ff6 --- /dev/null +++ b/docs/snippets/Snippets.NUnit/Attributes/TestAttributeExamples.cs @@ -0,0 +1,70 @@ +using System.Threading.Tasks; +using NUnit.Framework; + +namespace Snippets.NUnit.Attributes; + +public class TestAttributeExamples +{ + #region BasicTest + [TestFixture] + public sealed class BasicTests + { + [Test] + public void Add() + { + Assert.That(2 + 2, Is.EqualTo(4)); + } + } + #endregion + + #region TestWithDescription + [TestFixture] + public sealed class DescriptionTests + { + [Test(Description = "My really cool test")] + public void Add_WithDescriptionOnAttribute() + { + Assert.That(2 + 2, Is.EqualTo(4)); + } + + [Test] + [Description("My really really cool test")] + public void Add_WithDescriptionAttribute() + { + Assert.That(2 + 2, Is.EqualTo(4)); + } + } + #endregion + + #region AsyncTest + [TestFixture] + public sealed class AsyncTests + { + [Test] + public async Task AddAsync() + { + await Task.Delay(1); + Assert.That(2 + 2, Is.EqualTo(4)); + } + } + #endregion + + #region ExpectedResultTest + [TestFixture] + public sealed class ExpectedResultTests + { + [Test(ExpectedResult = 4)] + public int TestAdd() + { + return 2 + 2; + } + + [Test(ExpectedResult = 4)] + public async Task TestAddAsync() + { + await Task.Delay(1); + return 2 + 2; + } + } + #endregion +} diff --git a/docs/snippets/Snippets.NUnit/Attributes/TestCaseAttributeExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/TestCaseAttributeExamples.cs index 8bb2e38cc..d7b49bdff 100644 --- a/docs/snippets/Snippets.NUnit/Attributes/TestCaseAttributeExamples.cs +++ b/docs/snippets/Snippets.NUnit/Attributes/TestCaseAttributeExamples.cs @@ -1,4 +1,6 @@ -using NUnit.Framework; +using System; +using System.Text; +using NUnit.Framework; namespace Snippets.NUnit.Attributes { @@ -56,5 +58,81 @@ public void AddTestWithCategory(int a, int b) Assert.That(result, Is.GreaterThan(1)); } #endregion + + #region TestCaseWithDescriptionAuthorTestOf + [TestFixture] + public sealed class DescriptionAuthorTestOfExample + { + [TestCase(2, + ExpectedResult = 4, + Description = "Verify doubling for integer input", + Author = "Snippet Author", + TestOf = typeof(StringBuilder))] // System.Text (implicit usings) + public int DoublesCorrectly(int n) + { + return n * 2; + } + } + #endregion + + #region TestCaseWithPlatforms + [TestFixture] + public sealed class PlatformFilteringExample + { + /// Runs on all hosts; baseline case. + [TestCase(1)] + + /// Usually still runs—excludes Xbox moniker only (see Platform attribute docs for names). + [TestCase(2, ExcludePlatform = "XBox")] + + // IncludePlatform example (may skip on some hosts): [TestCase(3, IncludePlatform = "Net,Linux")] + public void PlatformAwareCases(int id) + { + Assert.That(id, Is.InRange(1, 2)); + } + } + #endregion + + #region TestCaseWithTestName + [TestFixture] + public sealed class CustomNamesExample + { + [TestCase(10, ExpectedResult = 20, TestName = "Doubling_Positive_Value({a})")] + [TestCase(-3, ExpectedResult = -6, TestName = "Doubling_Negative_Value({a})")] + public int DoubleForDisplay(int input) + { + return input * 2; + } + } + #endregion + + #region TestCaseWithIgnoreUntil + [TestFixture] + public sealed class IgnoreUntilExample + { + // Until requires IgnoreReason; expired dates revert to runnable (see Ignore attribute docs). + + [TestCase(99, IgnoreReason = "Stale doc sample ignore window", Until = "2001-01-01 12:00:00Z")] + [TestCase(1)] + public void IgnoreExpires(int value) + { + Assert.That(value, Is.Positive); + } + } + #endregion + + #region TestCaseWithTypeArgs + [TestFixture] + public sealed class TypeArgsRuntimeExample + { + [TestCase(42, TypeArgs = new[] { typeof(int) })] + [TestCase("sample", TypeArgs = new[] { typeof(string) })] + public void GenericViaTypeArgs(T payload) + { + Assert.That(payload, Is.Not.Null); + Assert.That(typeof(T), Is.EqualTo(payload!.GetType())); + } + } + #endregion } } diff --git a/docs/snippets/Snippets.NUnit/Attributes/TestCaseGenericExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/TestCaseGenericExamples.cs index 2ba6f9c36..22fc9bcf8 100644 --- a/docs/snippets/Snippets.NUnit/Attributes/TestCaseGenericExamples.cs +++ b/docs/snippets/Snippets.NUnit/Attributes/TestCaseGenericExamples.cs @@ -1,3 +1,4 @@ +using System; using NUnit.Framework; namespace Snippets.NUnit.Attributes @@ -77,5 +78,27 @@ public void CompileTimeSafeTest(T value) Assert.That(value, Is.InstanceOf()); } #endregion + + #region TypeArgsComparedToGenericAttribute + [TestFixture] + public sealed class TypeArgsVsCompileTimeGeneric + { + /// Specify generic arguments at runtime (TypeArgs). Works on .NET Framework. + [TestCase(42, TypeArgs = new Type[] { typeof(int) })] + [TestCase("literal", TypeArgs = new Type[] { typeof(string) })] + public void ViaTypeArgs(T value) + { + Assert.That(value, Is.InstanceOf()); + } + + /// Prefer on .NET 6+ where generic attributes are available (NUnit 4.6+). + [TestCase(2112)] + [TestCase(42.42)] + public void ViaGenericAttribute(T sample) + { + Assert.That(sample, Is.InstanceOf()); + } + } + #endregion } } diff --git a/docs/snippets/Snippets.NUnit/Attributes/TestOfAttributeExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/TestOfAttributeExamples.cs new file mode 100644 index 000000000..6c83a595c --- /dev/null +++ b/docs/snippets/Snippets.NUnit/Attributes/TestOfAttributeExamples.cs @@ -0,0 +1,70 @@ +using NUnit.Framework; + +namespace Snippets.NUnit.Attributes +{ + // Sample classes to test (for demonstration purposes) + public class Calculator + { + public int Add(int a, int b) => a + b; + } + + public class AdvancedCalculator : Calculator + { + public double SquareRoot(double value) => System.Math.Sqrt(value); + } + + public class TestOfAttributeExamples + { + #region TestOfBasic + [TestFixture] + [TestOf(typeof(Calculator))] + public class CalculatorTests + { + [Test] + public void Add_TwoPositiveNumbers_ReturnsSum() + { + var calculator = new Calculator(); + Assert.That(calculator.Add(2, 3), Is.EqualTo(5)); + } + + [Test] + [TestOf(typeof(AdvancedCalculator))] + public void SquareRoot_PositiveNumber_ReturnsCorrectResult() + { + // This specific test is for AdvancedCalculator + var calculator = new AdvancedCalculator(); + Assert.That(calculator.SquareRoot(4), Is.EqualTo(2.0)); + } + } + #endregion + + #region TestOfString + [TestFixture] + [TestOf("Snippets.NUnit.Attributes.Calculator")] + public class CalculatorTestsWithStringName + { + [Test] + [TestOf(nameof(AdvancedCalculator))] + public void TestUsingNameof() + { + // Using nameof() provides compile-time safety + var calculator = new AdvancedCalculator(); + Assert.That(calculator.Add(1, 1), Is.EqualTo(2)); + } + } + #endregion + + #region TestOfNamedParameter + [TestFixture(TestOf = typeof(Calculator))] + public class CalculatorTestsWithNamedParameter + { + [Test(TestOf = typeof(AdvancedCalculator))] + public void TestUsingNamedParameterSyntax() + { + var calculator = new AdvancedCalculator(); + Assert.That(calculator.SquareRoot(9), Is.EqualTo(3.0)); + } + } + #endregion + } +} diff --git a/docs/snippets/Snippets.NUnit/Attributes/ValueSourceAttributeExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/ValueSourceAttributeExamples.cs new file mode 100644 index 000000000..b4a17d50e --- /dev/null +++ b/docs/snippets/Snippets.NUnit/Attributes/ValueSourceAttributeExamples.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; +using NUnit.Framework; + +namespace Snippets.NUnit.Attributes +{ + public class ValueSourceAttributeExamples + { + private static readonly int[] Numbers = { 1, 2, 3 }; + + #region ValueSourceBasic + [Test] + public void TestUsingValueSource([ValueSource(nameof(Numbers))] int value) + { + Assert.That(value, Is.GreaterThan(0)); + } + #endregion + + public static IEnumerable Names() + { + yield return "Alice"; + yield return "Bob"; + } + } +} diff --git a/docs/snippets/Snippets.NUnit/Attributes/ValuesAttributeExamples.cs b/docs/snippets/Snippets.NUnit/Attributes/ValuesAttributeExamples.cs new file mode 100644 index 000000000..3db7baaf7 --- /dev/null +++ b/docs/snippets/Snippets.NUnit/Attributes/ValuesAttributeExamples.cs @@ -0,0 +1,39 @@ +using NUnit.Framework; + +namespace Snippets.NUnit.Attributes +{ + public class ValuesAttributeExamples + { + #region ValuesAttributeExample + [Test] + public void ValuesAttribute_BasicExample([Values(1, 2, 3)] int x, [Values("A", "B")] string s) + { + Assert.That(x, Is.GreaterThan(0)); + Assert.That(s, Is.Not.Null); + } + #endregion + + #region ValuesAttributeEnumExample + public enum MyEnumType + { + Value1, + Value2, + Value3 + } + + [Test] + public void ValuesAttribute_EnumExample([Values] MyEnumType myEnumArgument) + { + Assert.That(myEnumArgument, Is.TypeOf()); + } + #endregion + + #region ValuesAttributeBoolExample + [Test] + public void ValuesAttribute_BoolExample([Values] bool value) + { + Assert.That(value, Is.EqualTo(true).Or.EqualTo(false)); + } + #endregion + } +} diff --git a/docs/snippets/Snippets.NUnit/TestCaseDataExample.cs b/docs/snippets/Snippets.NUnit/TestCaseDataExample.cs index 81f8df0a0..82ec4ed46 100644 --- a/docs/snippets/Snippets.NUnit/TestCaseDataExample.cs +++ b/docs/snippets/Snippets.NUnit/TestCaseDataExample.cs @@ -1,11 +1,12 @@ -using System.Collections; +using System; +using System.Collections; +using System.Collections.Generic; using NUnit.Framework; namespace Snippets.NUnit; public class TestCaseDataExample { - #region TestCaseDataExample [TestFixture] public class MyTests @@ -48,4 +49,112 @@ private static IEnumerable ExplicitTypeArgsTestCases() } } #endregion + + #region GenericTestCaseDataExample + [TestFixture] + public class GenericTestCaseDataTests + { + [TestCaseSource(nameof(GenericTestCases))] + public Type GenericMethodWithExplicitType(T input) + { + return typeof(T); + } + + private static IEnumerable GenericTestCases() + { + // Using TestCaseData automatically sets TypeArgs to typeof(T) + // This ensures the generic method uses 'long' + yield return new TestCaseData(2L) + { + ExpectedResult = typeof(long) + }; + + // Another single type parameter example with TestCaseData + yield return new TestCaseData(42) + { + ExpectedResult = typeof(int) + }; + } + + [TestCaseSource(nameof(TwoTypeParameterCases))] + public void GenericMethodWithTwoTypes(T1 first, T2 second) + { + Assert.That(first, Is.TypeOf()); + Assert.That(second, Is.TypeOf()); + } + + private static IEnumerable TwoTypeParameterCases() + { + // TestCaseData sets TypeArgs = [typeof(T1), typeof(T2)] + yield return new TestCaseData("hello", 42); + yield return new TestCaseData(3.14, true); + } + } + #endregion + + #region IgnoreUntilExample + [TestFixture] + public class IgnoreUntilTests + { + [TestCaseSource(nameof(IgnoredTestCases))] + public void TestWithTemporaryIgnore(int value) + { + Assert.That(value, Is.Positive); + } + + private static IEnumerable IgnoredTestCases() + { + // This test case runs normally + yield return new TestCaseData(1); + + // This test case is ignored indefinitely + yield return new TestCaseData(2) + .Ignore("Known bug - see issue #123"); + + // This test case is ignored until the specified date + // After the date passes, the test will run automatically + yield return new TestCaseData(3) + .Ignore("Waiting for API v2 release") + .Until(new DateTimeOffset(2025, 6, 1, 0, 0, 0, TimeSpan.Zero)); + + // This test was ignored in the past - it now runs because the date has passed + yield return new TestCaseData(4) + .Ignore("Was waiting for feature X") + .Until(new DateTimeOffset(2020, 1, 1, 0, 0, 0, TimeSpan.Zero)); + } + } + #endregion + + #region SetArgDisplayNamesObjectExample + [TestFixture] + public class SetArgDisplayNamesObjectTests + { + [TestCaseSource(nameof(DisplayNameCases))] + public void TestWithCustomDisplayNames(Person person, int expectedAge) + { + Assert.That(person.Age, Is.EqualTo(expectedAge)); + } + + private static IEnumerable DisplayNameCases() + { + var john = new Person { Name = "John", Age = 30 }; + var jane = new Person { Name = "Jane", Age = 25 }; + + // SetArgDisplayNames with strings + yield return new TestCaseData(john, 30) + .SetArgDisplayNames("John Doe", "30"); + + // SetArgDisplayNames with objects - they are automatically formatted + // This is useful when you want the display name to match the object's ToString() + yield return new TestCaseData(jane, 25) + .SetArgDisplayNames(jane.Name, jane.Age); + } + + public class Person + { + public string Name { get; set; } = ""; + public int Age { get; set; } + } + } + #endregion } \ No newline at end of file diff --git a/docs/snippets/Snippets.NUnit/TestCaseSourceExamples.cs b/docs/snippets/Snippets.NUnit/TestCaseSourceExamples.cs index 190974afa..65def1b32 100644 --- a/docs/snippets/Snippets.NUnit/TestCaseSourceExamples.cs +++ b/docs/snippets/Snippets.NUnit/TestCaseSourceExamples.cs @@ -1,4 +1,5 @@ using System.Collections; +using System.Threading; using NUnit.Framework; using NUnit.Framework.Legacy; @@ -174,4 +175,121 @@ public class TestDataWrapper public TExp? Expected { get; set; } } #endregion + + #region TestCaseSourceWithCategory + [TestFixture] + public sealed class TestCaseSourceCategoryFixture + { + public static IEnumerable YieldTaggedCases() + { + yield return 1; + yield return 200; + } + + [TestCaseSource(nameof(YieldTaggedCases), Category = "DocSample,Smoke")] + public void EveryCaseFromSourceSharesCategoryTags(int magnitude) + { + Assert.That(magnitude, Is.Positive); + } + } + #endregion + + #region OptionalParameters + [TestFixture] + public class OptionalParametersFixture + { + [TestCaseSource(nameof(OptionalParameterCases))] + public void TestWithOptionalParameters(string first, string second = "default", int third = 42) + { + Assert.That(first, Is.Not.Null); + Assert.That(second, Is.Not.Null); + Assert.That(third, Is.GreaterThan(0)); + } + + private static IEnumerable OptionalParameterCases() + { + // Provide all three arguments + yield return new TestCaseData("a", "b", 100); + + // Provide only two arguments - third uses default value of 42 + yield return new TestCaseData("a", "b"); + + // Provide only one argument - second and third use defaults + yield return new TestCaseData("a"); + } + } + #endregion + + #region CancellationTokenSupport + [TestFixture] + public class CancellationTokenFixture + { + [TestCaseSource(nameof(TestCases))] + [CancelAfter(5000)] + public void TestWithCancellationToken(int value, CancellationToken cancellationToken) + { + // NUnit automatically provides the CancellationToken as the last parameter + // when [CancelAfter] is applied. The source only needs to provide the other arguments. + Assert.That(cancellationToken, Is.Not.EqualTo(default(CancellationToken))); + Assert.That(value, Is.Positive); + } + + [TestCaseSource(nameof(TestCases))] + [CancelAfter(5000)] + public void TestWithOptionalCancellationToken(int value, CancellationToken cancellationToken = default) + { + // CancellationToken can also have a default value + Assert.That(cancellationToken, Is.Not.EqualTo(default(CancellationToken))); + Assert.That(value, Is.Positive); + } + + private static IEnumerable TestCases() + { + // Note: Do NOT include CancellationToken in the test case data + // NUnit injects it automatically when [CancelAfter] is present + yield return new TestCaseData(1); + yield return new TestCaseData(2); + } + } + #endregion + + #region AsyncEnumerableSource + [TestFixture] + public class AsyncEnumerableSourceFixture + { + [TestCaseSource(nameof(AsyncTestCases))] + public async Task TestWithAsyncEnumerableSource(int expected, int actual) + { + await Task.Delay(10); // Simulate async work + Assert.That(actual, Is.EqualTo(expected)); + } + + // Source method returns IAsyncEnumerable (NUnit 4+) + private static async IAsyncEnumerable AsyncTestCases() + { + await Task.Delay(10); // Simulate async data fetching + yield return new TestCaseData(1, 1); + + await Task.Delay(10); + yield return new TestCaseData(42, 42); + } + + [TestCaseSource(nameof(TaskReturningSource))] + public void TestWithTaskReturningSource(string value) + { + Assert.That(value, Is.Not.Empty); + } + + // Source method returns Task (NUnit 3.14+) + private static async Task> TaskReturningSource() + { + await Task.Delay(10); // Simulate async data fetching + return new[] + { + new TestCaseData("first"), + new TestCaseData("second") + }; + } + } + #endregion } \ No newline at end of file