In a test that contains some asserts, for example:
Assert.AreEqual(1,1);
Assert.AreEqual(2,1);
Assert.AreEqual(2,2);
is it possible to let
Asserts thrown an NUnit.Framework.AssertionException if they fail. You could catch that exception on the second assert, evaluate the third assert, then re-throw the exception.
Not something I'd recommend, though, for the reasons pointed-out by Ed Woodcock and Carl Manaster.
I prefer to be practical and put several related assertions in one method.
I have a helper class which enables the following syntax (I use):
AssertAll.Succeed(
() => Assert.AreEqual("bb", id.Context),
() => Assert.AreEqual("abc", id.FullName),
() => Assert.AreEqual("b", id.SessionID));
which gives me error messages like this:
Assert.AreEqual failed. Expected:<bb>. Actual:<b\c>.
Assert.AreEqual failed. Expected:<abc>. Actual:<[b\c]a{103}>.
at FXP_COM.Tests.EnumToStringConverterterTests.<>c__DisplayClass3.<ShouldConvert>b__0() in UnitTest1.cs: line 31
at FXP_COM.Tests.AssertAll.Succeed(Action[] assertions) in UnitTest1.cs: line 46 at FXP_COM.Tests.AssertAll.Succeed(Action[] assertions) in UnitTest1.cs: line 62
at FXP_COM.Tests.EnumToStringConverterterTests.ShouldConvert() in UnitTest1.cs: line 30
and the helper class is the following:
using System;
using NUnit.Framework;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
public static class AssertAll
{
public static void Succeed(params Action[] assertions)
{
var errors = new List<Exception>();
foreach (var assertion in assertions)
try
{
assertion();
}
catch (Exception ex)
{
errors.Add(ex);
}
if (errors.Any())
{
var ex = new AssertionException(
string.Join(Environment.NewLine, errors.Select(e => e.Message)),
errors.First());
// Use stack trace from the first exception to ensure first
// failed Assert is one click away
ReplaceStackTrace(ex, errors.First().StackTrace);
throw ex;
}
}
static void ReplaceStackTrace(Exception exception, string stackTrace)
{
var remoteStackTraceString = typeof(Exception)
.GetField("_remoteStackTraceString",
BindingFlags.Instance | BindingFlags.NonPublic);
remoteStackTraceString.SetValue(exception, stackTrace);
}
}
NUnit 3.6 adds Assert.Multiple
method and MultipleAsserts
attribute.
See https://github.com/nunit/docs/wiki/Multiple-Asserts.
No. Typically in this situation you would put all the code above the asserts into a setup method, then write each assert into its own test case.
You can cheat a little and not actually fail at a given point, but rather mark for failure, then fail at the very end, something like the following:
var sbError = new StringBuilder();
if (!SomeCondition()) {
sbError.AppendLine("SomeCondition failed");
}
if (!SomeOtherCondition()) {
sbError.AppendLine("SomeOtherCondition failed");
}
Assert.AreEqual(0, sbError.Length, sbError.ToString());
I wouldn't recommend this, but if you need to do it once or twice, it shouldn't be that bad.
You could restructure your test to wrap the assertions in try/catch block and keep track of them for later validation. I don't recommend this, however. You really should be using separate tests for each condition if you want them to be tested independently.
bool[] assertionSuccesses = new bool[] { false, false, false };
try
{
Assert.AreEqual( 1, 1 );
assertionSuccesses[0] = true;
}
catch (AssertionException) {}
...
if (assertionSuccesses.Any( s => !s ))
{
Assert.Fail("one of the assertions failed");
}