Подтвердить что ты не робот

NUnit, можно ли продолжить выполнение теста после сбоя Assert?

В тесте, который содержит некоторые утверждения, например:

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

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

4b9b3361

Ответ 2

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

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

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);
    }
}

Ответ 3

Нет. Обычно в этой ситуации вы помещаете весь код выше утверждений в метод настройки, а затем записываете каждое утверждение в свой собственный тестовый пример.

Ответ 4

Нет, вы не можете сделать это с помощью 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_GroupsExceptions в строке 18

2) Ожидается: 3
      Но было: 4
      Из Verify_GroupsExceptions в строке 20

3) Ожидается: Истинный
      Но было: False
      Из Verify_GroupsExceptions в строке 21

Ответ 5

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

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

Ответ 6

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

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

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

Ответ 7

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

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

Ответ 8

Вы можете перестроить свой тест, чтобы обернуть утверждения в блок 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");
  }

Ответ 9

Я переписал образец кода Константина Спирина в 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