4.4. Тестирование методом черного ящика
Тестирование методом «черного ящика» – это простая технология, которая может оказать значительный эффект на качество кода. В статье [15] показывается преднамеренное внедрение случайных неправильные данные в приложение и неверные результаты работы. Также объясняется использование технологий создания безопасного кода: контрольных сумм, хранилищ данных XML и проверки кода, которые защищают программы от случайных данных. Кроте того, демонстрируется технология защиты, а именно упражнение по имитации подходов взломщиков кода: поврежденные файлов, которые могут вызвать сбой какой-либо программной системы, например Microsoft Word. Несколько несоответствующих байтов – и работа приложения более невозможна. Раньше, в эпоху операционных систем без механизмов защиты памяти, из-за этого могла прекратиться работа и всего компьютера. Почему Word не может распознать, что полученные данные не годятся, и просто выдать сообщение об ошибке? Почему это приложение повреждает свой собственный стек и прочие области памяти только из-за того, что поменялись несколько битов? Word – это не единственная программа, которая ведет себя столь ужасно при встрече с неверно сформированными файлами.
При тестировании методом «черного ящика» вы атакуете программу случайными неверными данными (которые называются искажением (fuzz)), а затем ждете и смотрите, что сломалось. Хитрость такого метода заключается в том, что тестирование нелогично. Вместо того, чтобы пытаться угадать, какие данные могут спровоцировать ошибку (как обычно поступают люди, занимающиеся тестированием), автоматизированный тест просто выдает программе как можно более случайный «мусор». Ошибки, определяемые подобным тестированием, обычно шокируют программистов, поскольку ни один логически мыслящий человек не мог их даже ожидать.
Простая методика может выявлять в программах важные ошибки. Она может находить те виды отказов, которые возникают при реальной эксплуатации, и сигнализировать о возможных путях атак, которые необходимо перекрыть еще до того, как программный продукт попадет к заказчикам.
Тестирование по методу «черного ящика» реализовать довольно просто:
- Подготовьте корректный файл, предназначенный для ввода в программу;
- Замените некоторые части этого файла случайными данными;
- Откройте файл в программе;
- Посмотрите, что идет не так.
Случайные данные можно менять любыми способами. Например, можно менять не просто часть файла, а весь файл заменить случайными данными. Можно ограничить содержимое файла лишь ASCII–текстом либо ненулевыми байтами. Главное – это подать приложению побольше случайных данных и посмотреть, что будет.
Хотя начальные тесты можно проводить и вручную, для достижения максимального эффекта тестирование следует автоматизировать. В этом случае сначала нужно определить правильное поведение при ошибке, когда приложение получает неверные входные данные. Если обнаруживается, что программа вообще не побеспокоилась определить, что случилось, когда поданные входные неверны, то это первая ошибка. Затем подаются случайные данные в программу до тех пор, пока не найдется файл, в ответ на который не появляется правильное диалоговое окно ошибки, сообщение, исключительная ситуация и т.д. необходимо сохранить и зарегистрировать этот файл, чтобы позже можно было воспроизвести проблему. алгоритм повторяется.
Хотя тестирование по методу «черного ящика» обычно требует некоторого ручного написания кода, существуют инструментальные средства, которые могут помочь в этом. Например, Листинг 1 демонстрирует простой Java-класс,™ который случайным образом модифицирует определенную длину файла. Обычно меняют файл где-нибудь после первых нескольких байт, поскольку программы имеют тенденцию определять ошибку в самом начале данных, а не потом. (Ищутся ошибки, которые программа не проверяет, а не те, с которыми она справляется.)
Исказить файл легко. Передать его приложению обычно ненамного труднее. Для написания этой части теста часто наилучшим выбором будут такие языки сценариев, как AppleScript или Perl. Для программ с графическим интерфейсом самой трудной частью может быть распознавание того факта, что приложение указало правильный режим ошибки. Иногда проще всего посадить кого-нибудь перед монитором и заставить его помечать каждый тест как удачный или неудачный. Обязательно отдельно называйте и сохраняйте все сгенерированные случайные контрольные примеры, чтобы потом можно было воспроизвести все ошибки, обнаруженные с помощью этой процедуры.
Тестирование по методу «черного ящика» может обнаружить наличие ошибок в программе. Оно не доказывает, что таких ошибок в программе нет. Однако проведение такого тестирования значительно повышает уверенность в том, что приложение надежно и безопасно по отношению к непредвиденным входным данным. Если тестирование программы по этому методу проводилось в течение 24 часов и она по-прежнему работает, то вряд ли дальнейшие атаки подобного рода вызовут ошибку. (Заметьте: это не невозможно, а просто менее вероятно.) Если тестирование все-таки обнаружило ошибки в программах, их надо исправить. Вместо того, чтобы исправлять случайно обнаруженные ошибки по мере их появления, более продуктивным может быть фундаментальное исправление формата файла на предмет разумного использования контрольных сумм, XML, очистки памяти и/или форматов файлов на базе грамматики.
Тестирование по методу «черного ящика» является важным средством нахождения в программах реальных ошибок. Все программисты, которые настроены на обеспечение безопасности и надежности своих программ, должны пользоваться этим средством.