Систематическое тестирование.
Постепенное тестирование каждого написанного модуля существенно лучше тестирования методом «большого скачка», когда сначала пишется вся программа, а затем она тестируется целиком.
Каждый модуль после написания должен быть оттестирован, а после включения любого модуля в цепочку работающих модулей необходимо оттестировать их взаимодействие.
При тестировании отдельного модуля в первую очередь тестированию подлежат самые простые и чаще всего используемые модули. При этом, на каждом этапе объем тестируемого кода должен увеличиваться. При таких тестах помимо граничных условий систематически тестируются отдельные случаи.
Даже при разработке самых простых программ может понадобиться большое количество тестов. Например, модуль, решающий квадратные уравнения должен быть подвергнут не менее чем 7 тестам – и это не считая «защиты от дурака» и проверки диапазонов арифметических значений.
При систематическом тестировании работы двоичного поиска в целочисленном массиве нужно протестировать все отдельные случаи в массиве, содержащем не менее пяти элементов.
Количество случаев, которые необходимо протестировать достаточно велико, чтобы написать программу, которая автоматически генерирует массив, подвергает тестированию, даже с учетом того, что при реальной эксплуатации программы автоматическая генерация не нужна.
При проведении тестов необходимо знать правильный результат, даже там, где этот результат получить трудно.
Если существует несколько независимых реализаций той или иной программы – то они должны давать одни и те же результаты на одних и тех же тестах. При проведении последовательных тестов каждое выражение в программе должно быть выполнено хотя бы один раз.
Стрессовое тестирование.
Под стрессовым тестированием понимается проверка программ большими объемами данных, которые зачастую удобнее сгенерировать компьютером. Большие объемы сами по себе могут стать причинами сбоев, вызывая переполнение буферов ввода, массивов, счетчиков. Большие объемы данных также очень полезны при поиске неоправданных ограничений в размерах структур данных.
Если при тестировании вводятся только осмысленные реалистичные данные, то большинство ошибок ввода никогда не случится и, следовательно, обрабатывающий их код не будет исполнен, а он может быть ошибочным.
Но важно не доводить дело до абсурда и не тратить время на исправление ошибок в ситуациях, когда их возникновение крайне маловероятно.
Некоторые виды тестов основаны на введении преднамеренно некорректных данных, так как любой не контролируемый ввод является потенциальной лазейкой для взлома системы.
Еще одним фактором, на который нужно обратить внимание при тестировании переполнений является преобразование типов.
Хорошие тесты и тестовые случаи часто могут быть использованы для большого количества программ. Например, каждая программа, читающая файлы, должна быть проверена вводом пустого файла. Каждая программа, читающая текст, должна быть оттестирована двоичным вводом, каждая программа, читающая строки текстов, должна быть проверена вводом очень длинных строк, пустых строк и файлами без употребления символа перевода строки вообще.
Автоматизация тестирования.
При большом количестве тестов, которые необходимо выполнить, полезно написать программу, которая последовательно запускает эти тесты.
Одной из основных форм автоматизации является возвратное тестирование, при котором выполняется последовательность тестов, сравнивающих очередную новую версию программы с предыдущей. Основное назначение возвратного тестирования – убедиться в том, что поведение программы изменилось только в предусмотренных рамках. В дополнение к возвратным тестам полезно использовать и замкнутые тесты, которые содержат в себе и вводимые данные, и ожидаемые результаты.
Существуют также инструменты, которые взаимодействуют с программой во время ее выполнения. Их основная цель – измерить качество тестирования, определить, в какой мере тесты проверяют алгоритм программы. Например, можно контролировать выполнение каждой подпрограммы, подсчитывая, сколько раз она вызывалась. Можно также учесть сколько раз выполняется каждый оператор исходной программы, или во всех ли направлениях выполняется каждый условный переход.
Часто такая статистика накапливается в отдельном файле или базе данных, что полезно при комплексном тестировании системы. Для автоматизации тестов разрабатываются также специальные языки.