2
ИНФОРМАЦИОННО-КОММУНИКАЦИОННЫЕ СИСТЕМЫ
О НЕКОТОРЫХ ЗАДАЧАХ ТЕСТИРОВАНИЯ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ
К.В. Рубинов
Научный руководитель - д.т.н., профессор А.А. Шалыто
Работа посвящена рассмотрению актуальных задач тестирования программного обеспечения, а также перспективных направлений их решения.
Введение
В настоящее время вопросу тестирования программного обеспечения (ПО) уделяется все больше внимания как со стороны производителей ПО, так и со стороны научной общественности. Потребность в решении задач тестирования ПО возникает при создании практически каждого программного продукта. При этом подходы к их решению могут существенно отличаться в зависимости от характеристик ПО, подлежащего тестированию.
Обзор литературы [1- 3] позволяет сделать вывод о том, что в области тестирования ПО ведутся активные исследования, а решаемые задачи по этой тематике актуальны. Настоящая работа посвящена рассмотрению наиболее важных, по мнению автора, задач тестирования ПО, а также перспективных направлений их решения. Предложенная классификация задач позволит проследить связи между зависимыми задачами с целью оптимизации процесса тестирования, а также поможет при выборе инструментов и подходов к их решению.
1. Постановка задачи
В работе приводится описание задач, связанных с процессом тестирования программного обеспечения. Чтобы показать связь этого процесса и возникающих в нем задач, отметим его основные этапы:
1. подготовка тестирования,
2. проектирование тестов,
3. разработка тестов,
4. создание тестовой среды,
5. выполнение тестов,
6. повторное (регрессионное) выполнение тестов.
В дальнейшем при рассмотрении задач будем обращаться к указанным этапам и порядку их следования.
В работе выделены не все задачи тестирования ПО, а только те из них, которые специфичны для этого процесса и могут быть интересны с точки зрения научных исследований, а также требуют специальных подходов к решению:
1. генерация и выбор тестовых данных,
2. создание модели тестирования,
3. задача тестового оракула,
4. выбор критериев тестового покрытия и оценка тестового покрытия,
5. генерация тестовых сценариев,
6. выбор тестов для повторного (регрессионного) тестирования.
Эти задачи появляются на разных этапах рассматриваемого процесса и, в общем случае, связаны между собой. Далее в работе будем исследовать каждую из задач в отдельности. При этом излагаются:
• описание задачи;
• предпосылки появления задачи;
• сложность решения задачи и ограничения;
• направления решения задачи;
• возможность автоматизации решения задачи;
• связи с другими задачами.
2. Задачи тестирования программного обеспечения
Основываясь на информации из современных источников (например, [1]) можно утверждать, что задачи тестирования основаны на следующих постулатах тестирования программного обеспечения:
• полное тестирование невозможно;
• стопроцентная автоматизация тестирования невозможна;
• общая теория тестирования отсутствует.
Поэтому для всех задач существует одна общая и, вероятно, основная причина их появления - это проблема выбора и нахождения баланса между подробным, трудоемким по времени и ресурсам тестированием, и менее глубоким, а, следовательно, более дешевым тестированием. Другими словами, большинство задач решаются с целью улучшения качества и глубины тестирования в условиях ограничений времени и других ресурсов.
2.1. Генерация и выбор тестовых данных
В настоящее время для большинства существующих и создаваемых программных систем существует проблема тестирования, известная под названием взрыв числа состояний (State space/combinatorial explosion). Проблема заключается в том, что невозможно выполнить тесты со всеми возможными комбинациями данных, которые могут быть использованы при функционировании систем. Это вызывает значительные сложности в процессе тестирования, а указанная проблема ставит перед разработчиками тестов ряд задач, основной из которых является задача генерации и выбора тестовых данных.
Рассматриваемая задача состоит в том, чтобы автоматически сгенерировать данные или комбинации данных. Помимо генерации, необходимо произвести отбор/выбор существенных данных из сгенерированных.
Выбор тестовых данных совершается для того, чтобы уменьшить их общее число и извлечь из всех возможных комбинаций для тестирования репрезентативные, которые позволяют выявить наибольшее число неисправностей, а также реалистичные данные, наиболее близкие к используемым при эксплуатации системы. При этом требуется учитывать ограничения на тестовые данные. Например, при генерации данных для загрузки памяти важно обеспечить возможность получить их в реальности в виде физических ресурсов памяти. Генерация сложных структур данных также является трудно разрешимой задачей.
Принимая во внимание ограничения и требования, предъявляемые к тестовым данным, для их выбора используются различные критерии отбора. Эти критерии могут быть основаны на используемых техниках тестирования, анализе рисков для тестируемой системы, критических обзорах документации к системе, выбранной стратегии тестирования, а также на основе других источников и их комбинациях.
Некоторые техники тестирования сами по себе нацелены на отбор данных - например, техника анализа граничных значений (Boundary value analysis), когда для тес-
тирования отбираются граничные значения данных, используемых в тестируемой системе [4]. При этом утверждается, что применение именно этих значений приводит к обнаружению часто встречающихся неисправностей.
Считается, что данная задача хорошо подходит для автоматизации, а отбор данных может быть совмещен с процессом генерации и производиться автоматически.
Для решения задачи генерации и выбора тестовых данных существует ряд подходов, начиная со случайной генерации данных (Random test data generation) и использования метода полного перебора и заканчивая подходами с применением генетических алгоритмов, комбинаторного анализа, а также построения и исследования моделей использования данных. Подходы могут быть основаны как на информации об исходном коде системы, предназначенной для тестирования, так и на ее спецификации [5].
Исследования по генерации тестовых данных ведутся повсеместно, а большое число публикаций приводит к тому, что разрабатываемые подходы достаточно сложно классифицировать. Широкий обзор направлений генерации тестовых данных представлен в работе [6]. Перечислим наиболее известные подходы:
1. случайная генерация данных (Random fest data generation);
2. генерация данных на основе алгоритмов поиска (Search-based test data generation), в том числе генерация данных посредством генетических алгоритмов;
3. символьное исполнение программ (Symbolic execution);
4. генерация данных на основе ограничений (Constraint-based techniques).
Для отбора наиболее эффективных в плане тестирования данных существуют различные техники, такие как:
1. техники тестирования с выделением эквивалентных классов данных (Category partitioning),
2. ортогональные массивы и попарное тестирование (Orthogonal arrays and pair-wise testing),
3. техника анализа граничных значений (Boundary value analysis).
Генерация и выбор тестовых данных производятся на этапах подготовки тестирования и проектирования тестов. От результатов решения этой задачи непосредственно зависит эффективность последующих этапов процесса тестирования - разработки и выполнения тестов.
2.2. Создание модели тестирования
На протяжении более десятилетия существует и развивается подход под названием тестирование на основе моделей (Model-Based Testing - MBT) [7, 8]. В его основе лежит использование моделей для контроля и управления процессом тестирования, в частности, для автоматической генерации тестов.
Известны работы [2, 9], в которых делаются попытки применить существующие модели для этих целей. Однако универсального подхода к использованию моделей для тестирования не существует. Поэтому вместо того, чтобы выбирать некоторую известную модель и исследовать, как она может быть использована для тестирования, можно продумать, как создать такую модель, чтобы с ее помощью ПО было эффективно протестировано [1].
В настоящее время для тестирования ПО применяются различные модели, такие как таблицы решений (Decision tables), конечные автоматы (Finite state machines), формальные грамматики (Grammars), модели Маркова (Markov chains), сети Петри (Petri nets), UML-модели (UML models), диаграммы состояний (Statecharts) и т.д. [8]. Эти модели могут быть использованы в тестировании с разной степенью эффективности. Причем оценить успех применения моделей можно только при анализе результатов тестирования и сравнении их с результатами других подходов. Немаловажно иметь сведения - подходит ли модель для тестирования конкретной системы или нет.
Эффективное применение модели тестирования может характеризоваться следующими показателями:
• возможностью автоматизации этапов процесса тестирования;
• применимостью модели для генерации тестовых данных и тестовых сценариев;
• однозначностью соответствия модели и спецификации тестируемой системы;
• возможностью оценки тестового покрытия для сгенерированных по модели тестов;
• удобством внесения изменений, сопровождения и понимания модели;
• сокращением ручного труда и времени разработки тестов.
Можно утверждать, что задача создания модели тестирования состоит в подборе и описании формальной модели, обладающей требуемым соотношением перечисленных выше показателей.
Трудоемкость процесса разработки моделей, сложность перехода от спецификации и исходного кода ПО к моделям вызывают трудности при их создании и использовании. В настоящее время развиваются подходы извлечения моделей из существующих программных систем [10]. Вместе с тем точность этих моделей и их пригодность для тестирования требуют исследования.
Помимо удобства использования моделей, необходимо, чтобы процесс работы с моделями был поддержан инструментальными средствами разработки программного обеспечения. При этом отметим, что в свободном доступе мало таких средств - многие являются либо закрытыми разработками компаний и учебных заведений, либо коммерческими приложениями [11].
Необходимо отметить, что решение задачи создания модели тестирования может непосредственно влиять и определять подходы к решению других задач тестирования ПО.
2.3. Задача тестового оракула
Приведем одно из определений тестирования. Тестирование - это оценивание программного обеспечения посредством наблюдения за его работой [2]. В данном случае будем рассматривать вопрос оценки поведения ПО: является ли поведение системы корректным в конкретной ситуации? Для ответа на этот вопрос необходим тестовый оракул.
Тестовый оракул - это система, метод или методика для предсказания или оценки корректности поведения системы, предназначенной для тестирования в определенных условиях [12]. Из этого определения следует, что без тестового оракула проведение тестирования не имеет смысла, так как невозможно оценить и контролировать процесс тестирования, а создание оракула - одна из важнейших задач тестирования ПО.
Сложность создания оракула связана с тем, что практически всегда во время проектирования и разработки тестов имеются допущения и обобщения относительно данных и поведения тестируемой системы. Вместе с тем необходимо создать такой оракул, который позволит однозначно определить корректность поведения системы в условиях неопределенности.
Разнообразные входные данные и воздействия, которые могут быть использованы в системе, весь спектр состояний, возможные реакции системы - все это должно быть учтено при создании тестового оракула. Процесс сравнения и вынесения вердикта существенно усложняется при оценке корректности поведения систем с данными со сложным информационным наполнением, например, аудио или видео, а также систем с временными ограничениями.
В роли тестового оракула может выступать человек. Это происходит при ручном тестировании, когда вердикт о результате теста выносит исполнитель теста. Опыт человека, выполняющего тест, позволяет проводить такие виды тестирования, как специальное/исследовательское (ad hoc/exploratory testing), когда не используются специальные документы, регламентирующие процесс тестирования [13]. В случае автоматиза-
ции тестирования можно говорить о том, что создание автоматических тестов возможно только с использованием тестовых оракулов [14].
Итак, описываемая задача состоит в том, чтобы создать тестовый оракул для программной системы с учетом ее характеристик в условиях существующей неопределенности с целью разработки автоматических тестов.
Существуют различные подходы к решению этой задачи. Например, сравнение поведения тестируемой системы с поведением предыдущей версии того же продукта или некоторой эталонной системы. Для тестирования графических интерейсов пользователей (Graphical User Interface - GUI) используют средства записи/воспроизведения (record/playback). В этом случае выполняется сравнение с эталонными образами и использование модели GUI. Иногда создание тестового оракула может быть более трудоемким и сложным процессом, чем создание тестируемой системы. Для ответственных систем (Mission-Critical Systems) могут быть разработаны и использованы несколько тестовых оракулов. Показателем корректности в этом случае будет среднее значение, полученное при сравнении результатов всех оракулов.
В заключение раздела отметим, что специфика рассматриваемой задачи определяется тем, что вопрос контроля корректности создаваемого тестового оракула остается открытым - необходимы способы обеспечения создания достоверных тестовых оракулов.
2.4. Выбор критериев тестового покрытия и оценка тестового покрытия
Для тестирования ПО разрабатываются тесты с различным целевым назначением, например, тесты, проверяющие базовую функциональность, нагрузочные тесты, тесты на производительность, тесты взаимодействия с другими компонентами или системами и т.д. Такие тесты объединяются в наборы, которые должны комплексно тестировать свойства и функции системы. Каждый набор тестов характеризуется целевым назначением и тем, какую функциональность он проверяет.
При этом возникает необходимость оценки этих характеристик, чтобы определить качество и полноту тестового набора по отношению к тестируемой системе. Существуют различные критерии оценки тестового покрытия, которые могут быть применены для этих целей. Число типов тестового покрытия достаточно велико [2, 15, 16]. Эти типы могут быть основаны на исходном коде ПО, спецификации ПО, вариантах использования программной системы и их модельных представлениях. В качестве примера назовем несколько типов тестового покрытия:
• покрытие ветвлений модуля программы (branch coverage for program unit);
• покрытие всех вершин в графе потока управления программы (nodes coverage of control flow graph);
• покрытие тестами требований из спецификации (requirements coverage).
Рассматриваемая задача состоит в выборе и сочетании критериев оценки тестового покрытия разрабатываемого набора тестов для программной системы и оценки этого покрытия. Выбор критериев должен осуществляться на этапах подготовки тестирования и проектирования тестов. Таким образом, тестовое покрытие может использоваться на протяжении всего процесса тестирования.
Основу для выбора критериев могут представлять данные анализа рисков системы, выбранная стратегия тестирования, а также требования, предъявляемые к системе. В то же время основная сложность в решении данной задачи обусловлена тем, что рассматриваемые оценки и сила критериев являются относительными.
Для оценки тестового покрытия производится сбор необходимых данных. В случае применения критериев оценки, основанных на спецификации, собирается информация о планируемом числе тестов, их целевом назначении и проверяемой фукнцио-нальности. Затем строится матрица контроля (traceability matrix), по которой определяется степень покрытия тестами характеристик системы.
При использовании критериев, основанных на исходном коде ПО, оценка может производиться автоматически с помощью специальных средств анализа тестового покрытия кода приложений [17]. Также получение оценки можно автоматизировать при использовании в процессе тестирования модели. При этом необходимая информация извлекается из модели автоматически.
Кроме того, что применение оценок тестового покрытия позволяет определять необходимое число тестов и данных для тестирования, существует другая сторона задачи тестового покрытия. Использование данных о тестовом покрытии может быть основой для решения вопроса о прекращении тестирования. Проблема завершения тестирования выделена среди основных актуальных проблем программной инженерии в работе [3]. В настоящее время существует потребность в разработке параметров и моделей, которые позволяли бы выявлять момент прекращения тестирования на основе специальных критериев.
Можно отметить также, что в инженерии надежности ПО (Software Reliability Engineering) тестовое покрытие является одним из механизмов предсказания надежности разрабатываемого ПО [18]. Информация о тестовом покрытии может быть использована наравне со знаниями о рисках тестируемой системы как инструмент для принятия решений о выборе тестов для повторного (регрессионного) тестирования. При этом критерии тестового покрытия могут применяться при выборе данных для тестирования вместе с критериями отбора тестовых данных, описанных в разд. 2.1.
2.5. Генерация тестовых сценариев
Тестовый сценарий - это основа любого теста. Сценарий содержит последовательность тестовых воздействий и соответствующие тестовые данные для тестирования системы в определенных состояниях. Помимо этого, тестовые сценарии должы быть оптимальны для тестируемой системы/программы - обладать следующими свойствами:
• должна отсутствовать избыточность и дублирование тестовых воздействий;
• должно быть обеспечено соответствие требованиям времени выполнения сценария;
• должно быть ограничено максимальное число тестовых воздействий.
Слишком длинная последовательность воздействий в тестовом сценарии может вызвать неоправданно длительный процесс выполнения теста. Это может помешать оптимальному выбору и исполнению тестов в дальнейшем. Слишком короткая последовательность может вызвать противоположную ситуацию - свести к минимуму эффективность применения сценарного тестирования из-за малого отличия от использования единичных тестовых воздействий.
Глубина и полнота тестирования непосредственно зависят от качества разработанных тестовых сценариев. Таким образом, необходимы формальные методы для создания оптимальных тестовых сценариев, а также способствующие автоматизации генерации тестовых сценариев.
Число воздействий в тестовых сценариях, как и число самих сценариев, может быть бесконечным. Поэтому появляется необходимость выбора тестовых сценариев. Так же, как и в задаче выбора тестовых данных (разд. 2.1), для этого применяются различные подходы и техники, целью которых является отбор сценариев, позволяющих провести проверки в значимых состояниях системы с меньшими затратами времени и других ресурсов.
Применение моделей тестирования может существенно облегчить процесс генерации тестовых сценариев. В настоящий момент известен ряд техник, методов и программных средств, позволяющих автоматически генерировать тестовые сценарии на основе разнообразных моделей [11].
В общем случае решение задачи с применением моделей тестирования сводится к созданию формального представления модели, которое описывает поведение системы, варианты использования системы или ограничения из спецификации. При этом модель
может базироваться на спецификации или исходном коде системы. Далее должен выполняться переход к представлению модели в виде графа, а затем осуществляться обход графа с использованием различных алгоритмов [19, 20] с последующей генерацией тестовых сценариев. В настоящее время существуют подходы для генерации тестов на основе спецификаций, в которых описанные действия производятся автоматически [5].
Существуют и применяются также такие виды тестирования, как ad hoc/exploratory. При этом тестовые сценарии не задаются заранее, а формируются инженером по тестированию непосредственно в процессе выполнения воздействий на тестируемую систему.
2.6. Выбор тестов для повторного (регрессионного) тестирования
Как и большинство задач тестирования, эта задача состоит в выборе альтернатив и в достижении компромисса между множеством условий и ограничений. В соответствии с работой [4], основная проблема регрессионного тестирования состоит в поиске компромисса между доступными ресурсами и необходимостью проведения повторных тестов по мере внесения каждого изменения в программную систему. В определенной степени рассматриваемая задача состоит в том, чтобы определить критерии «масштабов» изменений в ПО, с достижением которых необходимо проводить регрессионные тесты.
Таким образом, при регрессионном тестировании должны быть учтены критерии влияния различных факторов, таких как сложность редактируемого программного кода (code complexity) и архитектурные особенности ПО, включая информацию о компонентах, которые используют модифицируемую часть системы или используются ей.
Решения о выборе тестов принимаются на основе приоритетов тестов, назначенных на основе анализа рисков системы. Кроме этого, рассматривается матрица контроля (traceability matrix) для нахождения тестов, соответствующих требованиям спецификации или блокам кода ПО. После этого производится расчет необходимого времени выполнения тестов. Опеделяются операционные профили1. Собирается информация о функциональности системы, проверенной на предыдущих итерациях выполнения тестов, а также информация о том, сколько циклов повторений регрессионных тестов запланировано в процессе тестирования ПО. Кроме того, принимается во внимание готовность компонентов программного продукта к тестированию.
С учетом изложенного формируются различные подходы к решению задачи. В общем случае эти подходы выражаются в виде стратегий выбора тестов на протяжении всего процесса тестирования. Известны случаи создания моделей изменений ПО для регрессионного тестирования [21]. Эти модели позволяют выявлять зависимости в ПО, которые необходимо протестировать, а после этого автоматически генерировать тестовые наборы для регрессионного тестирования.
Можно отметить, что информация, полученная при решении вопросов остановки тестирования и оценки тестового покрытия (разд. 2.4), может быть непосредственно использована при подготовке и выборе тестов для регрессионного тестирования.
Заключение
В настоящей работе приведен обзор актуальных задач тестирования программного обеспечения. Рассмотрены вопросы автоматизации решения задач. Определена связь между задачами в рамках процесса тестирования ПО, и указаны пути решения рассмотренных задач.
1 Операционный профиль (operational profile) - набор тестовых данных, отражающий реальные условия функционирования программы с учетом вероятности их возникновения.
Литература
1. Bertolino A. Software Testing Research: Achievements, Challenges, Dreams /Future of Software Engineering. Briand L. and Wolf A. (eds.). IEEE-CS Press. 2007, pp. 85-103.
2. Ammann P., Offutt J. Introduction to software testing // NY: Cambridge University Press. 2008. 344 pp.
3. Воас Д. Чертова дюжина проблем программной инженерии // Открытые системы. -2007. - № 7. - С. 30-35. - Режим доступа: http://www.osp.ru/os/2007/07/4391815/
4. Орлик C. Программная инженерия. Тестирование программного обеспечения (Software Testing) /Введение в программную инженерию и управление жизненным циклом ПО. 2004. - Режим доступа: http://www.sorlik.ru/swebok/3-4-software_engineering_testing.pdf
5. Offutt J., Liu S., Abdurazik A., Ammann P. Generating Test Data From State-based Specifications /The Journal of Software Testing, Verification and Reliability. - 2003. -13(1). - Р. 25-53.
6. McMinn P. Search-based software test data generation: A survey /Software Testing, Verification and Reliability. - 2004. - 14(2). - Р. 105-156.
7. DACS (Data and Analysis Center for Software) Gold Practices Website. Model-based testing. - Режим доступа: https://www.goldpractices.com/practices/mbt/
8. El-Far I.K., Whittaker J. Model-Based Software Testing. Encyclopedia on Software Engineering (edited by Marciniak J.). Wiley. 2001. 225 pp.
9. Al-Ghafees M., Whittaker J. Markov Chain-based Test Data Adequacy Criteria: a Complete Family // IS June 2002. - P. 13-37.
10. Acharya M., Xie T., Pei J., Xu J. Mining API patterns as partial orders from source code: from usage scenarios to specifications / In Proc. ESEC/FSE 2007. - Режим доступа: http://people.engr.ncsu.edu/txie/publications/esecfse07.pdf
11. Hartman A. AGEDIS model based test generation tools. - Режим доступа: http://www.agedis.de/documents/ModelBasedTestGenerationTools.pdf
12. Блэк Р. Ключевые процессы тестирования: планирование, подготовка, проведение, совершенствование. - М.: Лори, 2006. - 576 с.
13. Bach J. Exploratory Testing Explained. 2002. 10 pp. - Режим доступа: http://www.satisfice.com/articles/et-article.pdf
14. Hoffman D. Using Oracles in Test Automation /Software Quality Methods. - 2001.
15. Towhidnejad M. Types of Software Testing Coverage. - Режим доступа: http://faculty.erau.edu/towhid/coverage.html
16. Kaner C. Software Negligence and Testing Coverage. - Режим доступа: http://www.kaner.com/coverage.htm
17. Дастин Э., Рэшка Д., Пол Д. Автоматизированное тестирование программного обеспечения. Внедрение, управление и эксплуатация. - М.: Лори, 2003. - 592 с.
18. Lyu, M. Software Reliability Engineering: A Roadmap /Future of Software Engineering. Briand L. and Wolf A. (eds.). - IEEE-CS Press, 2007. - Р. 153-170.
19. Бейзер Б. Тестирование черного ящика. Технологии функционального тестирования программного обеспечения и систем. - СПб: Питер, 2004. - 318 с.
20. Tonella P. Evolutionary Testing of Classes /Proceedings of the 2004 ACM SIGSOFT international symposium on Software testing and analysis ISSTA '04. ACM Press. - NY, 2004. - Р. 119-128.
21. Chen Y., Probert R., Ural H. Model-based regression test suite generation using dependence analysis / In Proc. of the 3rd International workshop on Advances in model-based testing. - London, 2007. - Р. 54-62.