- •4.9.1. Изменяемость
- •4.9.2. Классы операций
- •98 Глава 4
- •4.9.3. Полнота
- •100 Глава 4
- •4.9.5. Операции egual, similar и copy
- •102 Глава 4
- •104 Глава 4
- •5. Исключительные ситуации
- •108 Глава 5
- •110 Глава 5
- •6.2.1. Сигнализация об исключительных ситуациях
- •5.2.2. Обработка исключительных ситуаций
- •112 Глава 5
- •5.2.3. Предложение resignal
- •6.2.4. Необрабатываемые исключительные ситуации
- •114 Глава 5
- •6.2.3. Предложение resignal
- •5.2.4. Необрабатываемые исключительные ситуации
- •116 Глава 5
- •118 Глава 5
- •118 Глава 5
- •120 Глава 5
- •122 Глава 5
- •124 Глава 5
- •128 Глава 6
- •130 Глава 6
- •6.2.1. Реализация итераторов
- •6.2.2. Использование итераторов
- •132 Глава 6
- •134 Глава 6
- •136 Глава 6
- •138 Глава 6
- •140 Глава 7
- •142 Глава 7
- •7.2. Абстракция данных
- •144 Глава 7
- •146 Глава 7
- •148 Глава 7
- •150 Глава 7
- •7.4. Генераторы
- •162 Глава 7
- •154 Глава 7
- •156 Глава 7
- •162 Глава 8
- •164 Глава 8
- •166 Глава 8
- •168 Глава 8
- •170 Глава 9
- •172 Глава 9
- •174 Глава 9
- •176 Глава 9
- •9.1.3. Пример
- •178 Глава 9
- •180 Глава 9
- •182 Глава 9
- •184 Глава 9
- •186 Глава 9
- •188 Глава 9
- •190 Глава 9
- •192 Глава. 9
- •194 Глава 9
170 Глава 9
пироеание и отладка
Альтернативой верификации служит тестирование. Легко можем убедиться в том, что для некоторого набора входных значений программа работает правильно, простой проверкой ее работы с этими значениями. Если набор возможных входных значений невелик, то возможна полная проверка (для каждого из входных значений). Но для большинства программ входной набор слишком велик (зачастую бесконечен) и полная проверка не представляется возможной. Однако грамотно подобранный набор проверочных значений может в большой степени укрепить нашу уверенность в том, что программа функционирует правильно. Хорошо произведенный тест позволяет выявить большинство ошибок в программах.
В данной главе мы сфокусируем свое внимание на тестировании как методе проверки достоверности программ. Рассмотрим, как выбирать соответствующие тесты и как организовать процесс тестирования. Обсудим также процесс отладки и защитное программирование.
9.1. Тестирование
,i Тестирование представляет собой процесс выполнения про-1 граммы для некоторого набора проверочных значений и сравне-^ ния полученных результатов с ожидаемыми. Цель_тести р о^ания заключается в выявлении возможных ошибок~Тестирование~не указывает^конкретное^местонахождепие ошибки, иго осуществляется при отладке. При тестировании программы мы анализируем взаимосвязь между входными и выходными значениями. При отладке программы мы также заинтересованы в подобной взаимосвязи, однако при этом также обращаем свое внимание на промежуточные результаты вычислений.
Успех тестирования заключается в выборе подходящего набора проверочных данных. Как уже говорилось, исчерпывающее тестирование для большинства программ осуществить невозможно. Например, если программа принимает на входе три целых числа, каждое из которых может изменяться в диапазоне от 1 до 1000, то полная проверка потребует выполнения программы миллион раз. Если каждый прогон программы занимает по времени одну секунду, то на полную проверку потребуется немногим более 31 года.
Что мы можем сделать, учитывая невозможность проверки всех вариантов? Нашей целью является нахождение сравнительно небольшого набора тестов, которые позволят нам получить ту же"йнформацию, что и при полной проверке для всех возможных допустимых значений. Например, предположим, что программа принимает в качестве аргумента целое число, работая одним методом со всеми четными числами, и другим — со всеми
.четными. В этом случае достаточно будет проверки этой про-раммы с каким-либо четным числом, каким-либо нечетным, а »кже с нулем.
M.I. Тестирование методом черного ящика
Тестовые значения выбираются с учетом спецификации и са-^мой реализации программы. При тестировании методом черного 'ящика мы выбираем проверочные да^ные^^сходя^из одлои^спе->.дификации, и не учитываем внутреннюю^структуру 'программы.' 1Т1кой подход р^аспространён во многих инженёрных"дйсципли-нах и имеет ряд существенных преимуществ. Основным преимуществом является то, что процедура тестирования не находится в прямой зависимости от проверяемой компоненты. Например, предположим, что автор программы сделал ошибочное предположение о том, что для некоторого класса входных значений программа использоваться не будет. Исходя из этого, он не включил в программу анализ подобной ситуации. Если данные для проверки были подобраны на основании анализа программы, то вследствие этого неверного предположения проверяющий мог быть легко введен в заблуждение. Вторым преимуществом тестирования такого рода является независимость его по отношению к изменениям в реализации. Проверочные данные не требуется изменять даже в том случае, если в программе были произведены значительные изменения. Наконец, преимуществом является также и то, что результаты тестирования могут быть проанализированы людьми, незнакомыми с внутренней структурой проверяемой программы.
Пути тестирования „спецификации. Хорошим способом реализации тестирования методом черного ящика является тестирование, основанное на анализе различных частей спецификации. Такими частями могут быть предложения requires и effects. Рассмотрим пример тестирования на основе анализа предложения requires. Пусть имеется следующая спецификация:
sqrt = proc (х: real, epsilon: real) returns (ans: real) ; requires х^з 0 & (.00001 < epsilon < .001) effects (х — epsilon ^ ans * ans ^ x + epsilon)
В приведенной спецификации предложение requires представляет собой конъюнкцию двух термов:
1. х>0
2. (.00001 < epsilon < .001).
Для выделения условий, при которых предложение requires будет удовлетворено, мы должны проверить парные комбинации путей, при которых должно удовлетворяться каждое из условий. Поскольку первое условие есть дизъюнкция двух примитивных
