Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Липаев В.В. Программная инженерия

.pdf
Скачиваний:
719
Добавлен:
02.05.2014
Размер:
10.14 Mб
Скачать

Лекция 13. Верификация, тестирование и оценивание корректности компонентов

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

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

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

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

Слолсность тестирования программных компонентов (функцио­ нальных групп программ) определяется суммарной сложностью модулей и межмодульных связей по управлению и по информации. Каждый мо­ дуль должен тестироваться автономно до включения в группу программ и частично в составе группы. Затраты на тестирование модулей в составе

400

13.5. Примеры оценок сложности тестирования программ

группы программ должны учитывать относительные суммарные затраты на тестирование всех входящих модулей с коэффициентом di,< \, завися­ щим от степени предшествующей проверки модуля. Если модули автономно не тестировались (например, при нисходящем тестировании), то (i^ = 1 и затраты на тестирование каждого модуля войдут в затраты при тестирова­ нии группы программ в полном объеме. При тщательном автономном тестировании модулей можно полагать dj, = 0,1—0,01, т.е. в составе ПС затраты на тестирование каждого из модулей составляют несколько про­ центов.

13.5. Примеры оценок сложности тестирования программ

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

На рис. 13.7 представлен пример исходного графа модуля програм­ мы, содержащего 14 вершин, 20 дуг и 3 цикла. Такая программа сравни­ тельно невысокой сложности содержит около 30—50 операторов на языке высокого уровня и может рассматриваться как достаточно типичная. Для полной проверки модуля по первому критерию достаточно четырех марш­ рутов. По этому критерию гарантируется проверка всех передач управле­ ния между операторами программы и каждого оператора не менее одного раза. Самый длинный по числу вершин маршрут не охватывает только 3 вершины из 14 и только 6 дуг из 20.

После проверки еще двух маршрутов вне контроля остаются одна вершина и две дуги. Однако при этом критерии не учитывается комбина-

401

Лекция 13. Верификация, тестирование и оценивание корректности компонентов

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

13.5. Примеры оценок сложности тестирования программ

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

Наиболее глубокий третий критерий проверки и определения слож­ ности тестирования структуры программы включает требования однократ­ ной проверки не только линейно независимых, но и всех линейно зависи­ мых циклов и ациклических маршрутов. Он заключается в анализе хотя бы один раз каждого из реальных ациклических маршрутов исходного графа программы и каждого цикла, достижимого из всех этих маршрутов. Для примера графа программы, представленного на рис. 13.7, по данному критерию необходимо исполнить 6 ациклических и 5 маршрутов, из кото­ рых достижимы элементарные циклы. Для реализации выделенных марш­ рутов в 11 тестах необходимо в совокупности задать 66 условий. При этом особенностью четырех последних маршрутов с циклами, так же как соот­ ветствующих им ациклических маршрутов, является полный перебор со­ четаний ветвлений в 3 и 12 вершинах.

В реальных программах некоторые маршруты могут оказаться нереа­ лизуемыми из-за несовместимости условий, которые последовательно ана­ лизируется в разных вершинах (например, вершины 3 и 12 на рис. 13.7). С другой стороны, для каждого реализуемого маршрута может быть необхо­ димой проверка при нескольких прохождениях циклов и нескольких зна­ чениях каждой обрабатываемой переменной. Особенно важно проверять циклы с условным выходом на одном-двух промежуточных, а также при максимальном и минимальном числе витков исполнения циклов. В ре­ зультате показатель сложности, число необходимых тестов и длительнос­ ти проверки соответственно возрастают.

403

Лекция 13. Верификация, тестирование и оценивание корректности компонентов

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

Анализ проведен для двух типов ациклических графов при выделе­ нии маршрутов по критерию охвата каждой дуги графа программы хотя бы один раз Xi и по критерию выделения всех маршрутов, различающихся хотя бы одной дугой Хг. В числе выбранных содержатся структуры, охва­ тывающие наиболее типовые варианты компонентов графов программ. Структуры различались шириной графов, вследствие чего отличались чис­ ло маршрутов и сложность полного тестирования таких структур. Слож­ ность тестирования ПМ оценивалась по числу маршрутов исполнения про­ граммы, отражающих число тестов, необходимых для полной проверки корректности структуры модуля. Кроме того, в качестве показателя струк­ турной сложности тестирования анализировалось суммарное число

условий, которое необходимо задать в тестах (сложность тестирования) для проверки модуля.

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

Структурная сложность тестирования графов ПМ изменяется в более широком диапазоне, чем число маршрутов, что определило выбор

404

13.5. Примеры оценок сложности тестирования программ

логарифмического масштаба по оси ординат на рис. 13.8. Наименьшей структурной сложностью характеризуется граф Гз при выделении марш­ рутов по первому критерию. Для таких графов структурная сложность возрастает практически линейно в зависимости от числа вершин. При выделении маршрутов по второму критерию тот же граф характеризуется наибольшей структурной сложностью. При 30 и более вершинах струк­ турная сложность этого графа почти на порядок выше, чем графа Fj при том же числе вершин. Относительная разница сложности тестирования этих графов при критерии Х2 приблизительно сохраняется при изменении числа вершин от 16 до 100. Такое распределение значений структурной сложности от типов графов обусловлено различием их ширины. Так как число маршрутов при критерии Xj в зависимости от числа вершин во всех графах изменяется практически одинаково, то определяющим различия структурной сложности является число условий, анализируемых в каждом маршруте. Во всех маршрутах графа Г2 участвуют все его вершины, что определило его наибольшую структурную сложность.

> ^

1

^ - - "^

г, (XI Xi)

г^

'VWS

Рис. 13.8

На рис. 13.8 точками (с указанием числа совпадающих значений) отмечены значения структурной сложности тестирования около 70 реаль-

405

Лекция 13. Верификация, тестирование и оценивание корректности компонентов

ных ациклических ПМ в двух системах. Характеристики абстрактных гра­ фов Г] и Гг действительно охватывают диапазон изменения показателей сложности тестов для реальных программ, которые по каждому критерию группируются приблизительно посередине. Максимальная сложность тес­ тов по второму критерию для произвольных ациклических программ близка к числу вершин в квадрате. По тому же критерию минимальная сложность тестов для широких структурированных графов типа «дерево» на порядок меньше максимальной сложности. Для усредненных оценок сложности полных тестов произвольных ациклических программ хорошее приближе­ ние для инженерных оценок при п^> \0 дает выражение п^Уз (штриховая линия на рис. 13.8). Характерно, что увеличение числа вершин в 4 раза (от 32 до 128) для рассмотренных графов приводит к возрастанию структур­ ной сложности более чем в 10 раз. Если же программу, имеющую 128 вершин, разделить на 4 модуля, то их суммарная сложность практически равна только учетверенной сложности модулей, содержащих по 32 верши­ ны. Исследованные реальные ПМ 80% случаев содержат не более 10 вер­ шин и имеют структурную сложность тестирования < 50.

Показано, что при разработке ПМ целесообразно учитывать рацио­ нальное ограничение размеров модулей на уровне трехсот строк тек­ ста, что соответствует приблизительно тридцати альтернативам в ацик­ лических программах. При этом для полного покрытия таких ПМ тестами необходимо задавать до 1000 условий, что обычно достаточно трудно или невозможно реализовать практически. В среднем полное тестирование про­ грамм с 30-ю вершинами ветвления производится тестами с суммарной сложностью около 300—500. Суммарная сложность тестов, необходимых для полного тестирования программ, имеющих различные структуры, мо­ жет отличаться в несколько раз.

Поэтому при разработке ПМ рекомендован рациональный размер программ модулей в пределах 100—200 строк текста, для полного тести­ рования которых достаточно использовать 10—20 тестов с суммарным числом условий ветвления до 100. При превышении рекомендуемых раз­ меров ПМ их трудно протестировать полностью и целесообразно делить на более мелкие компоненты, доступные для практически полного по­ крытия тестами.

Для получения практических оценок достигаемой корректности про­ граммы при покрытии тестами ее структуры необходимо оценить диапа-

406

13.5. Примеры оценок сложности тестирования программ

ЗОН реальной вероятности ошибки, допускаемой квалифицированным программистом первично в каждой дуге графа программы. Эксперимен­ тально установлено, что для слабо структурированных программ число ошибок, выявляемых в процессе тестирования программных модулей, со­ ставляет около одного процента числа строк текста этих модулей. Для программ обработки информации и управления число условных перехо­ дов составляет около 10% числа строк в программе, т.е. ветвление в про­ грамме происходит в среднем после исполнения 10 строк текста линейных участков. Следовдтельно, порядка 10% линейных участков (или дуг в гра­ фе) программных модулей могут содержать первоначально ошибки перед тестированием, что соответствует вероятности qij ~ 0,1.

Использование правил структурного программирования, специфика­ ций требований на модули и группы программ, а также современной тех­ нологии программирования позволяет снизить первичную вероятность ошибок приблизительно на порядок, т.е. до уровня q^j ~ 0,01. Поэтому оценивание стратегий тестирования и достигаемой при этом корректности целесообразно проводить в диапазоне q^j = 0,1—0,01, соответствующем практически наихудшим и наилучшим значениям вероятностей ошибок в дуге до тестирования.

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

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

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

407

Лекция 13. Верификация, тестирование и оценивание корректности компонентов

вания достигнутой структурной корректности программы по каждо­ му из критериев выбора маршрутов.

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

иПС в целом.

13.6.Тестирование обработки потоков данных программными компонентами

Функционирование любой программы можно рассматривать как об­ работку потока данных, передаваемых от входа в программу к ее выхо­ ду (см. п. 13.1). Входные данные последовательно используются для опре­ деления ряда промежуточных результатов вплоть до получения необходи­ мого набора выходных данных. Задача тестирования и анализа потока данных состоит в установлении корректности их обработки и в выявлении ошибок в тестируемой программе. Эта задача может решаться статичес­ ки — без исполнения программы (анализом по ее тексту) и динамически — путем реального исполнения программы на ЭВМ в машинных кодах при различных исходных данных.

Наборы действий по преобразованию исходных данных в выходные могут быть формализованы диаграммами потоков данных (DFD — Data Flow Diagrams). Для этого применяется система графических элементов, содержаш[их квадратики с описаниями сущностей и номерами, а также соединяющие их стрелки процессов:

внешние сущности — объекты, являющиеся источниками или по­ требителями информации, идентифицируемые их содержанием и номерами;

процессы, перемещающие объекты от одного действия к другому, преобразующие исходные данные в результирующие;

408

13.6.Тестирование обработки потоков данных программными компонентами

накопители объектов или данных, где временно они размещаются на хранение;

потоки данных — информация, передаваемая от источника к по­ требителю.

Для построения DFD-диаграмм формализованы синтаксис и семанти­ ка графических элементов: отражающих движение объектов — процеду­ ры программ; описаний внешних сущностей — источников и потребите­ лей данных; их хранения. Рекомендуется вначале определять набор дей­ ствий, описывающих, что должны выполнять процедуры программы. Затем строить модель окружения — внешние сущности, порождающие процес­ сы и специфическое поведение при обработке данных. Наборы простей­ ших DFD-диаграмм — операторов программы, объединяются в иерархи­ ческие структуры, отражающие потоки данных в программных модулях или функциональных компонентах из ряда модулей.

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

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

работки данных:

полностью изменяющей область определения и значения результа­ тов обработки;

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

409