NUnit, возможно ли продолжить выполнение теста после сбоя Assert? - PullRequest
31 голосов
/ 14 мая 2010

В тесте, содержащем несколько утверждений, например:

Assert.AreEqual(1,1);
Assert.AreEqual(2,1);
Assert.AreEqual(2,2);

возможно ли позволить тесту продолжить работу после того, как он в какой-то момент провалится? В этом примере первое условие истинно, второе не выполнено и тест останавливается. Я хотел бы оценить также следующее условие.

Ответы [ 9 ]

23 голосов
/ 08 января 2013

Я предпочитаю быть практичным и объединить несколько связанных утверждений в один метод.

У меня есть вспомогательный класс, который включает следующий синтаксис (я использую):

AssertAll.Succeed(
    () => Assert.AreEqual("bb", id.Context),
    () => Assert.AreEqual("abc", id.FullName),
    () => Assert.AreEqual("b", id.SessionID));

, который выдает мне сообщения об ошибках вроде этого:

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

и вспомогательный класс выглядит следующим образом:

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);
    }
}
14 голосов
/ 10 июля 2015

NUnit 3.6 добавляет метод Assert.Multiple и атрибут MultipleAsserts.

enter image description here

См. https://github.com/nunit/docs/wiki/Multiple-Asserts.

11 голосов
/ 14 мая 2010

Нет. Как правило, в этой ситуации вы помещаете весь код над утверждениями в метод настройки, а затем записываете каждое утверждение в его собственный тестовый пример.

5 голосов
/ 24 июля 2014

Нет, вы не можете сделать это только с помощью NUnit. Вы должны сделать что-то вроде @Константин Спирин сказал. Я создал небольшое расширение, которое вы можете использовать; это называется NUnit-GroupAssert. Его можно найти здесь: https://github.com/slvnperron/NUnit-GroupAssert

Как это использовать:

[Test]
public void Verify_GroupsExceptions()
{
    var group = new AssertGroup();
    group.Add(() => Assert.AreEqual(10, 20));
    group.Add(() => Assert.AreEqual(1, 1));
    group.Add(() => Assert.AreEqual(3, 4));
    group.Add(() => Assert.IsTrue(1 > 3));
    group.Verify();
}

// OR

public void Verify_GroupsExceptions()
{
    // Verifies on disposal
    using (var group = new AssertGroup())
    {
        group.Add(() => Assert.AreEqual(10, 20));
        group.Add(() => Assert.AreEqual(1, 1));
        group.Add(() => Assert.AreEqual(3, 4));
        group.Add(() => Assert.IsTrue(1 > 3));
    }
}

будет выводиться:

Тест не пройден из-за сбоя одного или нескольких утверждений:
1) Ожидаемый: 10
Но было: 20
От исключений Verify_Groups в строке 18

2) Ожидаемое: 3
Но было: 4
От исключений Verify_Groups в строке 20

3) Ожидаемый: True
Но было: Ложь
От исключений Verify_Groups в строке 21

3 голосов
/ 14 мая 2010

Вы можете немного обмануть и на самом деле не потерпеть неудачу в данной точке, а скорее пометить за неудачу, а затем потерпеть неудачу в самом конце, что-то вроде следующего:

var sbError = new StringBuilder();
if (!SomeCondition()) {
  sbError.AppendLine("SomeCondition failed");
}
if (!SomeOtherCondition()) {
  sbError.AppendLine("SomeOtherCondition failed");
}
Assert.AreEqual(0, sbError.Length, sbError.ToString());

Я бы не рекомендовал это, но если вам нужно сделать это один или два раза, это не должно быть так плохо.

2 голосов
/ 14 мая 2010

Вы можете реструктурировать свой тест, чтобы обернуть утверждения в блок try / catch и отслеживать их для последующей проверки. Я не рекомендую это, однако. Вы действительно должны использовать отдельные тесты для каждого условия, если вы хотите, чтобы они тестировались независимо.

  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");
  }
2 голосов
/ 14 мая 2010

