Научная статья на тему 'Тестирование программных комплексов на основе принципа декомпозиции'

Тестирование программных комплексов на основе принципа декомпозиции Текст научной статьи по специальности «Компьютерные и информационные науки»

CC BY
946
72
i Надоели баннеры? Вы всегда можете отключить рекламу.
Ключевые слова
ПРОГРАММНЫЙ КОМПЛЕКС / ТЕСТИРОВАНИЕ / ДЕКОМПОЗИЦИЯ / АЛГОРИТМ / ГРАФ / SOFTWARE PACKAGE / TESTING / DECOMPOSITION / ALGORITHM / GRAPH

Аннотация научной статьи по компьютерным и информационным наукам, автор научной работы — Базин Александр Сергеевич

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

i Надоели баннеры? Вы всегда можете отключить рекламу.

Похожие темы научных работ по компьютерным и информационным наукам , автор научной работы — Базин Александр Сергеевич

iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.
i Надоели баннеры? Вы всегда можете отключить рекламу.

TESTING SOFTWARE PACKAGES ON THE BASIS OF DECOMPOSITION PRINCIPLE

An algorithm for software package testing has been developed which increases testing efficiency through the use of the decomposition principle.

Текст научной работы на тему «Тестирование программных комплексов на основе принципа декомпозиции»

ИНФОРМАЦИОННЫЕ ТЕХНОЛОГИИ

УДК 681.518.5

ТЕСТИРОВАНИЕ ПРОГРАММНЫХ КОМПЛЕКСОВ НА ОСНОВЕ ПРИНЦИПА ДЕКОМПОЗИЦИИ

© 2011 г. А. С. Базин

Нижегородский государственный технический университет им. Р.Е. Алексеева

alexander.bazin@gmail. com

Пкступнла вредасцню 12.02.2011

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

Ключевые слква: программный комплекс, тестирование, декомпозиция, алгоритм, граф.

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

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

1. Для программных комплексов практически всегда отсутствует точный эталонный образец результатов тестирования, как для исправных систем, так и для систем с наличием тех или иных дефектов. Поэтому при тестировании приходится использовать в качестве эталонных данных косвенные данные, которые не могут полностью отразить основные характеристики и функции комплекса.

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

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

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

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

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

• разработка математической модели, отражающей структурные свойства программного комплекса;

• разработка диагностической модели программного комплекса с целью локализации местоположения ошибки в программном коде;

• разработка соответствующих алгоритмов.

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

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

Использование иерархических структур позволяет стратифицировать связи между компонентами комплекса.

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

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

В основе алгоритма разбиения комплекса на модули лежит количественная характеристика программных процедур комплекса - «популярность» процедур в комплексе.

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

В дальнейшем «популярностью» процедуры / будем называть количество процедур g, которые вызывают процедуру /. «Популярность» процедуры может быть также определена как количество синтаксических вызовов этой процедуры.

Алгоритм начинается с построения графа «популярности» процедур комплекса - взвешенного направленного графа G = (V, Е) с множеством узлов V = S, где S — множество процедур комплекса и направленные дуги множества Е обозначают вызовы между процедурами в комплексе. Вес каждой дуги равен «популярности» вызываемой процедуры (т.е. «популярности» процедуры, соответствующей узлу назначения в дуге).

Далее алгоритм можно описать следующим образом:

1. Выбираем значение с «популярности» процедур. На первой итерации алгоритма значение с определяется пользователем на основе эмпирических соображений (результаты вычислительных экспериментов показывают, что при с=3 на первой итерации алгоритма получаем оптимальное разбиение комплекса на модули), а при следующих итерациях значение с выбирается равным максимальному весу дуги в графе G.

2. Временно удаляем узлы в графе «популярности» процедур, для которых «популярность» соответствующей процедуры выше выбранной «популярности» процедур с, образуя граф G'.

3. В полученном графе G' находим узлы, для которых полустепень захода равна нулю.

4. Далее вычисляется множество достижимых узлов в G' из найденных узлов с нулевой полустепенью захода; если достижим хотя бы один узел, полученный набор узлов определяется как единое целое, модуль. Узлы, соответствующие процедурам, которые выделяются в модули, удаляются из графа G и из подграфа G'. Если не достижим ни один узел из найденного узла, узел удаляется из графа G'.

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

Продемонстрируем предложенный алгоритм на простом примере.

1) Рассмотрим граф «популярности» процедур G, изображенный на рисунке.

2) Выбираем значение «популярности» процедур с=2 и временно удаляем узлы в графе G, для которых «популярность» соответствующей процедуры выше выбранной «популярности» процедур с=2. Удаляем узлы 2 и 13, так как «популярность» соответствующих процедур равна трем. Получаем граф G'.

3) В полученном графе G' находим узлы, для которых полустепень захода равна нулю, такими узлами являются 1, 3 и 10. Вычисляем

Рис. Пример разбиения управляющего графа программного комплекса на подграфы

множество достижимых узлов в G' из найденных 1, 3 и 10. Из узла 1 не достижим ни один узел графа G', удаляем этот узел из графа G'. Из узла 3 достижимы узлы 4-9, в таком случае объединяем узлы 3-9 в модуль и удаляем их из графов G и G'. Из узла 10 достижимы узлы 11 и 12 - объединяем узлы 10-12 в новый модуль и удаляем их из графов G и G'. Граф G' оказался пустым.

