Программирование. Принципы и практика использования C++ Исправленное издание, стр. 370
Простое выполнение сотен (или десятков тысяч) тестов, созданных на основе прошлых отчетов об ошибках, может выглядеть не очень систематизированным, но на самом деле в этом случае мы действительно целенаправленно используем опыт пользователей и разработчиков. Набор регрессивных тестов представляет собой главную часть коллективной памяти группы разработчиков. При разработке крупных систем мы просто не можем рассчитывать на постоянный контакт с разработчиками исходных кодов, чтобы они объяснили нам детали проектирования и реализации. Именно регрессивные тесты не позволяют системе отклоняться от линии поведения, согласованной с разработчиками и пользователями.
26.3.2. Модульные тесты
Однако достаточно слов! Рассмотрим конкретный пример: протестируем программу для бинарного поиска. Ее спецификация из стандарта ISO приведена ниже (раздел 25.3.3.4).
template<class ForwardIterator, class T> bool binary_search(ForwardIterator first, ForwardIterator last,const T& value); template<class ForwardIterator, class T, class Compare> bool binary_search(ForwardIterator first, ForwardIterator last,const T& value,Compare comp);Требует. Элементы
e[first, last]e<value!(value<e)comp(e,value)!comp(value,e)e[first,last]e<value!(value<e)comp(e,value)!comp(value,e)Возвращает. Значение
true[first,last]i!(*I<value)&&!(value<*i)comp(*i,value)==false&&comp(value,*i)==falseСложность. Не более
log(last–first)+2Нельзя сказать, что непосвященному человеку легко читать эту формальную (ну хорошо, полуформальную) спецификацию. Однако, если вы действительно выполнили упражнение, посвященное проектированию и реализации бинарного поиска, которое мы настоятельно рекомендовали сделать в начале главы, то уже должны хорошо понимать, что происходит при бинарном поиске и как его тестировать. Данная (стандартная) версия функции для бинарного поиска получает в качестве аргументов пару однонаправленных итераторов (см. раздел 20.10.1) и определенное значение и возвращает значение
true<binary_searchЗдесь мы столкнемся только с ошибками, которые не перехватывает компилятор, поэтому примеры, подобные этому, для кого-то станут проблемой.
binary_search(1,4,5); // ошибка: int — это не однонаправленный // итераторvector<int> v(10);binary_search(v.begin(),v.end(),"7"); // ошибка: невозможно найти // строку // в векторе целых чиселbinary_search(v.begin(),v.end()); // ошибка: забыли значение
binary_search()• Тест на возможные ошибки (находит большинство ошибок).
• Тест на опасные ошибки (находит ошибки, имеющие наихудшие возможные последствия).
Под опасными мы подразумеваем ошибки, которые могут иметь самые ужасные последствия. В целом это понятие носит неопределенный характер, но для конкретных программ его можно уточнить. Например, если рассматривать бинарный поиск изолированно от других задач, то все ошибки могут быть одинаково опасными. Но если мы используем функцию
binary_searchbinary_searchbinary_searchЛучшие тестировщики не только методичные, но и изворотливые люди (в хорошем смысле, конечно).
26.3.2.1. Стратегия тестирования
С чего мы начинаем испытание функции
binary_search[first,last]binary_search[first,last]last<firstbinary_searchbinary_searchbinary_search