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
37 changes: 34 additions & 3 deletions src/TestFramework/TestFramework/Assertions/Assert.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,41 @@ private Assert()
/// </summary>
/// <remarks>
/// Users can use this to plug-in custom assertions through C# extension methods.
/// For instance, the signature of a custom assertion provider could be "public static void IsOfType&lt;T&gt;(this Assert assert, object obj)"
/// Users could then use a syntax similar to the default assertions which in this case is "Assert.That.IsOfType&lt;Dog&gt;(animal);"
/// More documentation is at "https://github.com/Microsoft/testfx/docs/README.md".
/// For instance, the signature of a custom assertion provider could be <c>public static void IsOfType&lt;T&gt;(this Assert assert, object obj)</c>
/// and the call-site would be <c>Assert.That.IsOfType&lt;Dog&gt;(animal);</c>.
/// For more information, see <see href="https://learn.microsoft.com/dotnet/core/testing/unit-testing-mstest-writing-tests-assertions#create-custom-assertions-with-assertthat">Create custom assertions with Assert.That</see>.
/// </remarks>
/// <example>
/// The following example defines a custom <c>IsPrime</c> assertion as an extension method on
/// <see cref="Assert"/> and invokes it through <c>Assert.That</c>:
/// <code language="csharp">
/// using System;
/// using System.Linq;
/// using Microsoft.VisualStudio.TestTools.UnitTesting;
///
/// public static class CustomAssertExtensions
/// {
/// public static void IsPrime(this Assert assert, int value)
/// {
/// if (value &lt; 2 || Enumerable.Range(2, (int)Math.Sqrt(value) - 1).Any(i =&gt; value % i == 0))
/// {
/// throw new AssertFailedException($"Assert.That.IsPrime failed. Value &lt;{value}&gt; is not a prime number.");
/// }
/// }
/// }
///
/// [TestClass]
/// public class CalculatorTests
/// {
/// [TestMethod]
/// public void NextPrime_ReturnsPrime()
/// {
/// int result = new Calculator().NextPrime(10);
/// Assert.That.IsPrime(result);
/// }
/// }
/// </code>
/// </example>
public static Assert That { get; } = new();

/// <summary>
Expand Down
41 changes: 38 additions & 3 deletions src/TestFramework/TestFramework/Assertions/CollectionAssert.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,46 @@ private CollectionAssert()
/// Gets the singleton instance of the CollectionAssert functionality.
/// </summary>
/// <remarks>
/// <para>
/// Users can use this to plug-in custom assertions through C# extension methods.
/// For instance, the signature of a custom assertion provider could be "public static void AreEqualUnordered(this CollectionAssert customAssert, ICollection expected, ICollection actual)"
/// Users could then use a syntax similar to the default assertions which in this case is "CollectionAssert.That.AreEqualUnordered(list1, list2);"
/// More documentation is at "https://github.com/Microsoft/testfx/docs/README.md".
/// For instance, the signature of a custom assertion provider could be <c>public static void AreEqualUnordered(this CollectionAssert customAssert, ICollection expected, ICollection actual)</c>
/// and the call-site would be <c>CollectionAssert.That.AreEqualUnordered(list1, list2);</c>.
/// </para>
/// <para>
/// For new custom assertions, prefer extending <see cref="Assert.That"/> instead, because <see cref="CollectionAssert"/> is likely to be deprecated in a future release.
Comment thread
Evangelink marked this conversation as resolved.
/// For more information, see <see href="https://learn.microsoft.com/dotnet/core/testing/unit-testing-mstest-writing-tests-assertions#extension-hooks-on-stringassert-and-collectionassert">Extension hooks on StringAssert and CollectionAssert</see>.
/// </para>
/// </remarks>
/// <example>
/// The following example defines a custom <c>AreEqualUnordered</c> assertion as an extension method
/// on <see cref="CollectionAssert"/> and invokes it through <c>CollectionAssert.That</c>:
/// <code language="csharp">
/// using System.Collections.Generic;
/// using System.Linq;
/// using Microsoft.VisualStudio.TestTools.UnitTesting;
///
/// public static class CustomCollectionAssertExtensions
/// {
/// public static void AreEqualUnordered&lt;T&gt;(this CollectionAssert collectionAssert, IEnumerable&lt;T&gt; expected, IEnumerable&lt;T&gt; actual)
/// {
/// if (!expected.OrderBy(x =&gt; x).SequenceEqual(actual.OrderBy(x =&gt; x)))
/// {
/// throw new AssertFailedException("CollectionAssert.That.AreEqualUnordered failed. Collections do not contain the same elements.");
/// }
/// }
/// }
///
/// [TestClass]
/// public class SetTests
/// {
/// [TestMethod]
/// public void Items_MatchRegardlessOfOrder()
/// {
/// CollectionAssert.That.AreEqualUnordered(new[] { 1, 2, 3 }, new[] { 3, 1, 2 });
/// }
/// }
/// </code>
/// </example>
public static CollectionAssert That { get; } = new();

#endregion
Expand Down
43 changes: 40 additions & 3 deletions src/TestFramework/TestFramework/Assertions/StringAssert.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,48 @@ private StringAssert()
/// Gets the singleton instance of the StringAssert functionality.
/// </summary>
/// <remarks>
/// <para>
/// Users can use this to plug-in custom assertions through C# extension methods.
/// For instance, the signature of a custom assertion provider could be "public static void ContainsWords(this StringAssert customAssert, string value, ICollection substrings)"
/// Users could then use a syntax similar to the default assertions which in this case is "StringAssert.That.ContainsWords(value, substrings);"
/// More documentation is at "https://github.com/Microsoft/testfx/docs/README.md".
/// For instance, the signature of a custom assertion provider could be <c>public static void ContainsWords(this StringAssert customAssert, string value, ICollection substrings)</c>
/// and the call-site would be <c>StringAssert.That.ContainsWords(value, substrings);</c>.
/// </para>
/// <para>
/// For new custom assertions, prefer extending <see cref="Assert.That"/> instead, because <see cref="StringAssert"/> is likely to be deprecated in a future release.
Comment thread
Evangelink marked this conversation as resolved.
/// For more information, see <see href="https://learn.microsoft.com/dotnet/core/testing/unit-testing-mstest-writing-tests-assertions#extension-hooks-on-stringassert-and-collectionassert">Extension hooks on StringAssert and CollectionAssert</see>.
/// </para>
/// </remarks>
/// <example>
/// The following example defines a custom <c>ContainsWords</c> assertion as an extension method
/// on <see cref="StringAssert"/> and invokes it through <c>StringAssert.That</c>:
/// <code language="csharp">
/// using System.Collections.Generic;
/// using Microsoft.VisualStudio.TestTools.UnitTesting;
///
/// public static class CustomStringAssertExtensions
/// {
/// public static void ContainsWords(this StringAssert stringAssert, string value, IEnumerable&lt;string&gt; words)
/// {
/// foreach (string word in words)
/// {
/// if (value == null || !value.Contains(word))
/// {
/// throw new AssertFailedException($"StringAssert.That.ContainsWords failed. Word &lt;{word}&gt; not found in &lt;{value}&gt;.");
/// }
/// }
/// }
/// }
///
/// [TestClass]
/// public class MessageTests
/// {
/// [TestMethod]
/// public void Greeting_ContainsExpectedWords()
/// {
/// StringAssert.That.ContainsWords("Hello, world!", new[] { "Hello", "world" });
/// }
/// }
/// </code>
/// </example>
public static StringAssert That { get; } = new();

#endregion
Expand Down