УДК 681.518.54
С. Н. Малинин
ТЕСТИРОВАНИЕ ОБЪЕКТНО-ОРИЕНТИРОВАННЫХ ПРОГРАММ МОДЕЛИРОВАНИЕМ КОНЕЧНЫМИ АВТОМАТАМИ
Аннотация. В статье рассматривается метод определения входных данных для модульного и интеграционного тестирования объектно-ориентированного программного обеспечения на основе моделирования классов конечными автоматами. Приведен пример построения автоматной граф-модели.
Ключевые слова: модульное тестирование, конечные автоматы, объектноориентированный.
Abstract. In the paper a method of input data definition is considered for unit and integration testing of object-oriented software based upon finite state machines modeling. Given example illustrates building graph model as state machine.
Keywords: unit testing, finite state machines, object-oriented.
Непрерывно возрастающая сложность программного обеспечения (ПО) и информационных технологий требует эффективных методов обеспечения их качества. Одним из способов преодоления сложности анализа, проектирования и реализации ПО является объектно-ориентированный подход. В основе такого подхода лежит принцип, согласно которому решение задачи может со временем претерпевать изменения, в то же время структура и компоненты задачи не меняются в той же степени и столь же часто. Следовательно, программа, структура которой определяется особенностями задачи (и вовсе не непосредственно требуемым решением), обладает большей приспосабливае-мостью к последующим изменениям. Благодаря упомянутому обстоятельству он делает программное обеспечение более удобным в сопровождении и эксплуатации. Более того, поскольку компоненты были получены в соответствии с потребностями задачи, они могут быть повторно использованы при разработке других программных решений таких же или подобных задач, в результате чего повышаются возможности многократного использования компонентов программного обеспечения.
В связи с появлением большого количества программ, написанных на языках объектно-ориентированной парадигмы, стала актуальной задача обеспечения качества объектно-ориентированного программного обеспечения. Одним из основных требований к качеству системы является ее корректность. Под корректностью понимается соответствие системы ее предназначению. Как правило, анализ соответствия системы предъявляемым к ней требованиям производится методами либо верификации, либо тестирования. При этом гарантированное обоснование качества систем возможно только при помощи верификации, т.е. путем математического (формального) доказательства наличия или отсутствия у системы проверяемого свойства, описанного в спецификации [1]. Недостатки такого подхода заключаются в том, что формальные методы предъявляют особые требования к используемым системам программирования и языкам описания моделей программных систем. Сами формальные модели часто отличаются высокой сложностью. Поэтому средства верификации в большинстве случаев становятся неприменимыми.
Тестирование является основной формой контроля качества систем в настоящее время. Тестирование заключается в анализе поведения системы на некоторых выборочных входных данных (наборе тестов). Оно помогает выявлять ошибки при разработке программного обеспечения. Большинство существующих методик тестирования относятся к структурному тестированию, основанному на знании внутренней структуры программной системы. Процесс построения набора тестов при структурном тестировании основывается на конструировании графа-модели программы (ГМП). От этого зависит множество тестовых путей и генерация тестов, соответствующих тестовым путям. Общая схема построения ГМП или комплекса программ на основе анализа исходного кода может состоять в следующем. Любой программный модуль можно представить графически в виде укрупненной блок-схемы. Блокам укрупненной блок-схемы соответствуют операторы - предикаты или линейные цепочки операторов, т.е. совокупности последовательно выполняемых операторов, каждый из которых имеет один вход и один выход. Блокам, имеющим больше одного приемника, будут соответствовать логические выражения, в зависимости от значений которых и будет производиться передача управления. В больших схемах допускается объединять в один оператор цепочку и следующий за ней логический оператор. Связям между блоками такой схемы соответствуют линии передачи управления. Структуру блок-схемы в этом случае можно представить в виде ориентированного графа по управлению. Множество вершин графа отображает блоки укрупненной блок-схемы, а множество дуг - передачи управления между блоками. Аналогично можно представить в виде графа и комплекс программ, однако в этом случае вершины графа будут соответствовать модулям программного комплекса, а дуги -связям между модулями. Под информационным графом [2] (графом потока данных) программы понимается управляющий граф, который дополнен потоком данных, участвующих в вычислениях. Каждая из вершин выполняет определенные преобразования входного потока данных и передает результаты обработки информации в виде потоков данных для других вершин. Информационный граф отражает прохождение обрабатываемой информации.
Но на практике тестирование объектно-ориентированного программного обеспечения затруднено тем фактом, что тестируемая программа состоит как из вновь разрабатываемых, так и из ранее написанных готовых компонентов. При этом часто компоненты одной системы разрабатываются разными, слабо связанными группами людей. Исходный код ранее написанных компонентов не всегда доступен команде тестирования или внесение каких-либо изменений с целью построения структуры программы в исходный код недопустимо, что делает структурное тестирование невозможным. В этих случаях необходимо рассматривать систему как «черный ящик» и опираться на функциональное тестирование вместо структурного [3].
Одной из целей функционального тестирования является проверка соответствия объекта тестирования функциональным требованиям и спецификации. Обязательным этапом функционального тестирования является разработка тестовых сценариев (контрольных примеров, тестов). Каждый тестовый сценарий состоит из следующих элементов:
- описание состояния приложения перед началом теста;
- описание последовательности действий, в том числе используемые входные данные;
- ожидаемый результат.
Последовательность действий при использовании тестовых сценариев следующая: тестировщик переводит систему в начальное состояние, выполняет предписанное тестом событие, идентифицирует новое состояние системы и сравнивает его с ожидаемым состоянием. На основании этого сравнения выносится решение о наличии ошибок в тестируемой функциональности. При этом в метод передается набор входных данных и оценивается поведение тестируемой системы: код возврата, сообщение на экране, сгенерированное исключение или любой другой ожидаемый результат. При тестировании методом «черного ящика» проверяется, переходит ли при возникновении искусственно созданного события система в указанное моделью состояние. Действия, которые система не должна выполнять, также могут быть охвачены тестовыми сценариями.
Следовательно, задача построения такой граф-модели системы, с помощью которой было бы возможно определение достаточности покрытия программы множеством тестовых сценариев, измерение тестового покрытия кода и разработка новых тестовых сценариев на основе анализа спецификации программы, когда исходный код программы недоступен, является актуальной для тестирования объектно-ориентированного программного обеспечения.
Большинство современных приложений Windows с графическим интерфейсом разрабатываются на основе технологии объектно-ориентированного программирования и являются программами, управляемыми событиями (сообщениями) [4].
Примерами источников событий могут служить:
- устройства персонального компьютера (клавиатура, мышь, таймер);
- интерфейсный элемент приложения (команда меню, кнопка);
- результаты работы методов самого приложения.
Следовательно, функции программы не связаны друг с другом жестко. Передача управления внутри программы осуществляется не только путем явного указания последовательности обращений одних функций программы к другим, но и путем генерации сообщений, разбора сообщений соответствующим обработчиком и передача их объектам, для которых данные сообщения предназначены.
Основоположники методов объектно-ориентированного анализа и проектирования Г. Буч, Ж. Рамбаух характеризуют объект как что-то, имеющее идентичность, состояние и поведение, а класс можно охарактеризовать состояниями, событиями и переходами конечного автомата [5, 6]. Поведение классов может быть описано с помощью моделирования конечными автоматами в терминах состояний и событий. При наступлении какого-нибудь события (получении сообщения) происходит переход к другому устойчивому состоянию. Последовательность действий, сопровождающих переход в другое состояние, зависит не только от текущего состояния, но и от входного сигнала (события). Переход описывается начальным состоянием, конечным состоянием, событием, а также условием перехода и последовательностью действий. Условие перехода представляет собой выражение, которое принимает значение «истина» для осуществления перехода. Последовательность действий представляет собой набор операций, выполняемых при осуществлении перехода. Эти действия выражаются через поля
данных класса, вызовы методов объектов и переменные, возвращаемые методами, осуществляющими переход. Последовательность действий представляет собой блок кода, в котором выполняются все операции или не выполняется ни одно из них.
На основании вышеизложенного для описания функционирования программы целесообразно рассматривать автоматную модель программы, в которой выходы ассоциируются с переходами по событиям, а состояния соответствуют стабильным состояниям программной системы. Также следует отметить, что в объектно-ориентированном программном обеспечении элементом тестирования является не подпрограмма, а класс. Класс - это основной элемент абстракции предметной области и декомпозиции программы (например, при анализе программного обеспечения микроволновой печи можно выделить такие классы, как таймер, клавиатура, дисплей, нагревательный элемент и др.). Класс представляет собой план, согласно которому задаются состояние (поля данных) и поведение (методы) объектов данного класса. Автоматная модель класса должна отражать функциональные требования к тестируемой программной системе и может быть получена на этапе проектирования или самим тестировщиком. Связи и зависимости между методами могут быть выявлены в результате анализа спецификации, например, в виде иМЬ-диаграммы. В отличие от ИМЬ-диаграмм, автоматная модель объединяет статические и динамические аспекты программы, тем самым является достаточной для проведения полноценного тестирования.
В этой работе предлагается методика, которая моделирует поведение отдельного класса конечным автоматом, а затем на основе граф-модели автомата генерируются тестовые сценарии для тестирования отдельного класса. В ходе тестирования устанавливается, посылаются ли и получаются ли сообщения от объектов одного класса или компонента в ожидаемом порядке, переходят ли внешние объекты в другое состояние при получении этих сообщений.
Определение автоматной модели класса
В работе [7] автоматная модель класса представляет собой совокупность множеств
M = (V, F, S, Т),
где V - конечное множество полей данных класса; F - конечное множество методов класса; S - конечное множество состояний автомата; Т - конечное множество переходов,
Т = ^ | t = ^н, Sк, метод, условие, действия)},
где Sн, Sк е S - состояния автомата до и после перехода; метод - метод, переводящий автомат в другое состояние; условие - условие перехода в другое состояние; действия - деятельность или операция, которая должна быть выполнена экземпляром, когда он достигает состояния. Одно действие связывается с каждым состоянием. Действия сопровождают переход в другое состояние, представляют собой последовательность вычислений над значениями элементов множества V и параметрами элементов множества F.
Автомат называется конечным, если конечны все перечисленные выше множества V, F, S, Т.
Пример для одного класса
Построим предлагаемую автоматную модель для примера из [8] класса Oven, описывающего работу микроволновой печи, покажем, как может быть проведено его тестирование. Концепция устройства включает следующие элементы:
1. Имеется единственная кнопка управления, доступная для пользователя печи. Если дверца печи закрыта и пользователь нажмет кнопку, печь будет готовить пищу (т. е. силовой элемент будет находиться под напряжением) в течение 1 мин.
2. Если пользователь нажмет кнопку во время работы печи, то получает дополнительную минуту. Например, если у него остается 40 с для приготовления пищи и он нажмет кнопку дважды, время приготовления пищи увеличивается до 2 мин 40 с.
3. Нажатие кнопки при открытой двери не имеет никакого эффекта.
4. Можно останавливать процесс приготовления пищи открыванием дверцы.
При выборе конкретных состояний автомата надо ответить на следующие основные вопросы:
1. Какие значения может принимать параметр? Проверить граничные значения, недопустимые значения, нормальные значения.
2. Какие совокупности значений имеют особый смысл? Если параметры зависят друг от друга, проследить эти зависимости.
3. Какие комбинации параметров приведут к корректной работе метода?
4. Какие комбинации параметров вызовут ошибку, неправильный код возврата или аномальное поведение окружения?
Микроволновая печь может находиться в одном из следующих возможных состояний (рис. 1):
S0: Начальное состояние.
S1: Бездействие с закрытой дверью.
S2: Первоначальный период приготовления пищи.
S3: Приготовление пищи прервано.
S4: Бездействие с открытой дверью.
S5: Период приготовления пищи возрастает.
S6: Приготовление пищи завершено.
В этой задаче есть несколько событий, которые воздействуют на работу
печи:
1. Открывание двери.
2. Закрывание двери.
3. Нажатие кнопки управления.
4. Завершение предписанного интервала для приготовления пищи.
События инициируют переходы от одного состояния к другому.
Множества состояний, полей данных, методов и переходов определяются следующим образом:
S = {S0, S1, S2, S3, S4, S5, S6}
V = {int Time, int Voltage, boolean ISDoorNotOpen, boolean KeyOn}
F = {Oven (), ~Oven (), CheckDoor (boolean StatuS), Start (boolean in), Stop (), SetKeyOn(boolean in) }
T = {ti | 0 < i < 6}
t1 = (S0, S1, Oven(), {ISDoorNotOpen = true})
t2 = (S4, S1, CheckDoor(StatuS), StatuS == true, {ISDoorNotOpen = = StatuS})
t3 = (S1, S2, Start(in), in == true, { KeyOn = in, Time = 60, Voltage = 220}) t4 = (S2, S6, Stop(), Time == 0, {Voltage = 0})
t5 = (S2, S5, SetKeyOn(in), in == true, {KeyOn = in, Time = Time + 60}) t6 = (S5, S5, SetKeyOn(in), in == true, {KeyOn = in, Time = Time + 60}) t7 = (S2, S3, CheckDoor(StatuS), StatuS == falSe, {ISDoorNotOpen = = StatuS, Time = 0, Voltage = 0})
t8 = (S5, S3, CheckDoor(StatuS), StatuS == falSe, {ISDoorNotOpen = = StatuS, Time = 0, Voltage = 0})
t9 = (S5, S6, Stop(), Time == 0, {Voltage = 0}) t10 = (S3, S1, ~Oven(), ISDoorNotOpen == true, {}) t11 = (S1, S4, CheckDoor(StatuS), StatuS == falSe,
= StatuS})
t12 = (S6, S4, CheckDoor(StatuS), StatuS == falSe,
= StatuS})
Oven() и ~Oven() являются соответственно конструктором и деструктором класса, CheckDoor() позволяет контролировать состояние двери, SetKeyOn() увеличивает время на 1 мин. Start() запускает автомат при нажатии кнопки, а Stop() останавливает его.
{ISDoorNotOpen = {ISDoorNotOpen =
Автоматная модель для множества классов
Компонент - совокупность связанных между собой классов. Система -совокупность компонентов, предназначенных для решения задачи.
При тестировании компонентов и систем должно быть протестировано взаимодействие нескольких классов, для этого описанная выше модель должна быть расширена множеством классов М = (С, V, ^, S, Т). Автомат для множества классов должен представлять собой комбинацию автоматных моделей отдельных классов, а для каждого метода и поля данных должна указываться их принадлежность к соответствующему классу.
Методика определения входных данных на основе автоматной модели класса
На основании построенного графа автоматной модели можно получить необходимые тестовые сценарии: любой путь из начального состояния в конечное является тестом.
Рассмотрим, например, путь S0-S1-S2-S3-S1 в автомате. Этот путь соответствует тесту «Получить ошибку и завершить работу при открытии двери». Тест, реализованный на основе этого пути, должен в состоянии S2 сгенерировать событие t7 и перейти в состояние S3. Иными словами, в метод CheckDoor(Status) должен быть передан такой параметр Status (а именно равный false), который сигнализировал бы об открытии двери и приводил бы автомат к завершению его работы.
В теле теста должен быть проанализирован код возврата и сравнен с ожидаемым. В случае, если полученный код возврата не совпадает с ожидаемым, тест заканчивается с ошибкой, иначе происходит переход в соответствующее состояние и выполнение теста продолжается.
Таким образом, предлагаемый в работе метод определения входных данных представлен следующими шагами:
- анализ предметной области и выделение методов, связанных общей функциональностью;
- представление классов в виде модели их использования - конечного автомата;
- создание по графу переходов конечного автомата набора путей;
- определение входных данных, гарантирующих прохождение по отобранным путям.
Автоматная модель класса хорошо подходит, например, для тестирования функциональности с точки зрения пользовательского интерфейса. Все этапы, кроме собственно создания модели, могут быть автоматизированы на основании известных методов.
Список литературы
1. Кузьмин, Е. В. Структурированные системы переходов / Е. В. Кузьмин, В. А. Соколов. - М. : ФИЗМАТЛИТ, 2006. - 176 с.
2. Балыков, Е. Тестирование программных средств / Е. Балыков, В. Царев // RSDN Magazine. - 2006. - № 4.
3. Веденеев, В. В. Автоматизация тестирования использования программных
интерфейсов приложений на основе моделирования конечными автоматами /
В. В. Веденеев (Руководитель А. А. Шалыто). - Режим доступа:
http ://is.ifmo. ru/testing/vedeneev/
4. Хореев, П. Б. Технологии объектно-ориентированного программирования / Павел Борисович Хорев. - М. : Академия, 2004. - 448 с.
5. Буч, Г. Объектно-ориентированный анализ и проектирование с примерами приложений / Г. Буч. - M. : Вильямс, 2008. - 720 с.
6. Rumbaugh, J. Object Oriented Modeling and Design / J. Rumbaugh, M. Blaha, W. Premerlani, F. Eddy, W. Lorensen. - Prentice Hall, 1991.
7. Gallagher, L. Integration Testing of Object-oriented Components Using FSMS: Theory and Experimental Details / L. Gallagher, J. Offutt // GMU Technical Report ISE-TR-04-04. - 2004. - July.
8. Shlaer, S. Object Lifecycles: Modeling the World in States / Sally Shlaer, Stephen J. Mellor // Stephen J. Mellor; Sally Shlaer. - Prentice Hall, 1991.
Малинин Сергей Николаевич аспирант, Нижегородский государственный технический
Malinin Sergey Nikolaevich Postgraduate student, Nizhniy Novgorod State Technical University
университет
E-mail: [email protected]
УДК 681.518.54 Малинин, С. Н.
Тестирование объектно-ориентированных программ моделированием конечными автоматами / С. Н. Малинин // Известия высших учебных заведений. Поволжский регион. Технические науки. - 2009. - № 2 (10). -
С.63-70.