diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 000000000..cbde47d7c --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,13 @@ +{ + "permissions": { + "allow": [ + "Bash(dotnet build:*)", + "Bash(dotnet test:*)", + "Bash(docfx:*)", + "Bash(dir:*)", + "Bash(grep:*)" + ], + "deny": [], + "ask": [] + } +} \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..0a056d3b1 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,68 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Overview + +This is the NUnit documentation repository that serves content at . It's a DocFX-based static site generator that builds documentation from markdown files and generates API documentation from .NET assemblies. + +## Architecture + +- **docs/**: Main documentation content including articles, markdown files, and DocFX configuration +- **docs/docfx.json**: Primary DocFX configuration file that defines build settings, metadata, and site structure +- **docs/snippets/**: .NET solution (Snippets.sln) containing C# code snippets used in documentation +- **code-output/**: Directory where NUnit release assemblies are placed for API documentation generation +- **legacy/**: Legacy documentation content served as static resources +- **.devcontainer/**: Docker-based development environment with pre-configured tools + +## Development Commands + +### DevContainer/Codespaces (Recommended) + +- `build` - Build the documentation site using DocFX +- `serve` - Build and serve the site locally at +- `lint` - Run markdown linting using markdownlint-cli2 +- `spellcheck` - Run spell checking using cspell +- `snippets` - Build and test the code snippets solution +- `apidocs` - Download latest NUnit API documentation + +### Local Development (requires docfx installed) + +- `docfx docs/docfx.json` - Build the site +- `docfx docs/docfx.json --serve` - Build and serve locally +- `markdownlint-cli2 --config ".github/linters/.markdownlint.yml" "docs/**/*.md"` - Lint markdown +- `cspell --config cSpell.json "docs/**/*.md" --no-progress` - Spell check +- `dotnet test docs/snippets/Snippets.sln` - Test code snippets + +## Key Configuration Files + +- **docs/docfx.json**: DocFX build configuration, metadata generation, and site settings +- **cSpell.json**: Spell checker dictionary and configuration +- **.github/linters/.markdownlint.yml**: Markdown linting rules +- **.markdownlintrc**: Additional markdown lint configuration +- **docs/filterConfig.yml**: API documentation filtering rules + +## Documentation Structure + +- **docs/articles/**: Main documentation content organized by topic +- **docs/api/**: Generated API documentation (auto-generated from code-output assemblies) +- **docs/legacy/**: Legacy documentation served as static files +- **docs/images/**, **docs/css/**, **docs/js/**: Static assets +- **docs/toc.yml**: Main table of contents structure + +## Code Snippets + +The repository includes a .NET solution at `docs/snippets/Snippets.sln` containing: + +- **Snippets.NUnit**: NUnit framework code examples +- **Snippets.NUnitLite**: NUnit Lite framework examples + +Code snippets are tested as part of the build process to ensure documentation examples remain valid. + +## API Documentation Generation + +API docs are generated from NUnit release assemblies placed in the `code-output/` directory. The DevContainer automatically downloads the latest release, or assemblies can be manually extracted from NUnit GitHub releases. + +## Deployment + +The site is built and deployed via GitHub Actions to the `gh-pages` branch, which serves . 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 09c71e9fa..84c9a1004 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 @@ -17,9 +17,7 @@ ClassicAssert.AreEqual(object expected, object actual, The method overloads that compare two objects make special provision so that numeric values of different types compare as expected. This assert succeeds: -```csharp -ClassicAssert.AreEqual(5, 5.0); -``` +[!code-csharp[AreEqualExamples](~/snippets/Snippets.NUnit/ClassicAssertExamples.cs#AreEqualExamples)] ## Comparing Floating Point Values @@ -29,11 +27,7 @@ as equal. Special values are handled so that the following Asserts succeed: -```csharp -ClassicAssert.AreEqual(double.PositiveInfinity, double.PositiveInfinity); -ClassicAssert.AreEqual(double.NegativeInfinity, double.NegativeInfinity); -ClassicAssert.AreEqual(double.NaN, double.NaN); -``` +[!code-csharp[AreEqualExamples](~/snippets/Snippets.NUnit/ClassicAssertExamples.cs#AreEqualExamples)] ## Comparing Arrays and Collections 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 8c75a14c3..1d9117e46 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 @@ -15,9 +15,7 @@ ClassicAssert.IsTrue(bool condition, string message, params object[] params); You can also use **Assert.That** with a Boolean argument to achieve the same result. -```csharp -Assert.That(condition); -``` +[!code-csharp[TrueExamples](~/snippets/Snippets.NUnit/ClassicAssertExamples.cs#TrueExamples)] ## See Also diff --git a/docs/articles/nunit/writing-tests/attributes/category.md b/docs/articles/nunit/writing-tests/attributes/category.md index 6d00a7cb3..1d5cdb097 100644 --- a/docs/articles/nunit/writing-tests/attributes/category.md +++ b/docs/articles/nunit/writing-tests/attributes/category.md @@ -11,38 +11,11 @@ selected categories will be run. Those tests in categories that are not selected ## Test Fixture Syntax -```csharp -namespace NUnit.Tests -{ - using System; - using NUnit.Framework; - - [TestFixture] - [Category("LongRunning")] - public class LongRunningTests - { - // ... - } -} -``` +[!code-csharp[CategoryTestFixtureExample](~/snippets/Snippets.NUnit/AttributeExamples.cs#CategoryTestFixtureExample)] ## Test Syntax -```csharp -namespace NUnit.Tests -{ - using System; - using NUnit.Framework; - - [TestFixture] - public class SuccessTests - { - [Test] - [Category("Long")] - public void VeryLongTest() - { /* ... */ } -} -``` +[!code-csharp[CategoryTestExample](~/snippets/Snippets.NUnit/AttributeExamples.cs#CategoryTestExample)] ### Custom Category Attributes @@ -52,14 +25,4 @@ 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. -```csharp -[AttributeUsage(AttributeTargets.Method, AllowMultiple=false)] -public class CriticalAttribute : CategoryAttribute -{ } -``` - -```csharp -[Test, Critical] -public void MyTest() -{ /*...*/ } -``` +[!code-csharp[CustomCategoryAttribute](~/snippets/Snippets.NUnit/AttributeExamples.cs#CustomCategoryAttribute)] diff --git a/docs/articles/nunit/writing-tests/attributes/description.md b/docs/articles/nunit/writing-tests/attributes/description.md index a6736cea1..a9edcaf24 100644 --- a/docs/articles/nunit/writing-tests/attributes/description.md +++ b/docs/articles/nunit/writing-tests/attributes/description.md @@ -5,23 +5,7 @@ XML output file. ## Example -```csharp -[assembly: Description("Assembly description here")] - -namespace NUnit.Tests -{ - using System; - using NUnit.Framework; - - [TestFixture, Description("Fixture description here")] - public class SomeTests - { - [Test, Description("Test description here")] - public void OneTest() - { /* ... */ } - } -} -``` +[!code-csharp[DescriptionTestExample](~/snippets/Snippets.NUnit/AttributeExamples.cs#DescriptionTestExample)] > [!NOTE] > The Test and TestFixture attributes continue to support an optional Description property. The Description diff --git a/docs/articles/nunit/writing-tests/attributes/ignore.md b/docs/articles/nunit/writing-tests/attributes/ignore.md index 1ffba635e..86cbc8407 100644 --- a/docs/articles/nunit/writing-tests/attributes/ignore.md +++ b/docs/articles/nunit/writing-tests/attributes/ignore.md @@ -27,22 +27,7 @@ namespace NUnit.Tests ## Test Syntax -```csharp -namespace NUnit.Tests -{ - using System; - using NUnit.Framework; - - [TestFixture] - public class SuccessTests - { - [Test] - [Ignore("Ignore a test")] - public void IgnoredTest() - { /* ... */ } - } -} -``` +[!code-csharp[IgnoreTestExample](~/snippets/Snippets.NUnit/AttributeExamples.cs#IgnoreTestExample)] ## Ignore Until diff --git a/docs/articles/nunit/writing-tests/attributes/range.md b/docs/articles/nunit/writing-tests/attributes/range.md index 18fbe0285..b831a6360 100644 --- a/docs/articles/nunit/writing-tests/attributes/range.md +++ b/docs/articles/nunit/writing-tests/attributes/range.md @@ -29,15 +29,7 @@ public RangeAttribute(double from, double to, double step); The following test will be executed nine times. -```csharp -[Test] -public void MyTest( - [Values(1, 2, 3)] int x, - [Range(0.2, 0.6, 0.2)] double d) -{ - /* ... */ -} -``` +[!code-csharp[RangeAttributeExample](~/snippets/Snippets.NUnit/AttributeExamples.cs#RangeAttributeExample)] The MyTest method is called nine times, as follows: diff --git a/docs/articles/nunit/writing-tests/attributes/setup.md b/docs/articles/nunit/writing-tests/attributes/setup.md index 4dc6eacfc..e4aff2f22 100644 --- a/docs/articles/nunit/writing-tests/attributes/setup.md +++ b/docs/articles/nunit/writing-tests/attributes/setup.md @@ -14,26 +14,7 @@ If a SetUp method fails or throws an exception, the test is not executed and a f ## Example -```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() - { /* ... */ } - } -} -``` +[!code-csharp[SetUpTearDownExample](~/snippets/Snippets.NUnit/AttributeExamples.cs#SetUpTearDownExample)] ## Inheritance diff --git a/docs/articles/nunit/writing-tests/attributes/values.md b/docs/articles/nunit/writing-tests/attributes/values.md index d5000cdaa..47a20ddba 100644 --- a/docs/articles/nunit/writing-tests/attributes/values.md +++ b/docs/articles/nunit/writing-tests/attributes/values.md @@ -17,13 +17,7 @@ test method itself. ## Example -```csharp -[Test] -public void MyTest([Values(1, 2, 3)] int x, [Values("A", "B")] string s) -{ - /* ... */ -} -``` +[!code-csharp[ValuesAttributeExample](~/snippets/Snippets.NUnit/AttributeExamples.cs#ValuesAttributeExample)] The above test will be executed six times, as follows: @@ -43,24 +37,12 @@ The values attribute works in a special way with Enums and Boolean parameters. When used without any arguments, the **[Values]** attribute on an enum parameter will automatically include all possible values of the enumeration. -```csharp -[Test] -public void MyEnumTest([Values]MyEnumType myEnumArgument) -{ - //... -} -``` +[!code-csharp[ValuesAttributeEnumExample](~/snippets/Snippets.NUnit/AttributeExamples.cs#ValuesAttributeEnumExample)] 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. -```csharp -[Test] -public void MyBoolTest([Values]bool value) -{ - //... -} -``` +[!code-csharp[ValuesAttributeBoolExample](~/snippets/Snippets.NUnit/AttributeExamples.cs#ValuesAttributeBoolExample)] ## See also diff --git a/docs/articles/nunit/writing-tests/constraints/AndConstraint.md b/docs/articles/nunit/writing-tests/constraints/AndConstraint.md index 49ff82492..a294debe4 100644 --- a/docs/articles/nunit/writing-tests/constraints/AndConstraint.md +++ b/docs/articles/nunit/writing-tests/constraints/AndConstraint.md @@ -16,9 +16,7 @@ AndConstraint(Constraint left, Constraint right) ## Examples of Use -```csharp -Assert.That(2.3, Is.GreaterThan(2.0).And.LessThan(3.0)); -``` +[!code-csharp[AndConstraintExamples](~/snippets/Snippets.NUnit/ConstraintExamples.cs#AndConstraintExamples)] ## Evaluation Order and Precedence diff --git a/docs/articles/nunit/writing-tests/constraints/CollectionContainsConstraint.md b/docs/articles/nunit/writing-tests/constraints/CollectionContainsConstraint.md index ce898b0d6..c94518ac7 100644 --- a/docs/articles/nunit/writing-tests/constraints/CollectionContainsConstraint.md +++ b/docs/articles/nunit/writing-tests/constraints/CollectionContainsConstraint.md @@ -31,15 +31,7 @@ Does.Contain(object) ## Examples of Use -```csharp -int[] iarray = new int[] { 1, 2, 3 }; -string[] sarray = new string[] { "a", "b", "c" }; -Assert.That(iarray, Has.Member(3)); -Assert.That(sarray, Has.Member("b")); -Assert.That(sarray, Contains.Item("c")); -Assert.That(sarray, Has.No.Member("x")); -Assert.That(iarray, Does.Contain(3)); -``` +[!code-csharp[CollectionContainsExamples](~/snippets/Snippets.NUnit/ConstraintExamples.cs#CollectionContainsExamples)] ## Note diff --git a/docs/articles/nunit/writing-tests/constraints/DelayedConstraint.md b/docs/articles/nunit/writing-tests/constraints/DelayedConstraint.md index 320e6652e..e78f2308a 100644 --- a/docs/articles/nunit/writing-tests/constraints/DelayedConstraint.md +++ b/docs/articles/nunit/writing-tests/constraints/DelayedConstraint.md @@ -28,3 +28,7 @@ With NUnit 3.6, an enhanced syntax is available that allows expressing the delay ``` Only Minutes, Seconds and MilliSeconds (note capital-S) are accepted as time modifiers. The default is to use MilliSeconds. + +## Examples of Use + +[!code-csharp[DelayedConstraintExamples](~/snippets/Snippets.NUnit/ConstraintExamples.cs#DelayedConstraintExamples)] diff --git a/docs/articles/nunit/writing-tests/constraints/EmptyConstraint.md b/docs/articles/nunit/writing-tests/constraints/EmptyConstraint.md index 82ea5c24f..335a36c5e 100644 --- a/docs/articles/nunit/writing-tests/constraints/EmptyConstraint.md +++ b/docs/articles/nunit/writing-tests/constraints/EmptyConstraint.md @@ -16,11 +16,7 @@ Is.Empty ## Examples of Use -```csharp -Assert.That("", Is.Empty); -Assert.That(new Dictionary(), Is.Empty); -Assert.That(new List(), Is.Empty); -``` +[!code-csharp[EmptyConstraintExamples](~/snippets/Snippets.NUnit/ConstraintExamples.cs#EmptyConstraintExamples)] ## Notes diff --git a/docs/articles/nunit/writing-tests/constraints/EqualConstraint.md b/docs/articles/nunit/writing-tests/constraints/EqualConstraint.md index ee6a5480e..07130feca 100644 --- a/docs/articles/nunit/writing-tests/constraints/EqualConstraint.md +++ b/docs/articles/nunit/writing-tests/constraints/EqualConstraint.md @@ -58,15 +58,7 @@ Numerics are compared based on their values. Different types may be compared suc Using the **Within** modifier, numerics may be tested for equality within a fixed or percent tolerance. -```csharp -Assert.That(2 + 2, Is.EqualTo(4.0)); -Assert.That(2 + 2 == 4); -Assert.That(2 + 2, Is.Not.EqualTo(5)); -Assert.That(2 + 2 != 5); -Assert.That(5.0, Is.EqualTo(5)); -Assert.That(5.5, Is.EqualTo(5).Within(0.075)); -Assert.That(5.5, Is.EqualTo(5).Within(1.5).Percent); -``` +[!code-csharp[EqualConstraintNumerics](~/snippets/Snippets.NUnit/ConstraintExamples.cs#EqualConstraintNumerics)] ## Comparing Floating Point Values @@ -77,26 +69,14 @@ Floating-point values may be compared using a tolerance in "Units in the Last Pl numerical work, this is safer than a fixed tolerance because it automatically compensates for the added inaccuracy of larger numbers. -```csharp -Assert.That(2.1 + 1.2, Is.EqualTo(3.3).Within(.0005)); -Assert.That(double.PositiveInfinity, Is.EqualTo(double.PositiveInfinity)); -Assert.That(double.NegativeInfinity, Is.EqualTo(double.NegativeInfinity)); -Assert.That(double.NaN, Is.EqualTo(double.NaN)); -Assert.That(20000000000000004.0, Is.EqualTo(20000000000000000.0).Within(1).Ulps); -``` +[!code-csharp[EqualConstraintFloatingPoint](~/snippets/Snippets.NUnit/ConstraintExamples.cs#EqualConstraintFloatingPoint)] ## Comparing Strings String comparisons normally respect case. The `IgnoreCase` modifier causes the comparison to be case-insensitive. It may also be used when comparing arrays or collections of strings. -```csharp -Assert.That("Hello!", Is.Not.EqualTo("HELLO!")); -Assert.That("Hello!", Is.EqualTo("HELLO!").IgnoreCase); - -string[] expected = new string[] { "Hello", "World" }; -string[] actual = new string[] { "HELLO", "world" }; -``` +[!code-csharp[EqualConstraintStrings](~/snippets/Snippets.NUnit/ConstraintExamples.cs#EqualConstraintStrings)] Sometimes we need to compare strings irrespective of white space characters, e.g.: when comparing Json strings. This can be done with the `IgnoreWhiteSpace` modifier. diff --git a/docs/articles/nunit/writing-tests/constraints/ExactTypeConstraint.md b/docs/articles/nunit/writing-tests/constraints/ExactTypeConstraint.md index 39937afde..f9884d586 100644 --- a/docs/articles/nunit/writing-tests/constraints/ExactTypeConstraint.md +++ b/docs/articles/nunit/writing-tests/constraints/ExactTypeConstraint.md @@ -17,9 +17,4 @@ Is.TypeOf() ## Examples of Use -```csharp -Assert.That("Hello", Is.TypeOf(typeof(string))); -Assert.That("Hello", Is.Not.TypeOf(typeof(int))); - -Assert.That("World", Is.TypeOf()); -``` +[!code-csharp[TypeConstraintExamples](~/snippets/Snippets.NUnit/ConstraintExamples.cs#TypeConstraintExamples)] diff --git a/docs/articles/nunit/writing-tests/constraints/FileOrDirectoryExistsConstraint.md b/docs/articles/nunit/writing-tests/constraints/FileOrDirectoryExistsConstraint.md index 7f9935731..1a38e48c4 100644 --- a/docs/articles/nunit/writing-tests/constraints/FileOrDirectoryExistsConstraint.md +++ b/docs/articles/nunit/writing-tests/constraints/FileOrDirectoryExistsConstraint.md @@ -24,12 +24,4 @@ IgnoreFiles ## Examples of Use -```csharp -Assert.That(fileStr, Does.Exist); -Assert.That(dirStr, Does.Exist); -Assert.That(fileStr, Does.Not.Exist); -Assert.That(dirStr, Does.Not.Exist); - -Assert.That(new FileInfo(fileStr), Does.Exist); -Assert.That(new DirectoryInfo(dirStr), Does.Exist); -``` +[!code-csharp[FileConstraintExamples](~/snippets/Snippets.NUnit/ConstraintExamples.cs#FileConstraintExamples)] diff --git a/docs/articles/nunit/writing-tests/constraints/GreaterThanConstraint.md b/docs/articles/nunit/writing-tests/constraints/GreaterThanConstraint.md index 9b2a329c1..0f8859b03 100644 --- a/docs/articles/nunit/writing-tests/constraints/GreaterThanConstraint.md +++ b/docs/articles/nunit/writing-tests/constraints/GreaterThanConstraint.md @@ -26,9 +26,4 @@ Is.Positive // Equivalent to Is.GreaterThan(0) ## Examples of Use -```csharp -Assert.That(7, Is.GreaterThan(3)); -Assert.That(myOwnObject, Is.GreaterThan(theExpected).Using(myComparer)); -Assert.That(42, Is.Positive); -Assert.That(myDateTime, Is.GreaterThan(expectedDateTime).Within(TimeSpan.FromSeconds(1))) -``` +[!code-csharp[GreaterThanExamples](~/snippets/Snippets.NUnit/ConstraintExamples.cs#GreaterThanExamples)] diff --git a/docs/articles/nunit/writing-tests/constraints/InstanceOfTypeConstraint.md b/docs/articles/nunit/writing-tests/constraints/InstanceOfTypeConstraint.md index e4581e81f..984e7ebce 100644 --- a/docs/articles/nunit/writing-tests/constraints/InstanceOfTypeConstraint.md +++ b/docs/articles/nunit/writing-tests/constraints/InstanceOfTypeConstraint.md @@ -17,9 +17,4 @@ Is.InstanceOf() ## Examples of Use -```csharp -Assert.That("Hello", Is.InstanceOf(typeof(string))); -Assert.That(5, Is.Not.InstanceOf(typeof(string))); - -Assert.That(5, Is.Not.InstanceOf()); -``` +[!code-csharp[TypeConstraintExamples](~/snippets/Snippets.NUnit/ConstraintExamples.cs#TypeConstraintExamples)] diff --git a/docs/articles/nunit/writing-tests/constraints/LessThanConstraint.md b/docs/articles/nunit/writing-tests/constraints/LessThanConstraint.md index a05c2e355..7fa3f42b8 100644 --- a/docs/articles/nunit/writing-tests/constraints/LessThanConstraint.md +++ b/docs/articles/nunit/writing-tests/constraints/LessThanConstraint.md @@ -26,9 +26,4 @@ Is.Negative // Equivalent to Is.LessThan(0) ## Examples of Use -```csharp -Assert.That(3, Is.LessThan(7)); -Assert.That(myOwnObject, Is.LessThan(theExpected).Using(myComparer)); -Assert.That(-5, Is.Negative); -Assert.That(myDateTime, Is.LessThan(expectedDateTime).Within(TimeSpan.FromSeconds(1))) -``` +[!code-csharp[LessThanExamples](~/snippets/Snippets.NUnit/ConstraintExamples.cs#LessThanExamples)] diff --git a/docs/articles/nunit/writing-tests/constraints/NotConstraint.md b/docs/articles/nunit/writing-tests/constraints/NotConstraint.md index 41821ca82..5d87d1157 100644 --- a/docs/articles/nunit/writing-tests/constraints/NotConstraint.md +++ b/docs/articles/nunit/writing-tests/constraints/NotConstraint.md @@ -17,7 +17,4 @@ Is.Not... ## Examples of Use -```csharp -Assert.That(collection, Is.Not.Unique); -Assert.That(2 + 2, Is.Not.EqualTo(5)); -``` +[!code-csharp[NotConstraintExamples](~/snippets/Snippets.NUnit/ConstraintExamples.cs#PropertyConstraintExamples)] diff --git a/docs/articles/nunit/writing-tests/constraints/NullConstraint.md b/docs/articles/nunit/writing-tests/constraints/NullConstraint.md index b0534316f..3fee6ae6a 100644 --- a/docs/articles/nunit/writing-tests/constraints/NullConstraint.md +++ b/docs/articles/nunit/writing-tests/constraints/NullConstraint.md @@ -16,7 +16,4 @@ Is.Null ## Examples of Use -```csharp -Assert.That(anObject, Is.Null); -Assert.That(anObject, Is.Not.Null); -``` +[!code-csharp[NullConstraintExamples](~/snippets/Snippets.NUnit/ConstraintExamples.cs#NullConstraintExamples)] diff --git a/docs/articles/nunit/writing-tests/constraints/OrConstraint.md b/docs/articles/nunit/writing-tests/constraints/OrConstraint.md index 25c33a76d..69334542f 100644 --- a/docs/articles/nunit/writing-tests/constraints/OrConstraint.md +++ b/docs/articles/nunit/writing-tests/constraints/OrConstraint.md @@ -16,9 +16,7 @@ OrConstraint(Constraint left, Constraint right) ## Examples of Use -```csharp -Assert.That(3, Is.LessThan(5).Or.GreaterThan(10)); -``` +[!code-csharp[OrConstraintExamples](~/snippets/Snippets.NUnit/ConstraintExamples.cs#OrConstraintExamples)] ## Evaluation Order and Precedence diff --git a/docs/articles/nunit/writing-tests/constraints/PropertyConstraint.md b/docs/articles/nunit/writing-tests/constraints/PropertyConstraint.md index c26f74ac9..103fef947 100644 --- a/docs/articles/nunit/writing-tests/constraints/PropertyConstraint.md +++ b/docs/articles/nunit/writing-tests/constraints/PropertyConstraint.md @@ -17,11 +17,7 @@ Has.Property(string name)... // followed by further constraint syntax ## Examples of Use -```csharp -Assert.That(someObject, Has.Property("Version").EqualTo("2.0")); -Assert.That(collection, Has.Property("Count").GreaterThan(10)); -Assert.That(collection, Has.Count.GreaterThan(10); -``` +[!code-csharp[PropertyConstraintExamples](~/snippets/Snippets.NUnit/ConstraintExamples.cs#PropertyConstraintExamples)] As shown in the example, certain common properties are known to NUnit and may be tested using a shorter form. The following properties are supported: diff --git a/docs/articles/nunit/writing-tests/constraints/RangeConstraint.md b/docs/articles/nunit/writing-tests/constraints/RangeConstraint.md index 66b5e584d..b5008a481 100644 --- a/docs/articles/nunit/writing-tests/constraints/RangeConstraint.md +++ b/docs/articles/nunit/writing-tests/constraints/RangeConstraint.md @@ -24,10 +24,4 @@ Is.InRange(IComparable from, IComparable to) ## Examples of Use -```csharp -int[] iarray = new int[] { 1, 2, 3 }; - -Assert.That(42, Is.InRange(1, 100)); -Assert.That(iarray, Is.All.InRange(1, 3)); -Assert.That(myOwnObject, Is.InRange(lowExpected, highExpected).Using(myComparer)); -``` +[!code-csharp[RangeConstraintExamples](~/snippets/Snippets.NUnit/ConstraintExamples.cs#RangeConstraintExamples)] diff --git a/docs/articles/nunit/writing-tests/constraints/SubstringConstraint.md b/docs/articles/nunit/writing-tests/constraints/SubstringConstraint.md index 984d1c008..d09512376 100644 --- a/docs/articles/nunit/writing-tests/constraints/SubstringConstraint.md +++ b/docs/articles/nunit/writing-tests/constraints/SubstringConstraint.md @@ -22,10 +22,4 @@ Does.Contain(string expected) ## Examples of Use -```csharp -string phrase = "Make your tests fail before passing!"; - -Assert.That(phrase, Does.Contain("tests fail")); -Assert.That(phrase, Does.Not.Contain("tests pass")); -Assert.That(phrase, Does.Contain("make").IgnoreCase); -``` +[!code-csharp[StringConstraintExamples](~/snippets/Snippets.NUnit/ConstraintExamples.cs#StringConstraintExamples)] diff --git a/docs/articles/nunit/writing-tests/constraints/ThrowsConstraint.md b/docs/articles/nunit/writing-tests/constraints/ThrowsConstraint.md index 95438210b..00666ca45 100644 --- a/docs/articles/nunit/writing-tests/constraints/ThrowsConstraint.md +++ b/docs/articles/nunit/writing-tests/constraints/ThrowsConstraint.md @@ -38,16 +38,7 @@ Throws.InnerException ## Examples of Use -```csharp -Assert.That(SomeMethod, Throws.TypeOf()); -Assert.That(SomeMethod, Throws.Exception.TypeOf()); -Assert.That(SomeMethod, Throws.TypeOf() - .With.Property("Parameter").EqualTo("myParam")); -Assert.That(SomeMethod, Throws.ArgumentException); -Assert.That(SomeMethod, Throws.TargetInvocationException - .With.InnerException.TypeOf()); -Assert.That(() => { throw new ArgumentException(); }, Throws.ArgumentException); -``` +[!code-csharp[ThrowsConstraintExamples](~/snippets/Snippets.NUnit/ConstraintExamples.cs#ThrowsConstraintExamples)] ## Notes diff --git a/docs/articles/nunit/writing-tests/constraints/TrueConstraint.md b/docs/articles/nunit/writing-tests/constraints/TrueConstraint.md index f185ac404..1e0224559 100644 --- a/docs/articles/nunit/writing-tests/constraints/TrueConstraint.md +++ b/docs/articles/nunit/writing-tests/constraints/TrueConstraint.md @@ -16,6 +16,4 @@ Is.True ## Example of Use -```csharp -Assert.That(condition, Is.True); -``` +[!code-csharp[TrueConstraintExamples](~/snippets/Snippets.NUnit/ConstraintExamples.cs#TrueConstraintExamples)] diff --git a/docs/snippets/Snippets.NUnit/AttributeExamples.cs b/docs/snippets/Snippets.NUnit/AttributeExamples.cs new file mode 100644 index 000000000..f9a44f84c --- /dev/null +++ b/docs/snippets/Snippets.NUnit/AttributeExamples.cs @@ -0,0 +1,358 @@ +using NUnit.Framework; + +#pragma warning disable CA1822 +#pragma warning disable NUnit2045 +#pragma warning disable CS1998 + +namespace Snippets.NUnit; + +public class AttributeExamples +{ + #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 + + // ReSharper disable UnusedMember.Global + #region ValuesAttributeEnumExample + public enum MyEnumType + { + Value1, + Value2, + Value3 + } + + [Test] + public void ValuesAttribute_EnumExample([Values] MyEnumType myEnumArgument) + { + Assert.That(myEnumArgument, Is.TypeOf()); + } + #endregion + // ReSharper restore UnusedMember.Global + + // ReSharper disable RedundantBoolCompare +#pragma warning disable CS8794 // The input always matches the provided pattern. + #region ValuesAttributeBoolExample + [Test] + public void ValuesAttribute_BoolExample([Values] bool value) + { + // This test will run twice: once with true, once with false + Assert.That(value is true or false); + } + #endregion +#pragma warning restore CS8794 // The input always matches the provided pattern. + // ReSharper restore RedundantBoolCompare + + #region RangeAttributeExample + [Test] + public void RangeAttribute_Example( + [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 +} + +[TestFixture] +[Category("LongRunning")] +public class CategoryAttributeExamples +{ + #region CategoryTestFixtureExample + [Test] + public void Test_InLongRunningCategory() + { + Assert.Pass("This test is in the LongRunning category"); + } + #endregion + + #region CategoryTestExample + [Test] + [Category("Fast")] + public void FastTest() + { + Assert.Pass("This is a fast test"); + } + + [Test] + [Category("Slow")] + [Category("Database")] + public void SlowDatabaseTest() + { + Assert.Pass("This test has multiple categories"); + } + #endregion + + // ReSharper disable RedundantAttributeUsageProperty + // ReSharper disable MemberCanBePrivate.Global + // ReSharper disable RedundantTypeDeclarationBody + #region CustomCategoryAttribute + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] + public class CriticalAttribute : CategoryAttribute + { } + + [Test] + [Critical] + public void CriticalTest() + { + Assert.Pass("This test uses a custom category attribute"); + } + #endregion + // ReSharper restore RedundantAttributeUsageProperty + // ReSharper restore MemberCanBePrivate.Global + // ReSharper restore RedundantTypeDeclarationBody +} + +#region SetUpTearDownExample +[TestFixture] +public class SetupTeardownExamples +{ + private int _counter; + + [SetUp] + public void Init() + { + _counter = 0; + Console.WriteLine("SetUp method called before each test"); + } + [TearDown] + public void Cleanup() + { + Console.WriteLine("TearDown method called after each test"); + } + + [Test] + public void TestMethod1() + { + _counter++; + Assert.That(_counter, Is.EqualTo(1)); + } + + [Test] + public void TestMethod2() + { + _counter++; + Assert.That(_counter, Is.EqualTo(1)); + } +} +#endregion + +[TestFixture] +public class OneTimeSetupTeardownExamples +{ + private static int _staticCounter; + + #region OneTimeSetUpExample + [OneTimeSetUp] + public void OneTimeInit() + { + _staticCounter = 100; + Console.WriteLine("OneTimeSetUp called once before all tests in the fixture"); + } + #endregion + + #region OneTimeTearDownExample + [OneTimeTearDown] + public void OneTimeCleanup() + { + Console.WriteLine("OneTimeTearDown called once after all tests in the fixture"); + } + #endregion + + [Test] + public void Test1() + { + Assert.That(_staticCounter, Is.EqualTo(100)); + } + + [Test] + public void Test2() + { + Assert.That(_staticCounter, Is.EqualTo(100)); + } +} + +[TestFixture] +public class DescriptionAttributeExamples +{ + #region DescriptionTestFixtureExample + [Test] + [Description("This test validates the addition operation")] + public void Add_TwoNumbers_ReturnsSum() + { + Assert.That(2 + 2, Is.EqualTo(4)); + } + #endregion + + #region DescriptionTestExample + [Test] + [Description("This test should always pass")] + public void AlwaysPassingTest() + { + Assert.Pass("Test passed as expected"); + } + #endregion +} + +[TestFixture] +public class IgnoreAttributeExamples +{ + #region IgnoreTestExample + [Test] + [Ignore("Test is not ready yet")] + public void IgnoredTest() + { + Assert.Fail("This test is ignored and should not run"); + } + #endregion + + #region IgnoreWithReasonExample + [Test] + [Ignore("Waiting for bug fix #1234")] + public void TestWaitingForBugFix() + { + Assert.Fail("This test should not run"); + } + #endregion +} + +[TestFixture] +[Explicit("This fixture is for manual testing only")] +public class ExplicitAttributeExamples +{ + #region ExplicitTestExample + [Test] + [Explicit("Run this test manually when needed")] + public void ManualTest() + { + Assert.Pass("This test runs only when explicitly requested"); + } + #endregion + + [Test] + public void AnotherManualTest() + { + Assert.Pass("This test is explicit because the fixture is marked explicit"); + } +} + +[TestFixture] +public class TimeoutAttributeExamples +{ +#pragma warning disable CS0618 // Type or member is obsolete + #region TimeoutExample + [Test] + [Timeout(1000)] // 1 second timeout + public void FastTest() + { + Thread.Sleep(500); // This should pass as it's under 1 second + Assert.Pass(); + } + #endregion +#pragma warning restore CS0618 // Type or member is obsolete + +#pragma warning disable CS0618 // Type or member is obsolete + #region TimeoutWithAsyncExample + [Test] + [Timeout(2000)] // 2 second timeout + public async Task AsyncTestWithTimeout() + { + await Task.Delay(1000); // This should pass as it's under 2 seconds + Assert.Pass(); + } + #endregion +#pragma warning restore CS0618 // Type or member is obsolete +} + +// ReSharper disable RedundantDefaultMemberInitializer +#region RepeatExample +[TestFixture] +public class RepeatAttributeExamples +{ + private int _repeatCounter = 0; + + [Test] + [Repeat(3)] + public void RepeatedTest() + { + _repeatCounter++; + Console.WriteLine($"Repeat iteration: {_repeatCounter}"); + Assert.Pass(); + } +} +#endregion +// ReSharper restore RedundantDefaultMemberInitializer + +[TestFixture] +public class OrderAttributeExamples +{ + #region OrderExample + [Test, Order(1)] + public void FirstTest() + { + Console.WriteLine("This test should run first"); + Assert.Pass(); + } + + [Test, Order(2)] + public void SecondTest() + { + Console.WriteLine("This test should run second"); + Assert.Pass(); + } + + [Test] // No order specified, will run after ordered tests + public void UnorderedTest() + { + Console.WriteLine("This test has no specific order"); + Assert.Pass(); + } + #endregion +} + +[TestFixture] +public class TestOfAttributeExamples +{ + private class Calculator + { + public int Add(int a, int b) => a + b; + public int Subtract(int a, int b) => a - b; + } + + #region TestOfExample + [Test] + [TestOf(typeof(Calculator))] + public void Calculator_Add_ReturnsCorrectSum() + { + var calculator = new Calculator(); + Assert.That(calculator.Add(2, 3), Is.EqualTo(5)); + } + + [Test] + [TestOf(typeof(Calculator))] + public void Calculator_Subtract_ReturnsCorrectDifference() + { + var calculator = new Calculator(); + Assert.That(calculator.Subtract(5, 3), Is.EqualTo(2)); + } + #endregion +} + +[TestFixture] +public class PropertyAttributeExamples +{ + #region PropertyExample + [Test] + [Property("Author", "John Doe")] + [Property("Version", "1.0")] + public void TestWithProperties() + { + Assert.Pass("This test has custom properties"); + } + #endregion +} \ No newline at end of file diff --git a/docs/snippets/Snippets.NUnit/ClassicAssertExamples.cs b/docs/snippets/Snippets.NUnit/ClassicAssertExamples.cs new file mode 100644 index 000000000..1befb910d --- /dev/null +++ b/docs/snippets/Snippets.NUnit/ClassicAssertExamples.cs @@ -0,0 +1,304 @@ +using NUnit.Framework; +using NUnit.Framework.Legacy; +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; + +#pragma warning disable CA1822 +#pragma warning disable NUnit2045 +#pragma warning disable NUnit2005 + +namespace Snippets.NUnit; + +public class ClassicAssertExamples +{ + #region AreEqualExamples + [Test] + public void AreEqual_Examples() + { + // Comparing numerics of different types + ClassicAssert.AreEqual(5, 5.0); + + // Floating point special values + ClassicAssert.AreEqual(double.PositiveInfinity, double.PositiveInfinity); + ClassicAssert.AreEqual(double.NegativeInfinity, double.NegativeInfinity); + ClassicAssert.AreEqual(double.NaN, double.NaN); + + // Basic equality + ClassicAssert.AreEqual("expected", "expected"); + ClassicAssert.AreEqual(42, 42); + + // With tolerance for floating point + ClassicAssert.AreEqual(2.1 + 1.2, 3.3, 0.001); + } + #endregion + + #region AreNotEqualExamples + [Test] + public void AreNotEqual_Examples() + { + ClassicAssert.AreNotEqual(5, 3); + ClassicAssert.AreNotEqual("Hello", "World"); + ClassicAssert.AreNotEqual(null, "something"); + } + #endregion + + #region TrueExamples + [Test] + public void True_Examples() + { + ClassicAssert.True(2 + 2 == 4); + ClassicAssert.IsTrue(true); + ClassicAssert.True("Hello".StartsWith("H")); + + } + #endregion + + #region FalseExamples + [Test] + public void False_Examples() + { + ClassicAssert.False(2 + 2 == 5); + ClassicAssert.IsFalse(false); + ClassicAssert.False("Hello".StartsWith("X")); + } + #endregion + + #region NullExamples + [Test] + public void Null_Examples() + { + object obj = null; + ClassicAssert.Null(obj); + ClassicAssert.IsNull(obj); + + obj = "something"; + ClassicAssert.NotNull(obj); + ClassicAssert.IsNotNull(obj); + } + #endregion + + #region SameExamples + [Test] + public void Same_Examples() + { + object obj1 = new object(); + object obj2 = obj1; + object obj3 = new object(); + + ClassicAssert.AreSame(obj1, obj2); + ClassicAssert.AreNotSame(obj1, obj3); + } + #endregion + + #region GreaterExamples + [Test] + public void Greater_Examples() + { + ClassicAssert.Greater(7, 3); + ClassicAssert.Greater(3.5, 2.1); + ClassicAssert.Greater("b", "a"); + ClassicAssert.Greater(DateTime.Now, DateTime.Now.AddDays(-1)); + } + #endregion + + #region GreaterOrEqualExamples + [Test] + public void GreaterOrEqual_Examples() + { + ClassicAssert.GreaterOrEqual(7, 3); + ClassicAssert.GreaterOrEqual(7, 7); + ClassicAssert.GreaterOrEqual("b", "a"); + ClassicAssert.GreaterOrEqual("b", "b"); + } + #endregion + + #region LessExamples + [Test] + public void Less_Examples() + { + ClassicAssert.Less(3, 7); + ClassicAssert.Less(2.1, 3.5); + ClassicAssert.Less("a", "b"); + } + #endregion + + #region LessOrEqualExamples + [Test] + public void LessOrEqual_Examples() + { + ClassicAssert.LessOrEqual(3, 7); + ClassicAssert.LessOrEqual(7, 7); + ClassicAssert.LessOrEqual("a", "b"); + ClassicAssert.LessOrEqual("a", "a"); + } + #endregion + + #region ContainsExamples + [Test] + public void Contains_Examples() + { + var list = new List { 1, 2, 3, 4, 5 }; + ClassicAssert.Contains(3, list); + + var array = new string[] { "apple", "banana", "cherry" }; + ClassicAssert.Contains("banana", array); + } + #endregion + + #region PositiveNegativeZeroExamples + [Test] + public void PositiveNegativeZero_Examples() + { + ClassicAssert.Positive(5); + ClassicAssert.Positive(0.1); + + ClassicAssert.Negative(-5); + ClassicAssert.Negative(-0.1); + + ClassicAssert.Zero(0); + ClassicAssert.Zero(0.0); + + ClassicAssert.NotZero(5); + ClassicAssert.NotZero(-3); + } + #endregion + + #region NaNExamples + [Test] + public void NaN_Examples() + { + ClassicAssert.IsNaN(double.NaN); + ClassicAssert.IsNaN(float.NaN); + } + #endregion + + #region EmptyExamples + [Test] + public void Empty_Examples() + { + ClassicAssert.IsEmpty(""); + ClassicAssert.IsEmpty(new int[] { }); + ClassicAssert.IsEmpty(new List()); + + ClassicAssert.IsNotEmpty("Hello"); + ClassicAssert.IsNotEmpty(new int[] { 1, 2, 3 }); + ClassicAssert.IsNotEmpty(new List { "item" }); + } + #endregion + + #region InstanceOfExamples + [Test] + public void InstanceOf_Examples() + { + ClassicAssert.IsInstanceOf("Hello"); + ClassicAssert.IsInstanceOf(typeof(string), "Hello"); + ClassicAssert.IsInstanceOf("Hello"); + + ClassicAssert.IsNotInstanceOf("Hello"); + ClassicAssert.IsNotInstanceOf(typeof(int), "Hello"); + } + #endregion + + #region AssignableFromExamples + [Test] + public void AssignableFrom_Examples() + { + // object can be assigned FROM string (string is a subtype of object) + object obj = "Hello"; + ClassicAssert.IsAssignableFrom(obj); + ClassicAssert.IsAssignableFrom(typeof(string), obj); + + ClassicAssert.IsNotAssignableFrom("Hello"); + ClassicAssert.IsNotAssignableFrom(typeof(int), "Hello"); + } + #endregion +} + +public class CollectionAssertExamples +{ + #region CollectionAssertBasicExamples + [Test] + public void CollectionAssert_Basic_Examples() + { + var list1 = new int[] { 1, 2, 3 }; + var list2 = new int[] { 1, 2, 3 }; + var list3 = new int[] { 3, 2, 1 }; + var list4 = new int[] { 1, 2, 4 }; + + // Collections are equal (same order) + CollectionAssert.AreEqual(list1, list2); + + // Collections are equivalent (same items, any order) + CollectionAssert.AreEquivalent(list1, list3); + + // Collections are not equal + CollectionAssert.AreNotEqual(list1, list4); + + // Collections are not equivalent + CollectionAssert.AreNotEquivalent(list1, list4); + } + #endregion + + #region CollectionAssertContainsExamples + [Test] + public void CollectionAssert_Contains_Examples() + { + var list = new int[] { 1, 2, 3, 4, 5 }; + + CollectionAssert.Contains(list, 3); + CollectionAssert.DoesNotContain(list, 10); + } + #endregion + + #region CollectionAssertSubsetExamples + [Test] + public void CollectionAssert_Subset_Examples() + { + var superset = new int[] { 1, 2, 3, 4, 5 }; + var subset = new int[] { 2, 4 }; + var notSubset = new int[] { 1, 6 }; + + CollectionAssert.IsSubsetOf(subset, superset); + CollectionAssert.IsNotSubsetOf(notSubset, superset); + } + #endregion + + #region CollectionAssertEmptyExamples + [Test] + public void CollectionAssert_Empty_Examples() + { + var emptyList = new int[] { }; + var nonEmptyList = new int[] { 1, 2, 3 }; + + CollectionAssert.IsEmpty(emptyList); + CollectionAssert.IsNotEmpty(nonEmptyList); + } + #endregion + + #region CollectionAssertOrderedExamples + [Test] + public void CollectionAssert_Ordered_Examples() + { + var orderedList = new int[] { 1, 2, 3, 4, 5 }; + var reverseOrderedList = new int[] { 5, 4, 3, 2, 1 }; + + CollectionAssert.IsOrdered(orderedList); + CollectionAssert.IsOrdered(reverseOrderedList, Comparer.Create((x, y) => y.CompareTo(x))); + } + #endregion + + #region CollectionAssertItemTypeExamples + [Test] + public void CollectionAssert_ItemType_Examples() + { + var stringList = new string[] { "a", "b", "c" }; + var mixedList = new object[] { "string", 123, null }; + + CollectionAssert.AllItemsAreInstancesOfType(stringList, typeof(string)); + CollectionAssert.AllItemsAreNotNull(stringList); + CollectionAssert.AllItemsAreUnique(stringList); + } + #endregion +} \ No newline at end of file diff --git a/docs/snippets/Snippets.NUnit/ConstraintExamples.cs b/docs/snippets/Snippets.NUnit/ConstraintExamples.cs new file mode 100644 index 000000000..e61ab27a1 --- /dev/null +++ b/docs/snippets/Snippets.NUnit/ConstraintExamples.cs @@ -0,0 +1,270 @@ +using NUnit.Framework; + +#pragma warning disable CA1822 +#pragma warning disable NUnit2045 +#pragma warning disable CA2211 + +namespace Snippets.NUnit; + +public class ConstraintExamples +{ + #region EqualConstraintNumerics + [Test] + public void EqualConstraint_Numerics() + { + Assert.That(2 + 2, Is.EqualTo(4.0)); + Assert.That(2 + 2 == 4); + Assert.That(2 + 2, Is.Not.EqualTo(5)); + Assert.That(2 + 2 != 5); + Assert.That(5.0, Is.EqualTo(5)); + Assert.That(5.5, Is.EqualTo(5).Within(0.5)); + Assert.That(5.5, Is.EqualTo(5).Within(10).Percent); + } + #endregion + + #region EqualConstraintFloatingPoint + [Test] + public void EqualConstraint_FloatingPoint() + { + Assert.That(2.1 + 1.2, Is.EqualTo(3.3).Within(.0005)); + Assert.That(double.PositiveInfinity, Is.EqualTo(double.PositiveInfinity)); + Assert.That(double.NegativeInfinity, Is.EqualTo(double.NegativeInfinity)); + Assert.That(double.NaN, Is.EqualTo(double.NaN)); + Assert.That(20000000000000004.0, Is.EqualTo(20000000000000000.0).Within(1).Ulps); + } + #endregion + + #region EqualConstraintStrings + [Test] + public void EqualConstraint_Strings() + { + Assert.That("Hello!", Is.Not.EqualTo("HELLO!")); + Assert.That("Hello!", Is.EqualTo("HELLO!").IgnoreCase); + + string[] expected = ["Hello", "World"]; + string[] actual = ["HELLO", "world"]; + Assert.That(actual, Is.EqualTo(expected).IgnoreCase); + } + #endregion + + #region AndConstraintExamples + [Test] + public void AndConstraint_Examples() + { + Assert.That(2.3, Is.GreaterThan(2.0).And.LessThan(3.0)); + + int? i = 10; + Assert.That(i, Is.Not.Null.And.GreaterThan(9)); + } + #endregion + + #region CollectionContainsExamples + [Test] + public void CollectionContains_Examples() + { + int[] intArray = [1, 2, 3]; + string[] stringArray = ["a", "b", "c"]; + + Assert.That(intArray, Has.Member(3)); + Assert.That(stringArray, Has.Member("b")); + Assert.That(stringArray, Contains.Item("c")); + Assert.That(stringArray, Has.No.Member("x")); + Assert.That(intArray, Does.Contain(3)); + } + #endregion + + #region GreaterThanExamples + [Test] + public void GreaterThan_Examples() + { + Assert.That(7, Is.GreaterThan(3)); + Assert.That(42, Is.Positive); + + DateTime expectedDateTime = DateTime.Now.AddMinutes(-1); + DateTime myDateTime = DateTime.Now; + Assert.That(myDateTime, Is.GreaterThan(expectedDateTime).Within(TimeSpan.FromSeconds(1))); + } + #endregion + + #pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type. + #region NullConstraintExamples + [Test] + public void NullConstraint_Examples() + { + object anObject = null; + Assert.That(anObject, Is.Null); + + anObject = "something"; + Assert.That(anObject, Is.Not.Null); + } + #endregion + #pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type. + + #region LessThanExamples + [Test] + public void LessThan_Examples() + { + Assert.That(3, Is.LessThan(7)); + Assert.That(-5, Is.Negative); + } + #endregion + + #region StringConstraintExamples + [Test] + public void StringConstraint_Examples() + { + Assert.That("Hello World!", Does.StartWith("Hello")); + Assert.That("Hello World!", Does.EndWith("World!")); + Assert.That("Hello World!", Does.Contain("lo Wor")); + Assert.That("Hello World!", Does.Match("H.*!")); + } + #endregion + + #region TrueConstraintExamples + [Test] + public void TrueConstraint_Examples() + { + Assert.That(2 + 2 == 4, Is.True); + Assert.That(2 + 2 == 5, Is.False); + } + #endregion + + #region TypeConstraintExamples + [Test] + public void TypeConstraint_Examples() + { + Assert.That("Hello", Is.TypeOf()); + Assert.That("Hello", Is.TypeOf(typeof(string))); + Assert.That("Hello", Is.InstanceOf()); + Assert.That("Hello", Is.InstanceOf()); + Assert.That("Hello", Is.AssignableTo()); + } + #endregion + + #region RangeConstraintExamples + [Test] + public void RangeConstraint_Examples() + { + int[] intArray = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + Assert.That(5, Is.InRange(1, 10)); + Assert.That(42, Is.Not.InRange(1, 10)); + Assert.That(intArray, Has.All.InRange(1, 10)); + } + #endregion + + #region CollectionConstraintExamples + [Test] + public void CollectionConstraint_Examples() + { + int[] intArray = [1, 2, 3]; + string[] stringArray = ["a", "b", "c"]; + + Assert.That(intArray, Is.All.GreaterThan(0)); + Assert.That(stringArray, Is.All.InstanceOf()); + Assert.That(intArray, Has.Some.EqualTo(2)); + Assert.That(intArray, Has.None.EqualTo(4)); + Assert.That(intArray, Is.Unique); + Assert.That(new int[] {}, Is.Empty); + Assert.That(intArray, Has.Exactly(3).Items); + Assert.That(intArray, Has.Some.GreaterThan(2)); + } + #endregion + + #region FileConstraintExamples + [Test] + public void FileConstraint_Examples() + { + var tempFile = Path.GetTempFileName(); + File.WriteAllText(tempFile, "test content"); + + try + { + Assert.That(tempFile, Does.Exist); + Assert.That("nonexistent.txt", Does.Not.Exist); + } + finally + { + if (File.Exists(tempFile)) + File.Delete(tempFile); + } + } + #endregion + + // ReSharper disable once MemberCanBePrivate.Global + // ReSharper disable UnusedAutoPropertyAccessor.Global + #region PropertyConstraintExamples + public class Person + { + public string Name { get; set; } = ""; + public int Age { get; set; } + public string Email { get; set; } = ""; + } + + [Test] + public void PropertyConstraint_Examples() + { + var person = new Person { Name = "John", Age = 25, Email = "john@example.com" }; + + Assert.That(person, Has.Property("Name").EqualTo("John")); + Assert.That(person, Has.Property("Age").GreaterThan(18)); + Assert.That(person, Has.Property("Email").Contains("@")); + } + #endregion + // ReSharper restore UnusedAutoPropertyAccessor.Global + + #region EmptyConstraintExamples + [Test] + public void EmptyConstraint_Examples() + { + Assert.That("", Is.Empty); + Assert.That(new int[] {}, Is.Empty); + Assert.That(new List(), Is.Empty); + Assert.That("Hello", Is.Not.Empty); + } + #endregion + + #region OrConstraintExamples + [Test] + public void OrConstraint_Examples() + { + Assert.That(3, Is.LessThan(5).Or.GreaterThan(10)); + Assert.That(12, Is.LessThan(5).Or.GreaterThan(10)); + } + #endregion + + #region NotConstraintExamples + [Test] + public void NotConstraint_Examples() + { + Assert.That(42, Is.Not.EqualTo(99)); + Assert.That("Hello", Is.Not.Null); + Assert.That(new[] { 1, 2, 3 }, Is.Not.Empty); + } + #endregion + + #region ThrowsConstraintExamples + [Test] + public void ThrowsConstraint_Examples() + { + Assert.That(() => throw new ArgumentException(), Throws.ArgumentException); + Assert.That(() => throw new InvalidOperationException("test"), + Throws.InvalidOperationException.With.Message.EqualTo("test")); + Assert.That(() => { }, Throws.Nothing); + } + #endregion + + #region DelayedConstraintExamples + [Test] + public void DelayedConstraint_Examples() + { + bool flag = false; + Task.Run(async () => + { + await Task.Delay(100); + flag = true; + }); + + Assert.That(() => flag, Is.True.After(200).MilliSeconds); + } + #endregion +} \ No newline at end of file