Строгость в захвате тестов для юнит-тестирования
Допустим, у нас есть простая функция, определенная в псевдо-языке.
List<Numbers> SortNumbers(List<Numbers> unsorted, bool ascending);
Мы передаем несортированный список чисел и логическое значение, указывающее порядок сортировки по возрастанию или убыванию. В ответ мы получаем отсортированный список номеров.
По моему опыту, некоторые люди лучше улавливают граничные условия, чем другие. Вопрос в том, "как вы узнаете, когда вы" закончили "захват контрольных примеров"?
Мы можем начать перечислять случаи сейчас, и некоторые умные люди, несомненно, подумают о "еще одном" случае, который не охватывается ни одним из предыдущих.
5 ответов
Не тратьте слишком много времени, пытаясь думать о каждом граничном состоянии. Ваши тесты не смогут поймать каждую ошибку в первый раз. Идея состоит в том, чтобы иметь довольно хорошие тесты, а затем каждый раз, когда ошибка появляется, напишите новый тест специально для этой ошибки, чтобы вы никогда не услышали о ней снова.
Еще одно замечание, которое я хочу сделать об инструментах покрытия кода. На таких языках, как C# или Java, где у вас много методов get / set и аналогичных методов, вы не должны стрелять на 100%. Это означает, что вы тратите слишком много времени на написание тестов для тривиального кода. Вам нужно только 100% покрытие вашей сложной бизнес-логики. Если ваша полная кодовая база ближе к 70-80% покрытия, вы делаете хорошую работу. Если ваш инструмент покрытия кода позволяет использовать несколько показателей покрытия, лучшим из них является "покрытие блоков", которое измеряет покрытие "базовых блоков". Другие типы - это покрытие класса и метода (которое не дает вам столько информации) и покрытие линии (что слишком мелко).
Как вы узнаете, когда вы закончите захват контрольных примеров?
Вы не можете. Вы не можете добраться до 100%, за исключением самых тривиальных случаев. Также 100% покрытие (линий, путей, условий...) не говорит о том, что вы достигли всех граничных условий.
Самое главное, контрольные примеры не пишут и забывают. Каждый раз, когда вы найдете ошибку, напишите дополнительный тест. Проверьте, что он не работает с оригинальной программой, проверьте, прошел ли он с исправленной программой и добавьте его в свой тестовый набор.
Отрывок из "Искусства тестирования программного обеспечения " Гленфорда Дж. Майерса:
- Если входное условие задает диапазон значений, запишите контрольные примеры для концов диапазона и недопустимые контрольные примеры для ситуаций, выходящих за пределы.
- Если входное условие задает количество значений, запишите контрольные примеры для минимального и максимального количества значений и одного под этими значениями и за их пределами.
- Используйте рекомендацию 1 для каждого выходного условия.
- Используйте рекомендацию 2 для каждого выходного условия.
- Если вход или выход программы является упорядоченным набором, обратите внимание на первый и последний элементы набора.
- Кроме того, используйте свою изобретательность для поиска других граничных условий
(Я вставил только минимум по причинам авторского права.)
Пункты 3. и 4. выше очень важны. Люди склонны забывать граничные условия для выходов. 5. все в порядке. 6. действительно не помогает:-)
Краткий экзамен
Это сложнее, чем кажется. Майерс предлагает этот тест:
Программа считывает три целочисленных значения из диалогового окна ввода. Три значения представляют длины сторон треугольника. Программа отображает сообщение о том, является ли треугольник равносторонним, равнобедренным или равносторонним.
Помните, что равносторонний треугольник - это тот, в котором нет двух равных сторон, тогда как равнобедренный треугольник имеет две равные стороны, а равносторонний треугольник имеет три стороны равной длины. Кроме того, углы, противоположные равным сторонам в равнобедренном треугольнике, также равны (из этого также следует, что стороны, противоположные равным углам в треугольнике, равны), и все углы в равностороннем треугольнике равны.
Напишите ваши тесты. Сколько у тебя? Майерс задает 14 вопросов о вашем наборе тестов и сообщает, что высококвалифицированные профессиональные программы в среднем 7,8 из 14 возможных.
С практической точки зрения я создаю список тестов, которые, по моему мнению, должны пройти до принятия. Я проверяю их и автоматизирую, где это возможно. Исходя из того, сколько времени я оценил для выполнения задания или сколько времени мне дали, я расширяю свое тестовое покрытие, чтобы включить элементы, которые должны пройти до принятия. Конечно, грань между "должен" и "должен" субъективна. После этого я обновляю автоматизированные тесты по мере обнаружения ошибок.
@Keith
Я думаю, что вы прибили это, важно рассмотреть охват кода, если вы хотите увидеть, как "сделали" вы, но я думаю, что 100% - это немного нереальная цель. Стремление к 75-90% даст вам довольно хорошее освещение, не выходя за борт... не проверяйте себя ради достижения 100%, потому что в этот момент вы просто теряете время.
Хороший инструмент покрытия кода действительно помогает.
100% покрытие не означает, что оно определенно адекватно протестировано, но это хороший показатель.
Для.Net NCover неплох, но больше не является открытым исходным кодом.
@Mike Stone - Да, возможно, это должен был быть "высокий охват" - мы стремимся к минимуму 80%, после 95% это обычно уменьшает отдачу, особенно если у вас есть код пояса и скобок.