2009-08-02 5 views
20

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

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

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

Написание единицы измерения для Sum() является простым. Однако, когда я пишу тест для Average(), и Sum() терпит неудачу, скорее всего, также выйдет Average().

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

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

ответ

14

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

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

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


Johannes,

Это, как я бы реализовать 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.

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

+0

. Не могли бы вы рассказать о том, как вы подойдете к этому в этом очень особенном случае? –

+0

Большое вам спасибо. поэтому, по сути, вы говорите, что нет необходимости писать явный тест для Sum(), но проверяя его через Average(). С точки зрения охвата кода это все равно приводит к такому же результату. –

+1

Я бы также написал тесты для Sum(). Кто знает в мой сонный момент, я могу набрать «-» вместо «/». :) С тестами для Sum() на месте, если я получил все тесты для Sum(), но какой-то тест для Average() терпит неудачу, я могу быть очень уверен, что реализация для Average() неверна. Я не буду обвинять Sum() в том, что вы вызываете ошибку Average(). :) – tranmq

9

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

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

+1

Пара комментариев: (1) Visual Studio рассматривает те тесты, которые утверждают, что они считаются «пропущенными тестами» в Test Explorer. Затем эта категория становится вашим списком дел. Джаред уже упоминал об этом с «отфильтровыванием тестовых сбоев», но я считаю это большим преимуществом (2) Если у вас есть несколько утверждений в одном тесте (который проходит), но один утверждает, что он неубедительный, весь тест считается «пропущенным» «. Раньше я использовал unonclusive для того, чтобы представить ту же ситуацию, что и Dennis C, но сейчас это не нравится, потому что неясно, каков общий результат теста. – DPH

23

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

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

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

+2

Я использовал Inconclusive в письме unittest. Код отправляет электронные письма, и я должен проверить визуальный макет из почтового ящика Outlook, –

7

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

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

-или-

Мой тест имеет зависимость, и что зависимость недоступно. Например,

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