Skip to content

Commit

Permalink
Updated docs on TestCaseSource (#792)
Browse files Browse the repository at this point in the history
  • Loading branch information
OsirisTerje authored Sep 21, 2023
1 parent 69f69bb commit a313455
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 6 deletions.
24 changes: 23 additions & 1 deletion docs/articles/nunit/writing-tests/attributes/testcasesource.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,28 @@ See the **Test Case Construction** section below for details.

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

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 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.

## Examples using TestCaseSource with Typed data and expected results

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 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.

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

It is also possible to use a generic wrapper (or any custom wrapper) for the testcase data and the expected result, as shown in the example below.

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

## Named Parameters

TestCaseSourceAttribute supports one named parameter:
Expand All @@ -88,7 +110,7 @@ the enumerator as follows:

* If it is an `object[]`, its members are used to provide
the arguments for the method. This is the approach taken in
the three examples above.
the three first examples above.
* If it is an array of some other type, NUnit can use it provided
that the arguments to the method are all of that type. For example,
the above examples could be modified to make the three nested arrays
Expand Down
9 changes: 5 additions & 4 deletions docs/snippets/Snippets.NUnit/Assumptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ namespace Snippets.NUnit
public class Assumptions
{
#region TestThatUsesAssume
[Test]
public void Number_Divided_By_Itself_Is1()
[TestCase(5)]
[TestCase(0)]
[TestCase(-5)]
public void Number_Divided_By_Itself_Is1(int numberToCheck)
{
var numberToCheck = 5;
var divisor = GetMatchingDivisor(numberToCheck);

Assume.That(divisor, Is.Not.EqualTo(0), () => "divisor must not zero in order for this test to be valid");
Assume.That(divisor, Is.Not.EqualTo(0), () => "divisor must not be zero in order for this test to be valid");

var result = numberToCheck / divisor;
Assert.That(result, Is.EqualTo(1));
Expand Down
57 changes: 56 additions & 1 deletion docs/snippets/Snippets.NUnit/TestCaseSourceExamples.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public void ShortNameWithEvenNumberOfCharacters(string name)
{
Assert.That(name.Length, Is.LessThan(15));

bool hasEvenNumOfCharacters = (name.Length % 2) == 0;
bool hasEvenNumOfCharacters = (name.Length % 2) == 0;
Assert.That(hasEvenNumOfCharacters, Is.True);
}

Expand Down Expand Up @@ -117,4 +117,59 @@ public void TestMethod(int num)
Assert.That(num % 2, Is.Zero);
}
#endregion

#region TypedValuesWithExpectedAsAnonymousTuple
public class TypedValuesWithExpectedAsAnonymousTuple
{
[TestCaseSource(nameof(TestCases))]
public void TestOfPersonAge((Person P, bool Expected) td)
{
var res = td.P.IsOldEnoughToBuyAlcohol();
Assert.That(res, Is.EqualTo(td.Expected));
}

public static IEnumerable<(Person, bool)> TestCases()
{
yield return (new Person { Name = "John", Age = 10 }, false);
yield return (new Person { Name = "Jane", Age = 30 }, true);
}
}

public class Person
{
public string Name { get; set; } = "";
public int Age { get; set; }

public bool IsOldEnoughToBuyAlcohol()
{
return Age >= 18;
}
}
#endregion

#region TypedValuesWithExpectedInWrapperClass
public class TypedValuesWithExpectedInWrapperClass
{


[TestCaseSource(nameof(TestCases))]
public void TestOfPersonAge(TestDataWrapper<Person, bool> td)
{
var res = td.Value?.IsOldEnoughToBuyAlcohol();
Assert.That(res, Is.EqualTo(td.Expected));
}

public static IEnumerable<TestDataWrapper<Person, bool>> TestCases()
{
yield return new TestDataWrapper<Person, bool> { Value = new Person { Name = "John", Age = 10 }, Expected = false };
yield return new TestDataWrapper<Person, bool> { Value = new Person { Name = "Jane", Age = 30 }, Expected = true };
}
}

public class TestDataWrapper<T, TExp>
{
public T? Value { get; set; }
public TExp? Expected { get; set; }
}
#endregion
}

0 comments on commit a313455

Please sign in to comment.