в различных ситуациях остается одним
Тестирование работы программы в различных ситуациях остается одним из самых широко используемых способов демонстрации ее корректности, особенно для достаточно сложного приложения. Но все существующие методики создания тестов, обеспечивающие их полноту в соответствии с некоторыми естественными критериями, требуют весьма значительных трудозатрат.
Однако в ряде случаев, например, при тестировании же объемных интерфейсов, содержащих тысячи операций, полное и тщательное тестирование обходится слишком дорого, а иногда и вовсе не требуется для всех элементов интерфейса системы. Вместо этого проводится тестирование работоспособности, то есть проверяется, что все функции системы устойчиво работают хотя бы на простейших сценариях использования. Уже затем, для наиболее критической части интерфейса разрабатываются детальные тесты.
Именно для решения таких типов задач предназначена технология Azov [1], созданная в 2007 году в Институте системного программирования. Технология нацелена на разработку тестов работоспособности, вызывающих тестируемые операции в правильном окружении с какими-нибудь допустимыми значениями параметров, характеризующими простейшие сценарии использования этих операций. При этом она позволяет существенно автоматизировать создание теста.
Область применимости технологии включает те случаи, когда информация об интерфейсе доступна в хорошо структурированном, годном для автоматической обработки виде. При этом трудозатраты на создание одного теста существенно меньше, если тестируемый интерфейс содержит большое количество операций.
В частности технология Azov была использована при создании тестового набора для бинарных операций библиотеки Qt3, предназначенной для разработки приложений с графическим интерфейсом [4] и входящей в стандарт Linux Standard Base [2,3] (LSB). Стандарт включает в себя около 10000 методов и функций библиотеки и хранит информацию об их синтаксисе в своей базе данных.
Тестирование библиотек, написанных на языке C++, в частности Qt3 [4], является достаточно трудоемкой задачей. Поведение метода может зависеть не только от передаваемых ему параметров и глобального состояния системы, но и от состояния объекта, которому он принадлежит. Сама же библиотека графического интерфейса содержит дополнительные механизмы, которые также оказывают существенное влияние на работу методов.
Поэтому базовая методика, предлагаемая технологией Azov, должна быть дополнена набором средств, позволяющих формировать работоспособные тесты на языке C++ во всевозможных ситуациях, возникающих при тестировании элементов интерфейса, и учитывающих особенности библиотеки Qt [3], в частности механизм передачи сообщений.
Воздействия на систему требуется производить не только последовательно, но и асинхронно, т.е. подавать их из различных потоков, процессов или с разных машин. Результаты, выдаваемые системой после подачи воздействия, зависят от чередований событий внутри нее. В системах, взаимодействующих посредством удаленного вызова методов, такими событиями являются удаленные вызовы методов. Результат может зависеть от порядка вызова этих методов. Соответственно, метод оценки корректности должен обеспечивать проверку результатов для любых возможных чередований событий. Кроме того, для исчерпывающего тестирования необходимо проверить результаты для различных чередований, т.е. уже недостаточно проверить одно из возможных чередований. Эта особенность должна быть учтена при оценке полноты тестирования. Особо важную роль в распределенных системах играет задача перебора различных чередований событий. В силу того, что появление того или иного порядка событий зависит от многих факторов, таких как планирование процессов в операционной системе, управлять которыми разработчик системы не имеет возможности, нет гарантии того, что данный порядок появится в процессе воздействия на систему. Перебор только части возможных чередований оставляет возможность проявления ошибки на непроверенных чередованиях. Ошибки такого рода крайне тяжело выявлять и исправлять; даже если такая ошибка обнаружена, ее трудно повторить, так как вероятность появления порядка, на котором проявляется ошибка, может быть крайне мала. Целью данной работы является построение метода тестирования, позволяющего гарантировать, что будут проверены все различные чередования событий, приводящие к разным результатам. Задача перебора различных чередований событий традиционно решается в методах проверки моделей (model checking), которые позволяют найти последовательность событий, нарушающих данную темпоральную формулу или доказать, что такой последовательности не существует. Методы проверки моделей работают с замкнутой системой, т.е.
системой, которая не принимает входных воздействий и не выдает реакций. Для верификации других систем, например, предоставляющих программный интерфейс, требуется предоставить окружение, взаимодействующее с системой. От размеров окружения напрямую зависит количество состояний, получающихся в процессе поиска. С другой стороны, от окружения зависит качество верификации, и далеко не всегда можно ограничиться простым окружением. Методы проверки моделей обладают рядом ограничений:
- Взрыв количества состояний;
- Требование функции сравнения состояний;
- Требование отката.
сброса системы в начальное состояние и повторного выполнения. Мы сформулируем задачу для случая, когда в реализации нет механизма отката и нет возможности сброса в начальное состояние. Мы будем предполагать, что вместо отката алгоритму поиска предоставляется возможность возврата в одно из состояний, которое принадлежит некоторому множеству, называемому обобщенным состоянием. Мы предполагаем, что последовательность воздействий на систему строится на основе обхода графа состояний конечного автомата [,]. Состояния автомата являются множествами исходных состояний системы и называются обобщенными состояниями. Множества выбираются, как разбиения состояний системы на классы эквивалентности. Возможность обобщенного отката реализуется за счет требования сильной связности графа состояний, необходимого для построения обхода графа. Таким образом, обобщенный откат - это путь в графе состояний, ведущий в требуемое обобщенное состояние. В следующем разделе описан пример, на котором будет продемонстрирован метод тестирования. В разделе "Алгоритм поиска" описан алгоритм, позволяющий перебирать различные порядки вызовов методов. Далее следует описание архитектуры, необходимой для его работы.