Тестирование программы как белого ящика

Стратегия белого ящика, или стратегия тестирования, управляемого логикой программы, позволяет исследовать внутреннюю структуру программы. В этом случае тес­ти­рую­щий получает тестовые данные путем анализа логики программы (к сожалению, здесь часто не используется спецификация программы).

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

Последнее утверждение имеет два слабых пункта. Один из них состоит в том, что число не повторяющих друг друга маршрутов в программе — астрономическое. Чтобы убедиться в этом, рассмотрим представленный на рис. 6.1 граф передач управления простейшей программы. Каждая вершина или кружок обозначают участок программы, содержащий последовательность линейных операторов, которая может заканчиваться оператором ветвления. Дуги, оканчивающиеся стрелками, соответствуют передачам управления. По-ви­ди­мо­му, граф описывает программу из 10–20 операторов, включая цикл DO, который исполняется не менее 20 раз. Внутри цикла имеется несколько операторов IF. Для того, чтобы определять число неповторяющихся маршрутов при исполнении программы, подсчитаем число неповторяющихся маршрутов из точки A в B в предположении, что все приказы взаимно независимы. Это число вычисляется как сумма 520 + 519 + … + 51 = 100 триллионов, где 5 — число путей внутри цикла. Приведем такой пример: если допустить, что на составление каждого теста мы тра­тим пять минут, то для построения набора тестов нам потребуется примерно один миллиард лет.

Рис. 6.1 — Граф передач управления небольшой программы

Второй слабый пункт утверждения заключается в том, что, хотя исчерпывающее тестирование маршрутов является полным тестом и хотя каждый маршрут программы может быть проверен, сама программа может содержать ошибки. Это объясняется следующим образом. Во-пер­вых, исчерпывающее тестирование маршрутов не может дать гарантии того, что программа соответствует описанию. Например, вместо требуемой программы сортировки по возрастанию случайно была написана программа сортировки по убыванию. В этом случае ценность тестирования маршрутов невелика, поскольку после тестирования в программе окажется одна ошибка, т.е. программа неверна. Во-вто­рых, программа может быть неверной в силу того, что пропущены некоторые маршруты. Исчерпывающее тестирование маршрутов не обнаружит их отсутствия. В-третьих, исчерпывающее тестирование маршрутов не может обнаружить ошибок, появление которых зависит от обрабатываемых данных. Существует множество примеров таких ошибок. Приведем один из них. Допустим, в программе необходимо выполнить сравнение двух чисел на сходимость, т.е. определить, является ли разность между двумя числами меньше предварительно определенного числа. Может быть написано выражение

IF ((A – B) < EPSILON)…

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

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