4) В результате предыдущих шагов в графе G осталось всего 3 вершины - 1, 2, 13. В этом графе находим узлы, для которых полустепень захода равна нулю, такими узлами являются 1 и 13. Вычисляем множество достижимых узлов в графе G из найденных узлов 1 и 13. Из узла 1 достижим узел 2, объединяем узлы 1 и 2 в модуль и удаляем из графа G. Осталась единственная нерассмотренная вершина 13, из нее не достижим ни один узел графа G, но, тем не менее, выделяем ее в отдельный модуль.

Таким образом, граф «популярности» G разбит на 4 подграфа.

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

С помощью автоматизированной технологии генерации тестов можно обнаружить стандартные ошибки, такие, как неожиданное завершение программы (crash), утверждения о нарушениях логики работы программы (assertion viola-

tion) и незавершение программы. Во время тестирования осуществляется направленный поиск (разновидность динамического формирования тестов) [1, 2]. Начиная со случайных входных данных, во время исполнения текущего теста вычисляется входной вектор для следующего исполнения. Этот вектор содержит значения, которые являются решением символических связей, данное значение состоит из предикатов операторов ветвления (операторов перехода), накопленных в течение предыдущего исполнения. Новый входной вектор стремится выполнить программу вдоль нового пути. Повторяя этот процесс, направленный поиск стремится охватить все возможные пути исполнения программы.

Для автоматизированной генерации тестов предлагается использовать утилиту CUTE [3]. Данная утилита реализует символьное выполнение программ. Также CUTE позволяет обозревать все возможные пути исполнения программы и предоставляет статистику покрытия кода тестируемой программы.

Для демонстрации эффективности предложенного автором подхода был выбран программный комплекс Open SCTP, разработка протокола передачи с управлением потока (Stream Control Transmission Protocol) с открытым исходным кодом. Реализация данного комплекса на языке программирования С доступна на сайте http://www.openss7.org.

Тaблнцa

Результаты вычислительного эксперимента

Алгоритм разбиения Количество выделенных модулей Покрытие кода тестами при тестировании модулей комплекса

Случайное разбиение комплекса на 6 модулей 6 0.44

Случайное разбиение комплекса на 11 модулей 11 0.49

Случайное разбиение комплекса на 16 модулей 16 0.32

Разработанный автором алгоритм 18 0.85

Случайное разбиение комплекса на 21 модуль 21 0.5

Случайное разбиение комплекса на 26 модулей 26 0.49

Алгоритм Fiductia-Mattheyses З0 0.75

Случайное разбиение комплекса на 31 модуль З1 0.52

Алгоритм Kemighan-Lin З5 0.65

Случайное разбиение комплекса на 36 модулей З6 0.58

Случайное разбиение комплекса на 41 модуль 41 0.52

Случайное разбиение комплекса на 46 модулей 46 0.56

Случайное разбиение комплекса на 51 модуль 51 0.68

Для тестирования был выделен программный код, отвечающий за кодирование и декодирование сообщений SCTP протокола, данный фрагмент кода состоит из 70 процедур (—10500 строчек программного кода).

Построив управляющий граф для данного комплекса, можно увидеть, что 25 из 70 процедур мало «популярны» - вызываются лишь одной или двумя другими процедурами, 22 процедуры вызываются 5-ю другими процедурами, 15 процедур вызываются 10-ю другими процедурами, и 8 процедур очень «популярны», вызываются 20-ю разными процедурами.

Алгоритм, предложенный автором, разбил данный комплекс на 18 модулей. Далее тестирование полученных модулей проводилось утилитой CUTE, которая генерировала до 1000 различных входных данных для каждого модуля. В результате было обнаружено несколько ошибок в реализации протокола SCTP, которые могли привести к неожиданному завершению работы комплекса. Покрытие исходного кода комплекса тестами составило 85%.

Для подтверждения эффективности алгоритма, предложенного автором, был проведен следующий эксперимент. Описанный выше программный комплекс был разделен на модули разными алгоритмами (случайное разделение на N частей, алгоритм Kernighan-Lin [4], алгоритм Fiduccia-Mattheyses [5]), и далее полученные

модули тестировались программой CUTE, генерировалась 1000 различных входных данных для каждого модуля. В процессе тестирования велась статистика тестового покрытия. Результаты эксперимента приведены в таблице.

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

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

CnucoK numepamypbi

1. Korel B. A dynamic approach of test data generation // IEEE Conference on Software. IEEE Computer Society Press, 1990. November. P. 311-317.

2. Gupta N., Mathur A.P., and Soffa M.L. Generating test data for branch coverage // Proceedings of the 15-th IEEE International Conference on Automated Software Engineering. IEEE Computer Society Press, 2000. September. P. 219-227.

3. Sen K., Marinov D., and Agha G. CUTE: A concolic unit testing engine for C // Proceedings of the

10-th European software engineering conference held jointly with 13-th ACM SIGSOFT International symposium on foundations of software engineering, 2005. P. 263-272.

4. Pothen A., Simon H., and Liou K.-P. Partitioning sparse matrices with eigenvectors of graphs // SIAM Journal of Matrix Analysis and Applications. 1990. №

11. P. 430-452.

5. Mattheyses R.M. and Fiduccia C.M. A linear time heuristic for improving network partitions // In: Proceedings 19-th IEEE Design Automation Conference, 1982. P. 175-181.

TESTING SOFTWARE PACKAGES ON THE BASIS OF DECOMPOSITION PRINCIPLE

A.S. Bazin

An algorithm for software package testing has been developed which increases testing efficiency through the use of the decomposition principle.

Keywords: software package, testing, decomposition, algorithm, graph.

i Надоели баннеры? Вы всегда можете отключить рекламу.