Какие ошибки могут содержать мой код, даже если у меня 100% покрытие кода? - PullRequest
14 голосов
/ 17 февраля 2009

Какой тип ошибок может содержать мой код, даже если у меня 100% покрытие кода? Я ищу конкретные примеры или ссылки на конкретные примеры таких ошибок.

Ответы [ 21 ]

3 голосов
/ 17 февраля 2009

Покрытие кода ничего не значит, если ваши тесты содержат ошибки или вы тестируете не то.

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

sorted = sort(2,1,6,4,3,1,6,2);

for element in sorted {
  if (is_defined(previousElement)) {
    assert(element >= previousElement);
  }

  previousElement = element;
}

бонусная карма Джону Скиту, который указал на лазейку, о которой я думал

2 голосов
/ 17 февраля 2009

Ошибки в тестах:)

1 голос
/ 17 февраля 2009

К вашему сведению, Microsoft Pex пытается помочь, изучая ваш код и находя «крайние» случаи, такие как деление на ноль, переполнение и т. Д.

Этот инструмент является частью VS2010, хотя вы можете установить техническую предварительную версию в VS2008. Весьма примечательно, что этот инструмент находит то, что он находит, хотя, IME, он все равно не даст вам полностью «пуленепробиваемый».

1 голос
/ 17 февраля 2009

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

1 голос
/ 17 февраля 2009

Я не знаю ни о ком другом, но мы не получаем почти 100% покрытия. Ни одна из наших CATCH «этого никогда не должно происходить» не выполняется в наших тестах (ну, иногда они делают, но затем код исправляется, чтобы они больше не выполнялись!). Боюсь, я не волнуюсь, что может быть ошибка синтаксиса / логики в никогда не происходящем CATCH

1 голос
/ 17 февраля 2009

Аргументация проверки, ака. Нулевые Проверки. Если вы берете какие-либо внешние входы и передаете их в функции, но никогда не проверяете, являются ли они действительными / нулевыми, тогда вы можете достичь 100% покрытия, но вы все равно получите исключение NullReferenceException, если вы каким-то образом передадите нуль в функцию, потому что это то, что дает ваша база данных. вы.

также, арифметическое переполнение, как

int result = int.MAXVALUE + int.MAXVALUE;

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

1 голос
/ 17 февраля 2009

Хорошо, если ваши тесты не проверяют то, что происходит в покрытом коде. Если у вас есть этот метод, который добавляет число к свойствам, например:

public void AddTo(int i)
{
NumberA += i;
NumberB -= i;
}

Если ваш тест проверяет только свойство NumberA, но не NumberB, то у вас будет 100% покрытие, тест пройден, но NumberB все равно будет содержать ошибку.

Вывод: модульный тест со 100% не гарантирует отсутствие ошибок в коде.

0 голосов
/ 23 февраля 2009

Почти все.

Вы прочитали Код завершен ? (Потому что StackOverflow говорит, что вы действительно должны .) В главе 22 говорится, что «100% покрытие заявлений - хорошее начало, но вряд ли его достаточно». В оставшейся части главы объясняется, как определить, какие дополнительные тесты добавить. Вот краткий дегустатор.

  • Структурное базовое тестирование и тестирование потока данных означает тестирование каждого логического пути в программе. Ниже приведено четыре пути в подготовленном коде, в зависимости от значений A и B. 100% -ное покрытие оператора может быть достигнуто путем тестирования только двух из четырех путей, возможно, f=1:g=1/f и f=0:g=f+1. Но f=0:g=1/f даст ошибку деления на ноль. Вы должны учитывать , если операторы и , тогда как и для циклов (тело цикла может никогда не выполняться) и каждая ветвь выбирает или switch оператор.

    If A Then
    f = 1
    Else
    f = 0
    End If
    If B Then
    g = f + 1
    Else
    g = f / 0
    End If

  • Догадка ошибок - информированные предположения о типах ввода, которые часто вызывают ошибки. Например, граничные условия (отключено на одну ошибку), неверные данные, очень большие значения, очень маленькие значения, нули, нули, пустые коллекции.

И даже в этом случае могут быть ошибки в ваших требованиях, ошибки в ваших тестах и ​​т. Д., Как уже упоминали другие.

0 голосов
/ 17 февраля 2009

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

Кроме того, вы можете иметь 0 ошибок, но логика в вашем коде может быть неправильной (не соответствующей требованиям). Покрытие кодом или отсутствие ошибок на 100% никак не поможет.

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

  1. Имеют четко написанную функциональную спецификацию
  2. Составьте план тестирования, составленный в соответствии с (1), и проверьте его на предмет рецензирования
  3. Имейте тестовые случаи, написанные против (2), и сделайте их рецензированными
  4. Пишите код в соответствии с функциональной спецификацией и проверяйте его
  5. Протестируйте ваш код в соответствии с контрольными примерами
  6. Проведите анализ покрытия кода и напишите больше тестовых случаев, чтобы получить хорошее покрытие.

Обратите внимание, что я сказал "хорошо", а не "100%". Не всегда возможно достичь 100% покрытия - в этом случае ваша энергия лучше всего расходуется на достижение правильности кода, а не на покрытие некоторых неясных ветвей. Разные виды вещей могут пойти не так на любом из шагов с 1 по 5 выше: неправильная идея, неправильная спецификация, неправильные тесты, неправильный код, неправильное выполнение теста ... Суть в том, что один шаг 6 не является самым важным шагом в процесс.

Конкретный пример неправильного кода, который не содержит ошибок и имеет 100% охват:

/**
 * Returns the duration in milliseconds
 */
int getDuration() {
    return end - start;
}

// test:

start = 0;
end = 1;
assertEquals(1, getDuration()); // yay!

// but the requirement was:
// The interface should have a method for returning the duration in *seconds*.
0 голосов
/ 17 февраля 2009

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

Например, рассмотрим типичный метод сравнения (на языке Java, но применяется на большинстве языков):

//Return Negative, 0 or positive depending on x is <, = or > y
int compareTo(int x, int y) {
   return x-y;
}

Пока у вас есть тест для compareTo(0,0), вы получаете покрытие кода. Тем не менее, вам нужно как минимум 3 тестовых случая здесь (для 3 результатов). Тем не менее, это не без ошибок. Также стоит добавить тесты, чтобы покрыть исключительные / ошибочные условия. В приведенном выше случае, если вы попытаетесь compareTo(10, Integer.MAX_INT), произойдет сбой.

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

Также проверьте наличие таких инструментов, как QuickCheck (если доступно для вашего языка).

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