Утверждает, что выбрасывается исключение NUnit.Framework.AssertionException, если они терпят неудачу. Вы можете перехватить это исключение во втором утверждении, оценить третье утверждение, а затем повторно выдать исключение.

Однако я бы не рекомендовал этого по причинам, указанным Эд Вудкоком и Карлом Манастером.

2 голосов
/ 14 мая 2010

Неа. В любом случае, вы не должны иметь более одного утверждения в каждом тесте, что уменьшает разделение и затрудняет поиск того, какой из них провалился.

Если у вас есть много кода, который нужно выполнить перед Assert, выделите его в функцию [SetUp] или сделайте его отдельной процедурой.

0 голосов
/ 13 августа 2015

Я переписал пример кода Константина Спирина в VB.

Imports NUnit.Framework
Imports System.Reflection

Public Class Group_LIB_NUnit_Assert_Multiple

    Public Shared Sub Multiple(ParamArray Assertions As Action())
        Dim ExceptionObj As Exception
        Dim Exceptions As New List(Of Exception)
        Dim Message As String

        For Each Assertion In Assertions
            Try
                Assertion()
            Catch ex As Exception
                Exceptions.Add(ex)
            End Try
        Next

        If Exceptions.Count > 0 Then
            Message = String.Format("{0}{1} assertions failed: {2}{3}", Environment.NewLine, Exceptions.Count, Environment.NewLine, String.Join(Environment.NewLine, Exceptions.Select(Function(e) e.Message).ToList()))

            ExceptionObj = New AssertionException(Message)

            StackTraceReplace(ExceptionObj, Exceptions.First.StackTrace)

            Throw ExceptionObj
        End If
    End Sub

    Public Shared Sub StackTraceReplace(ExceptionObj As Exception, StackTrace As String)
        Dim RemoteStackTraceString As FieldInfo

        RemoteStackTraceString = GetType(Exception).GetField("_remoteStackTraceString", Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic)

        RemoteStackTraceString.SetValue(ExceptionObj, StackTrace)

    End Sub
End Class

Imports Group.Library4
Imports NUnit.Framework

<TestFixture()> _
Public Class TEST_Group_LIB_NUnit_Assert_Multiple

    <Test()> _
    <TestCaseSource("Factory")> _
    Public Sub Multiple(TestObj As TEST_DATA_Group_LIB_NUnit_Assert_Multiple)

        Group_LIB_NUnit_Assert_Multiple.Multiple(Sub() Assert.That(TestObj.Gender, [Is].EqualTo("F"c), "Gender"), Sub() Assert.That(TestObj.Name, [Is].EqualTo("George Washington"), "Name"))
    End Sub

    Public Function Factory() As List(Of TEST_DATA_Group_LIB_NUnit_Assert_Multiple)
        Dim L As New List(Of TEST_DATA_Group_LIB_NUnit_Assert_Multiple)
        Dim TestObj As TEST_DATA_Group_LIB_NUnit_Assert_Multiple

        TestObj = New TEST_DATA_Group_LIB_NUnit_Assert_Multiple()
        TestObj.DOB = New DateTime(2015, 8, 12)
        TestObj.Gender = "M"c
        TestObj.Name = "Abraham Lincoln"
        L.Add(TestObj)

        TestObj = New TEST_DATA_Group_LIB_NUnit_Assert_Multiple()
        TestObj.DOB = New DateTime(2015, 8, 12)
        TestObj.Gender = "F"c
        TestObj.Name = "George Washington"
        L.Add(TestObj)

        TestObj = New TEST_DATA_Group_LIB_NUnit_Assert_Multiple()
        TestObj.DOB = New DateTime(2015, 8, 12)
        TestObj.Gender = "A"c
        TestObj.Name = "John Hancock"
        L.Add(TestObj)

        Return L
    End Function
End Class

Public Class TEST_DATA_Group_LIB_NUnit_Assert_Multiple

    Public Property DOB As Date

    Public Property Gender As Char

    Public Property Name As String

End Class
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...