Skip to content

Assertion messages that use expressions more naturally #7135

@nohwnd

Description

@nohwnd

Now that we have the expressions, it would be nice to go from this:

failed TestMethod1 (21ms)
  Assert.ThrowsExactly failed. Expected exception type:<System.InvalidOperationException>. Actual exception type:<System.ArgumentNullException>. 'action' expression: '() => MyClass.MyMethod()'.
  from bin\Debug\net10.0\mstest319.dll (net10.0|x64)
  Assert.ThrowsExactly failed. Expected exception type:<System.InvalidOperationException>. Actual exception type:<System.ArgumentNullException>. 'action' expression: '() => MyClass.MyMethod()'.
    at Microsoft.VisualStudio.TestTools.UnitTesting.Assert.<>c__DisplayClass226_1`1.<IsThrowsFailing>b__1(String userMessage) in /_/src/TestFramework/TestFramework/Assertions/Assert.ThrowsException.cs:581
    at Microsoft.VisualStudio.TestTools.UnitTesting.Assert.ThrowsException[TException](Action action, Boolean isStrictType, String message, String actionExpression, String assertMethodName) in /_/src/TestFramework/TestFramework/Assertions/Assert.ThrowsException.cs:330
    at Microsoft.VisualStudio.TestTools.UnitTesting.Assert.ThrowsExactly[TException](Action action, String message, String actionExpression) in /_/src/TestFramework/TestFramework/Assertions/Assert.ThrowsException.cs:267
    at mstest319.Test1.TestMethod1() in Test1.cs:9
    at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
    at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)

to this:

failed TestMethod1 (21ms)
  from bin\Debug\net10.0\mstest319.dll (net10.0|x64)
  Assert.ThrowsExactly failed. () => MyClass.MyMethod() was expected to throw System.InvalidOperationException, but System.ArgumentNullException was thrown.
    Expected exception type: System.InvalidOperationException
    Actual exception: System.ArgumentNullException: Value cannot be null.
      System.ArgumentNullException: Value cannot be null.
      at mstest319.MyClass.MyMethod() in Test1.cs:18
      at mstest319.Test1.TestMethod1() in Test1.cs:9
        ...
    at Microsoft.VisualStudio.TestTools.UnitTesting.Assert.<>c__DisplayClass226_1`1.<IsThrowsFailing>b__1(String userMessage) in /_/src/TestFramework/TestFramework/Assertions/Assert.ThrowsException.cs:581
    at Microsoft.VisualStudio.TestTools.UnitTesting.Assert.ThrowsException[TException](Action action, Boolean isStrictType, String message, String actionExpression, String assertMethodName) in /_/src/TestFramework/TestFramework/Assertions/Assert.ThrowsException.cs:330
    at Microsoft.VisualStudio.TestTools.UnitTesting.Assert.ThrowsExactly[TException](Action action, String message, String actionExpression) in /_/src/TestFramework/TestFramework/Assertions/Assert.ThrowsException.cs:267
    at mstest319.Test1.TestMethod1() in Test1.cs:9
    at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
    at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)

(the three dots are not meant to represent shortening of the inner stack trace, I just don't have exact example)

Following this pattern in all assertions:

<short summary of what failed, without adding multiline details e.g. expanding objects>, so I can see what is the problem before digging into the details. This is up to each assertion to see what is correct. e.g. expanding long strings in the short message is not good. Showing whole error and stack trace before saying "but the message did not match" is also not great.

<user message?>

<details of expected>
<details of actual>

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions