diff --git a/src/TestFramework/TestFramework/Assertions/Assert.cs b/src/TestFramework/TestFramework/Assertions/Assert.cs
index b345210c39..6fa6f41ca7 100644
--- a/src/TestFramework/TestFramework/Assertions/Assert.cs
+++ b/src/TestFramework/TestFramework/Assertions/Assert.cs
@@ -20,10 +20,41 @@ private Assert()
///
///
/// 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<T>(this Assert assert, object obj)"
- /// Users could then use a syntax similar to the default assertions which in this case is "Assert.That.IsOfType<Dog>(animal);"
- /// More documentation is at "https://github.com/Microsoft/testfx/docs/README.md".
+ /// For instance, the signature of a custom assertion provider could be public static void IsOfType<T>(this Assert assert, object obj)
+ /// and the call-site would be Assert.That.IsOfType<Dog>(animal);.
+ /// For more information, see Create custom assertions with Assert.That.
///
+ ///
+ /// The following example defines a custom IsPrime assertion as an extension method on
+ /// and invokes it through Assert.That:
+ ///
+ /// 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 < 2 || Enumerable.Range(2, (int)Math.Sqrt(value) - 1).Any(i => value % i == 0))
+ /// {
+ /// throw new AssertFailedException($"Assert.That.IsPrime failed. Value <{value}> is not a prime number.");
+ /// }
+ /// }
+ /// }
+ ///
+ /// [TestClass]
+ /// public class CalculatorTests
+ /// {
+ /// [TestMethod]
+ /// public void NextPrime_ReturnsPrime()
+ /// {
+ /// int result = new Calculator().NextPrime(10);
+ /// Assert.That.IsPrime(result);
+ /// }
+ /// }
+ ///
+ ///
public static Assert That { get; } = new();
///
diff --git a/src/TestFramework/TestFramework/Assertions/CollectionAssert.cs b/src/TestFramework/TestFramework/Assertions/CollectionAssert.cs
index 30a2558bb4..2393ac17d0 100644
--- a/src/TestFramework/TestFramework/Assertions/CollectionAssert.cs
+++ b/src/TestFramework/TestFramework/Assertions/CollectionAssert.cs
@@ -21,11 +21,46 @@ private CollectionAssert()
/// Gets the singleton instance of the CollectionAssert functionality.
///
///
+ ///
/// 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 public static void AreEqualUnordered(this CollectionAssert customAssert, ICollection expected, ICollection actual)
+ /// and the call-site would be CollectionAssert.That.AreEqualUnordered(list1, list2);.
+ ///
+ ///
+ /// For new custom assertions, prefer extending instead, because is likely to be deprecated in a future release.
+ /// For more information, see Extension hooks on StringAssert and CollectionAssert.
+ ///
///
+ ///
+ /// The following example defines a custom AreEqualUnordered assertion as an extension method
+ /// on and invokes it through CollectionAssert.That:
+ ///
+ /// using System.Collections.Generic;
+ /// using System.Linq;
+ /// using Microsoft.VisualStudio.TestTools.UnitTesting;
+ ///
+ /// public static class CustomCollectionAssertExtensions
+ /// {
+ /// public static void AreEqualUnordered<T>(this CollectionAssert collectionAssert, IEnumerable<T> expected, IEnumerable<T> actual)
+ /// {
+ /// if (!expected.OrderBy(x => x).SequenceEqual(actual.OrderBy(x => 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 });
+ /// }
+ /// }
+ ///
+ ///
public static CollectionAssert That { get; } = new();
#endregion
diff --git a/src/TestFramework/TestFramework/Assertions/StringAssert.cs b/src/TestFramework/TestFramework/Assertions/StringAssert.cs
index 08106d7e22..f7ab02bc93 100644
--- a/src/TestFramework/TestFramework/Assertions/StringAssert.cs
+++ b/src/TestFramework/TestFramework/Assertions/StringAssert.cs
@@ -19,11 +19,48 @@ private StringAssert()
/// Gets the singleton instance of the StringAssert functionality.
///
///
+ ///
/// 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 public static void ContainsWords(this StringAssert customAssert, string value, ICollection substrings)
+ /// and the call-site would be StringAssert.That.ContainsWords(value, substrings);.
+ ///
+ ///
+ /// For new custom assertions, prefer extending instead, because is likely to be deprecated in a future release.
+ /// For more information, see Extension hooks on StringAssert and CollectionAssert.
+ ///
///
+ ///
+ /// The following example defines a custom ContainsWords assertion as an extension method
+ /// on and invokes it through StringAssert.That:
+ ///
+ /// using System.Collections.Generic;
+ /// using Microsoft.VisualStudio.TestTools.UnitTesting;
+ ///
+ /// public static class CustomStringAssertExtensions
+ /// {
+ /// public static void ContainsWords(this StringAssert stringAssert, string value, IEnumerable<string> words)
+ /// {
+ /// foreach (string word in words)
+ /// {
+ /// if (value == null || !value.Contains(word))
+ /// {
+ /// throw new AssertFailedException($"StringAssert.That.ContainsWords failed. Word <{word}> not found in <{value}>.");
+ /// }
+ /// }
+ /// }
+ /// }
+ ///
+ /// [TestClass]
+ /// public class MessageTests
+ /// {
+ /// [TestMethod]
+ /// public void Greeting_ContainsExpectedWords()
+ /// {
+ /// StringAssert.That.ContainsWords("Hello, world!", new[] { "Hello", "world" });
+ /// }
+ /// }
+ ///
+ ///
public static StringAssert That { get; } = new();
#endregion