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

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

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

4b9b3361

Ответ 1

Наличие 100% -ного охвата кода не так уж велико, как можно подумать. Рассмотрим треугольный пример:

double Foo(double a, double b)
{
    return a / b;
}

Даже один unit test повысит охват кода этого метода до 100%, но указанный unit test не скажет нам, какой код работает и какой код нет. Это может быть вполне допустимый код, но без тестирования краевых условий (например, когда b есть 0.0) unit test в лучшем случае неубедительно.

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

Прослушайте этот для интересного обсуждения.

Ответ 2

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

Более элегантный способ сделать то же самое - это нечто, называемое абстрактной интерпретацией. MSR (Microsoft Research) выпустила что-то, называемое CodeContracts на основе абстрактной интерпретации. Проверьте Pex, они действительно выделяют методы тестирования времени выполнения приложений.. p >

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

Покрытие кода не означает хороших тестов

Ответ 3

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

Ответ 4

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

Он сообщает только, какие части вашего кода гарантированно непроверены.

Ответ 5

1. Проблемы с пространством данных

Ваш (плохой) код:

void f(int n, int increment)
{
  while(n < 500)
  {
    cout << n;
    n += increment;
  }
}

Ваш тест:

f(200,100);

Ошибка в реальном мире:

f(200,0);

Моя точка: ваш тест может охватывать 100% строк вашего кода, но он не будет (обычно) охватывать все возможные области входных данных, т.е. набор всех возможных значений входов.

2. Тестирование против вашей собственной ошибки

Еще один классический пример - когда вы просто принимаете плохое решение в дизайне и проверяете свой код против своего собственного плохого решения.

например. В документе спецификаций говорится "распечатать все простые числа до n", и вы печатаете все простые числа до n, но исключая n. И ваши модульные тесты проверяют вашу неправильную идею.

3. Undefined поведение

Использовать значение неинициализированных переменных, вызвать недопустимый доступ к памяти и т.д., а ваш код имеет поведение Undefined (на С++ или на любом другом языке, который предполагает "поведение undefined" ). Иногда это будет проходить ваши тесты, но он потерпит крах в реальном мире.

...

Ответ 6

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

Ответ 7

Рассмотрим следующий код:

int add(int a, int b)
{
  return a + b;
}

Этот код может не реализовать некоторые необходимые функции (т.е. не удовлетворять требованиям конечного пользователя): "100% -ый охват" не обязательно проверяет/обнаруживает функциональность, которая должна быть реализована, но которая не является.

Этот код может работать для некоторых, но не для всех диапазонов входных данных (например, когда a и b очень большие).

Ответ 8

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

В качестве связанной касательной; Напомню, что я могу тривиально построить метод 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;
}

бонус-карма к Jon Skeet, который указал на лазейку, о которой я думал,

Ответ 9

Покрытие кода обычно указывает только, сколько покрытий внутри функции. Обычно он не сообщает о различных путях, которые можно было бы сделать между вызовами функций. Многие ошибки в программах происходят потому, что передача обслуживания от одного метода к другому неверна, а не потому, что сами методы содержат ошибки. Все ошибки этой формы могут все еще существовать в 100% -ном охвате кода.

Ответ 10

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

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

Ссылка на статью здесь, и я нашел приблизительное резюме .

Ответ 11

работает на моей машине

Многие вещи хорошо работают на локальной машине, и мы не можем гарантировать, что работаем над Staging/Production. Покрытие кода может не охватывать это.

Ответ 12

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

Ответ 13

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

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

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

Вывод: a unit test со 100% не гарантирует, что код не содержит ошибок.

Ответ 14

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

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

int result = int.MAXVALUE + int.MAXVALUE;

Code Coverage охватывает только существующий код, он не сможет указать, где вы должны добавить больше кода.

Ответ 15

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

Ответ 16

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

Ответ 17

FYI, Microsoft Pex пытается помочь, исследуя ваш код и находя "крайние" случаи, такие как деление на ноль, переполнение и т.д.

Этот инструмент является частью VS2010, хотя вы можете установить техническую версию предварительного просмотра в VS2008. Это замечательно, что инструмент находит все, что он находит, хотя, IME, он все равно не собирается доводить вас до "пуленепробиваемого".

Ответ 18

Выполняйте 100% -ный охват кода, то есть 100% -ные инструкции, 100% -ные входные и выходные домены, 100% -ные пути, 100%, что бы вы ни думали, и у вас все еще могут быть ошибки в коде: /STRONG > .

Ответ 19

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

Например, рассмотрим типичный метод compareTo (в 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), он будет терпеть неудачу.

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

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

Ответ 20

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

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

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

  • Имейте четко написанную функциональную спецификацию
  • Имейте план тестирования, написанный против (1), и проверите его рецензирование
  • У вас есть тестовые примеры, написанные против (2), и они должны быть оценены экспертами.
  • Напиши код в соответствии с функциональной спецификацией и проверив его рецензированием
  • Проверьте свой код на тестовые примеры
  • Проведите анализ покрытия кода и напишите больше тестовых примеров, чтобы достичь хорошего охвата.

Обратите внимание, что я сказал "хорошо", а не "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*.

Ответ 21

Почти все.

Вы читали Code Complete? (Потому что StackOverflow говорит, что вы действительно should.) В главе 22 говорится:" 100% охват заявлений - хорошее начало, но этого мало. В остальной части главы объясняется, как определить, какие дополнительные тесты нужно добавить. Здесь короткий дегустатор.

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

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

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

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