Технологии тестирования программ

Дав рабочее определение тестированию, необходимо ответить на во­прос – возможно ли обнаружить все ошибки программы. Оказывается, что ответ будет отрицательным даже для самых тривиальных программ. В об­щем случае невозможно обнаружить все ошибки программы. А это в свою очередь порождает экономические проблемы, задачи, связанные с функ­циями человека в процессе отладки, способы построения тестов.

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

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

При таком подходе обнаружение всех ошибок в программе может быть достигнуто, если в качестве тестовых наборов использовать все воз­можные наборы входных данных. Следовательно, мы приходим к выводу, что для исчерпывающею тестирования программы требуется бесконечное число тестов.

Поскольку исчерпывающее тестирование исключается, нашей целью должна стать максимизация результативности капиталовложений в тести­рование (иными словами, максимизация числа ошибок, обнаруживаемых одним тестом). Для этого мы можем рассматривать внутреннюю структуру программы и делать некоторые разумные, но, конечно, не обладающие полной гарантией достоверности предположения (например, разумно предположить, что если программа сравнивает два числа a и b, и в про­цессе тестирования она сочла равными a, принявшее значение 3, и b, при­нявшее значение 3, то она также сочтет равными a, принявшее значение 5, и b, принявшее значение 5).

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

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

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

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

Конечно, в реальных программах условные переходы не могут быть взаимно независимы, т.е. число маршрутов исполнения будет несколько меньше. С другой стороны, реальные программы значительно больше, чем простая программа, представленная на рис. 3.4. Следовательно, исчерпы­вающее тестирование маршрутов, как и исчерпывающее входное тестиро­вание, не только невыполнимо, но и невозможно.

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

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

IF ((А –В) < EPSILON) ...

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

 


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

 

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