Russian Language English Language

3 Модели и методы для обоснования выбора состав программных средств ВС

3.1 МАТЕМАТИЧЕСКАЯ МОДЕЛЬ СТРУКТУРЫ БАЗЫ ДАННЫХ И ЕЕ РОЛЬ В АВТОМАТИЗАЦИИ ФОРМИРОВАНИЯ SQL-ЗАПРОСОВ

3.2 СРАВНИТЕЛЬНЫЙ АНАЛИЗ АЛГОРИТМОВ РЕШЕНИЯ ЗАДАЧИ РАСПОЗНАВАНИЯ ДЛЯ СИСТЕМ ОБНАРУЖЕНИЯ ЗНАНИЙ В БАЗАХ ДАННЫХ

3.3 БАЗОВЫЕ ПРОГРАММНЫЕ КОНСТРУКЦИИ ЯЗЫКОВ ПРОГРАММИРОВАНИЯ И ИХ ТЕСТИРОВАНИЕ

3.4 МЕТОД КОМПОНЕНТНОГО ТЕСТИРОВАНИЯ ПРОГРАММНЫХ СИСТЕМ

3.5 РАЗВИТИЕ СТАНДАРТНЫХ СРЕДСТВ РАЗГРАНИЧЕНИЯ ДОСТУПА В ОС СЕМЕЙСТВА WINDOWS 2000/XP/2003

3.6 ЭКОНОМИКО-МАТЕМАТИЧЕСКИЕ МОДЕЛИ ЛОГИСТИКИ ФАРМАЦИИ И РЕСУРСОСБЕРЕГАЮЩИХ ТЕХНОЛОГИЙ


Экспресс информация

Редколлегия журнала

Подписка на новости

Гостевая книга

Предоставление материалов

Письмо в редакцию

На начало


2005, Номер2 ( 7)



Place for sale
МЕТОД КОМПЛЕКСНОГО ТЕСТИРОВАНИЯ ПРОГРАММНЫХ КОМПЛЕКСОВ ИНФОРМАЦИОННЫХ СИСТЕМ

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

Н.Л. Куликова, Ю.П. Кораблин

(Москва, Российский государственный социальный университет, Россия)

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

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

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

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

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

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

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

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

Отметим, что вычисление различных значений компонентами С и С’ в процессе выполнения программы р и р’ еще не гарантирует вычисление различных значений программами р и р’, то есть программа р и ее мутант р’ могут при этом дать один и тот же выходной результат. Это является недостатком компонентного подхода по сравнению с методом сильного мутационного тестирования. Однако следует заметить, что любой метод, основанный на компонентном подходе, может рассматриваться как аппроксимация метода сильной мутации. Более того, эти методы могут быть частично упорядочены по их мощности, то есть способности обнаружения ошибок в программе. Таким образом, метод сильной мутации может рассматриваться как наименьшая верхняя грань частично упорядоченного множества всех компонентных методов тестирования. Заметим также, что широко используемые методы структурного тестирования (например, метод ветвевого тестирования) являются частными случаями компонентных методов тестирования, а, следовательно, и метода сильной мутации. В том случае, если в качестве трансформируемых компонент выбираются лишь предикаты, входящие в состав условий в точках ветвления программ (в частности, и условий выполнения циклов), то мы получаем компонентный метод тестирования, эквивалентный по мощности методу путевого тестирования.

Рассмотрение методов компонентного тестирования мы будем осуществлять как с точки зрения конструкций языка программирования, так и с функциональной точки зрения. С функциональной точки зрения программе р будет сопоставляться функция f, реализуемая этой программой. Обозначим через Uf  множество функций, имеющих ту же самую входную область, что и f, включая саму функцию f. Очевидно, что множество функций f Π Uf, таких, что f ¹ f , представляет собой множество “похожих” функций. В общем случае коды программ р и р’, вычисляющих соответственно f и f , могут быть совершенно различны, поскольку даже одна и та же функция может иметь различные алгоритмы её вычисления, а значит, и различные коды. По причине высокой сложности мы ограничиваем понятие ²похожести² функции f и f лишь теми случаями, когда коды р и р’ реализующие f и f , соответственно отличаются таким образом, что код программы р’ может быть получен из кода программы р введением в него заданных классов ошибок. Таким образом, классы Uf могут рассматриваться как моделирование классов программных ошибок.

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

Введем ряд обозначений, используемых нами в дальнейшем. Обозначим через Х - множество переменных, через V - множество значений переменных, через ТТ - множество истинностных значений, состоящих из двух символов: TRUE и FALSE, обозначаемых далее как Т и F соответственно.

Обозначим через SТ- множество состояний программы, через s - состояние программы, являющейся функцией вида s: Х х Х х ... х Х Þ V х V х ... х V , то есть состояние сопоставляет вектору переменных программы вектор их значений. Отметим, что, в общем случае, область V включает в себя как значения, являющиеся содержимым ячеек памяти, так и имена переменных (например, в случае ссылочных переменных), что соответствует адресам, сопоставляемым переменным программы через
s { v }, где v Î X, будем обозначать значения переменной v . Если е выражение, то запись s [е / v] обозначает состояние, в котором переменной v сопоставляется выражение е, тогда как значения остальных переменных определяются состоянием s.

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