0

Is it possible to continue after a failed Assertion in FluentAssertions? I had some assertions which are no show stoppers and should only be reported but not failing the Test run.

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestMethod1()
    {
        using (var scope = new AssertionScope())
        {
            "This Should not Failed with an AssertException".Should().Be("Should Failed");
            "And this also not".Should().Be("Should Failed");
            "All should only be printed to the console".Should().NotBeEmpty();
        }
        "But the Test should continue".Should().Be("And Failed here with an AssertException");
    }
}
Christian
  • 1,022
  • 13
  • 28
  • 1
    A small example of code would definitely help here. Talking in general, don't assert something unimportant. You can output something, just google for your unit test framework (e.g. [here](https://stackoverflow.com/a/45492953/1997232) is NUnit way). – Sinatr Dec 16 '19 at 08:27
  • I am making Selenium Tests, and if a text is not as excpected it is no reason to stop the Test only to print a message. – Christian Dec 16 '19 at 08:34

2 Answers2

1

You can wrap the assertions in an AssertionScope to capture all the failures in a single exception. See also https://fluentassertions.com/introduction#assertion-scopes

Dennis Doomen
  • 8,368
  • 1
  • 32
  • 44
  • Do you have a practical use case example for `AssertionScope`? When is it useful? To me, in example there "Expected value to be 10, but found 5." is enough to know, I don't care if more asserts are failing because I must fix that first failing one anyway. – Sinatr Dec 16 '19 at 08:33
  • Yes, but if I wrap the Asserts in an AssertionScope and do scope.Discard() at the end their are no message. How can I get the failed assertions to output but still continue? – Christian Dec 16 '19 at 08:33
  • I don't think you can, assertions are explicitly check this and fail if not. If you only want to log, perhaps all you have to do is create something similar that just writes to the console? – Lasse V. Karlsen Dec 16 '19 at 09:22
  • `scope.Discard()` returns you the failure messages, so you can just dump them to the command-line or use XUnit's `ITestOutputHelper`. – Dennis Doomen Dec 16 '19 at 14:01
1

For the output side, use ITestOutputHelper from XUnit — it's the only way to get test log output in XUnit 2.0+. If you must write the checks as assertions, you can provide your own implementation of IAssertionStrategy as a constructor parameter to AssertionScope, and have it send assertion failure messages to XUnit's test output instead of throwing.

Note: You'll need at least v5.9.0 of FluentAssertions to pull this off.

public class XUnitTestOutputAssertionStrategy : IAssertionStrategy
{
    private readonly ITestOutputHelper output;
    private readonly List<string> failures = new List<string>();

    public XUnitTestOutputAssertionStrategy(ITestOutputHelper output)
    {
        this.output = output;
    }

    public void HandleFailure(string message)
    {
        failures.Add(message);
    }

    public IEnumerable<string> DiscardFailures()
    {
        var snapshot = failures.ToArray();
        failures.Clear();
        return snapshot;
    }

    public void ThrowIfAny(IDictionary<string, object> context)
    {
        if (!failures.Any()) return;

        var sb = new StringBuilder();
        sb.AppendLine(string.Join(Environment.NewLine, failures));
        foreach ((string key, object value) in context)
            sb.AppendFormat("\nWith {0}:\n{1}", key, value);

        output.WriteLine(sb.ToString());
    }

    public IEnumerable<string> FailureMessages => failures;
}

public class ContrivedTests
{
    private readonly ITestOutputHelper output;

    public ContrivedTests(ITestOutputHelper output)
    {
        this.output = output;
    }

    [Fact]
    public void WhenRunningTest_WithContrivedExample_ShouldOutputThenAssert()
    {
        using (new AssertionScope(new XUnitTestOutputAssertionStrategy(output)))
        {
            "Failures will log".Should().Contain("nope", "because we want to log this");
            "Success won't log".Should().StartWith("Success", "because we want to log this too, but it succeeded");
        }

        "This line will fail the test".Should().StartWith("Bottom Text", "because I pulled a sneaky on ya");
    }
}
Tullo_x86
  • 2,573
  • 25
  • 27