Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions docs/articles/nunit/writing-tests/attributes/testcasesource.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,23 @@ test case data.

[!code-csharp[OptionalParameters](~/snippets/Snippets.NUnit/TestCaseSourceExamples.cs#OptionalParameters)]

### Params arrays

When the last parameter of the test method is a `params` array, any arguments supplied by the source beyond the fixed
parameters are gathered into that array, just as they are for [TestCase](xref:attribute-testcase). A test case that
supplies no extra arguments gives an empty array, and a test case whose last argument is already an array of the right
type passes it through unchanged. (_NUnit 4.5+_)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should say something here or in the CancellationToken section below that these two don't mix.
We cannot declare a CancellationToken parameter after a params array.
Therefore if [CancelAfter] is used with a params array, the user needs to use TestContext.CurrentContext.CancellationToken instead.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I've captured this in the latest commit. Let me know if you agree.

[!code-csharp[ParamsArray](~/snippets/Snippets.NUnit/TestCaseSourceExamples.cs#ParamsArray)]

> [!NOTE]
> A `params` array must be the last parameter of the method, so a test that uses one cannot also declare the
> `CancellationToken` parameter that [CancelAfter](xref:attribute-cancelafter) injects (see
> [CancellationToken support](#cancellationtoken-support) below). When combining `[CancelAfter]` with a `params`
> array, read the token from `TestContext.CurrentContext.CancellationToken` instead.

[!code-csharp[ParamsArrayWithCancelAfter](~/snippets/Snippets.NUnit/TestCaseSourceExamples.cs#ParamsArrayWithCancelAfter)]

### CancellationToken support

When using `[CancelAfter]` with `TestCaseSource`, NUnit automatically injects a `CancellationToken` as the last
Expand All @@ -192,6 +209,9 @@ provides it automatically.

[!code-csharp[CancellationTokenSupport](~/snippets/Snippets.NUnit/TestCaseSourceExamples.cs#CancellationTokenSupport)]

Because the injected `CancellationToken` must be the last parameter, this cannot be combined with a
[`params` array](#params-arrays). In that case, use `TestContext.CurrentContext.CancellationToken` instead.

See [CancelAfter](xref:attribute-cancelafter) for more information on cancellation token handling.

## Test Case Construction
Expand Down
54 changes: 54 additions & 0 deletions docs/snippets/Snippets.NUnit/TestCaseSourceExamples.cs
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,60 @@ private static IEnumerable<TestCaseData> OptionalParameterCases()
}
#endregion

#region ParamsArray
[TestFixture]
public class ParamsArrayFixture
{
[TestCaseSource(nameof(ParamsArrayCases))]
public void TestWithParamsArray(string name, params int[] values)
{
Assert.That(name, Is.Not.Null);
Assert.That(values, Is.Not.Null);
Assert.That(values, Is.All.Positive);
}

private static IEnumerable<TestCaseData> ParamsArrayCases()
{
// Extra arguments are gathered into the params array: values = [1, 2, 3]
yield return new TestCaseData("three", 1, 2, 3);

// A single extra argument gives a one-element array: values = [1]
yield return new TestCaseData("one", 1);

// No extra arguments gives an empty array: values = []
yield return new TestCaseData("none");

// An array of the right type as the last argument is used as-is: values = [4, 5]
yield return new TestCaseData("array", new[] { 4, 5 });
}
}
#endregion

#region ParamsArrayWithCancelAfter
[TestFixture]
public class ParamsArrayWithCancelAfterFixture
{
[TestCaseSource(nameof(Cases))]
[CancelAfter(5000)]
public void TestWithParamsArrayAndCancelAfter(string name, params int[] values)
{
// A CancellationToken parameter cannot follow a params array,
// so read the token from the test context instead.
CancellationToken cancellationToken = TestContext.CurrentContext.CancellationToken;

cancellationToken.ThrowIfCancellationRequested();
Assert.That(name, Is.Not.Null);
Assert.That(values, Is.All.Positive);
}

private static IEnumerable<TestCaseData> Cases()
{
yield return new TestCaseData("three", 1, 2, 3);
yield return new TestCaseData("none");
}
}
#endregion

#region CancellationTokenSupport
[TestFixture]
public class CancellationTokenFixture
Expand Down
Loading