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

Использование Assert.Inconclusive

Мне интересно, как кто-то должен использовать Assert.Inconclusive().

Я использую его, если мой unit test будет терпеть неудачу по другой причине, кроме теста.

Например, у меня есть метод класса, который вычисляет сумму массива из int. В том же классе существует также метод вычисления среднего значения элемента. Он реализуется путем вызова суммы и деления ее на длину массива.

Запись unit test для Sum() проста. Однако, когда я пишу тест для Average(), и Sum() терпит неудачу, скорее всего, также выйдет Average().

Неисправность Среднего значения не является явной о причине ее отказа; он не по какой-то причине, кроме того, что он должен проверить. Поэтому я бы проверял, возвращает ли Sum() правильный результат, иначе я Assert.Inconclusive().

Это считается хорошей практикой? Для чего предназначен Assert.Inconclusive? Или я должен скорее решить предыдущий пример с помощью Изоляционной Структуры?

4b9b3361

Ответ 1

Когда я использую VS для создания модульных тестов, я получил Assert.Inclusive для сгенерированных тестовых методов, и обычно я изменяю это утверждение так, чтобы что-то еще, когда я их работаю. Я использую вопросительные знаки Assert.Inconclusive в результатах теста в качестве маркеров, чтобы быстро сказать, какие тесты я еще не выполнил.

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

Однако, из описания вашего метода Average(), я думаю, что, возможно, ваш unit test не достаточно атомный, чтобы охватить только один "блок", один конкретный сценарий. Иногда я пишу 2 или 3 метода unit test для одного метода. Или вы можете разбить свой метод Average() на более мелкие методы, охватывающие отдельные обязанности. Таким образом, вы можете unit test те более мелкие методы перед тестированием устройства Average() one.


Йоханнес,

Вот как я мог бы реализовать методы Sum() и Average().

public static class MyMath
{
    private static void ValidateInput(ICollection<int> numbers)
    {
        if (numbers == null)
            throw new ArgumentNullException("numbers", "Null input.  Nothing to compute!");
        if (numbers.Count == 0)
            throw new ArgumentException("Input is empty.  Nothing to compute!");
    }

    public static int Sum(int[] numbers)
    {
        ValidateInput(numbers);

        var total = 0;
        foreach (var number in numbers)
            total += number;

        return total;
    }

    public static double Average(int[] numbers)
    {
        ValidateInput(numbers);
        return Sum(numbers) / numbers.Length;
    }
}

Для простоты я просто бросаю ArgumentException исключения из метода ValidateInput(ICollection<int>). Вы также можете проверить возможность переполнения и бросить OverflowException в методе ValidateInput(ICollection<int>).

С учетом сказанного здесь я проведу функцию Average(int[]).

[TestMethod]
public void AverageTest_GoodInput()
{
    int[] numbers = {1, 2, 3};
    const double expected = 2.0;
    var actual = MyMath.Average(numbers);
    Assert.AreEqual(expected, actual);
}

[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void AverageTest_NullInput()
{
    int[] numbers = null;
    MyMath.Average(numbers);
}

[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void AverageTest_EmptyInput()
{
    var numbers = new int[0];
    MyMath.Average(numbers);
}

С помощью этих тестов я могу быть уверен, что когда все тесты пройдут, моя функция верна. Ну, кроме случая переполнения. Теперь я могу вернуться к методу ValidateInput(ICollection<int>), чтобы добавить логику для проверки переполнения, а затем добавить еще один тест, чтобы оживить OverflowException для типов входов, которые вызывают переполнение. Или делать это в обратном порядке, если вам нравится подход с использованием TDD.

Надеюсь, это поможет прояснить эту идею.

Ответ 2

Неконкретный тест - это тест, для которого вы не можете определить результат. Например, что делать, если у вас был тест, который использует какой-то внешний ресурс (например, подключение к Интернету). Если соединение в настоящее время недоступно, это не означает, что тест является сбоем. С другой стороны, вы не должны просто отмечать ее как успешную, не выполняя ее. Поэтому вы отмечаете это как неубедительное, и это можно увидеть в отчете об испытаниях.

ПРИМЕЧАНИЕ. В общем, вы не должны использовать такие внешние ресурсы в своих тестах, поскольку это может сделать тесты уязвимыми.

Для тестов, которые еще не закончены, я использую атрибут MbUnit Explicit.

Ответ 3

Я только Assert.Inconclusive на модульных тестах еще не написал. Иногда, когда я пишу что-то, я понимаю какой-то угловой случай, который я не хочу пропустить. Поэтому я быстро перепрыгиваю, записываю тестовый метод с описательным именем и добавляю одну строку Assert.Inconclusive.

Причиной этого является то, что он предоставляет документацию о вещах, которые мне нужны для тестирования, не слишком сильно прерывая мой рабочий процесс. Это также позволяет быстро отфильтровать тестовые сбои в списке результатов. Имея неубедительный отказ, я ничего не сломал, я просто больше тестов, чтобы писать.

Ответ 4

Assert.Inconclusive указывает, что либо:

Я еще не написал тест, я только создал тестовый метод

-или -

У моего теста есть зависимость, и эта зависимость недоступна. Например

List<Customer> custs = o.GetAllCustomers();
if (custs.Count == 0)
{
  Assert.Inconclusive("No customers to test");
  return;
}