Microsoft Word petrenko rus doc



Yüklə 332,91 Kb.
səhifə2/3
tarix08.08.2018
ölçüsü332,91 Kb.
#61155
1   2   3

2.3 Основные понятия

Рассмотрим некоторую программную систему, содержащую функционально замкнутый набор процедур. Необходимо определить функциональные спецификации внешних интерфейсов, то есть определить программный контракт, а также разработать тестовые наборы, пригодные для проверки выполнения реализацией программного контракта. Поскольку элементами программного контракта являются процедуры, можно говорить о тестировании программного интерфейса, API. Далее будем считать, что программный интерфейс состоит только из процедур. Существуют и другие виды элементов API, такие как операции, функции, методы (в С++), подпрограммы (в Фортране) и т.д. Будем рассматривать все эти термины как синонимы и использовать для них термин

«процедура».

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

Дадим несколько определений. Часть тестовой системы, непосредственно участвующую в процессе выполнения тестов и взаимодействия с тестируемой системой (SUT – system under test), будем называть тестовым окружением (test harness). В некоторых случаях вместо SUT мы будем употреблять термин «целевая система». Основную часть тестового окружения составляют так называемые тестовые драйверы (test drivers). Функциональность тестовых драйверов опирается на систему поддержки времени выполнения (test bed). Тестовые драйверы

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

Мы различаем два уровня тестовых драйверов. Назовем базовым драйвером тестовый драйвер для некоторой процедуры, который выполняет следующие задачи:

проверяет выполнение предусловия

целевой процедуры на некотором

наборе входных параметров;

вызывает целевую процедуру с

данными входными параметрами и

сохраняет полученные значения выходных параметров;

выносит вердикт о корректности

работы целевой процедуры;



собирает информацию, необходимую

для оценки тестового покрытия, или

исследует причины ошибки.

Назовем скрипт-драйвером тестовый драйвер для некоторой целевой процедуры или группы процедур, который выполняет следующие задачи:



читает значения параметров

тестирования;



генерирует множество входных

параметров в соответствии с

полученными параметрами тестирования;

вызывает базовый драйвер с некоторым

набором входных параметров;



если необходимо, производит

дополнительную проверку

корректности работы целевой процедуры и выносит вердикт;

если желаемое тестовое покрытие не

достигнуто, продолжает генерировать

наборы значений входных параметров и вызывать базовые драйверы.

Назовем тестовым планом программу, которая определяет порядок вызовов скрипт-драйверов с данными параметрами

тестирования, проверяет условия вызова и

корректность завершения работы скрипт-

драйверов.

Кроме базовых и скрипт-драйверов и интерпретатора тест-планов тестовое окружение также содержит репозиторий и

инструменты для выполнения тест-планов и

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





реализации.

2.4 Шаги методологии

KIL методология состоят из нескольких шагов (см. рис. 1):



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

контракта;



разработка спецификаций;

генерация тестовых наборов;

выполнение тестов и анализ

результатов.

Рис. 1. KVEST методология – шаги и результаты

2.4.1 Определение состава программного контракта

Цели этого шага:



определить минимальный и

ортогональный интерфейс;



скрыть внутренние структуры данных и

детали реализации.

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

2.4.2 Разработка спецификаций

Цели:


Строго описать функциональность;

Создать входную информацию для

генерации тестов.

Базовые драйверы могут быть сгенерированы полностью автоматически.

2.4.3 Генерация тестовых наборов

Цели:


сгенерировать тестовые наборы;

дополнить сгенерированные тестовые

наборы компонентами, разработанными

вручную компонентами (MDC –

manually-developed component).

Большинство MDC представляют собой конвертеры между модельным и реализационным представлением данных,

инициализаторы тестовых структур данных

и итераторы. Тестовые наборы

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

Рис. 2. Общая схема KVEST технологии

2.4.4 Выполнение тестов и анализ результатов

К инструментам для пропуска тестов и анализа результатов предъявляются следующие требования:



автоматизация выполнения тестов;

сбор трассировочной информации и

вычисление достигнутого тестового

покрытия;

предоставление навигационных

возможностей;



возможность «инкрементального

тестирования», то есть восстановление

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

На рис. 2 обобщенно представлены

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

2.4.5 Метод тестирования

При разработке тестового драйвера необходимо решить три проблемы:



как сгенерировать оракула, то есть

программу, которая выносит вердикт о

корректности работы целевой процедуры;

как оценить полноту тестового

покрытия;



как перебирать комбинации тестовых

входных данных.

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

Критерий тестового покрытия – это метрика, определенная в терминах





реализации или спецификации. Наиболее известными критериями покрытия в терминах реализации являются:

C1 – все операторы покрыты;

C2 – все ветви покрыты.

В случае использования спецификаций

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

Хорошее покрытие доменов, даже дополненных интересными точками (например, находящимися на границах

доменов), не гарантирует хорошего

покрытия реализационного кода. Тем не менее, наш опыт показывает, что средний уровень покрытия при KVEST технологии составляет от 70 до 100 процентов операторов реализации.

Мы различаем два уровня критериев покрытия. Первый уровень – это покрытие всех ветвей постусловия. Второй – покрытие всех дизъюнктов (элементарных конъюнкций) в постусловии, представленном как СДНФ, также принимая во внимание предусловие. KVEST технология позволяет производить разбиение в терминах ветвей и СДНФ спецификации полностью автоматически. Одна из наиболее сложных проблем – вычисление достижимых дизъюнктов и удаление недостижимых дизъюнктов. В KVEST эта проблема решается путем использования специальных приемов написания предусловий.

Наблюдение за достигнутым тестовым покрытием производится скрипт- драйверами. Основываясь на этих данных,

скрипт-драйвер может подстраивать

параметры тестирования и/или длительность тестирования.



2.5 Технология генерации тестов
2.5.1 Классификация API

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

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

Эти классы упорядочены – первый класс накладывает самые строгие ограничения на процедуру, а последующие классы постепенно эти ограничения ослабляют:



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

Примеры взаимозависимостей между параметрами будут приведены ниже.



Класс 2. Взаимозависимости между входными параметрами отсутствуют.

Однако значения входных параметров не обязательно имеют литеральный вид. Такие

процедуры также могут тестироваться

поодиночке.

Пример: Процедура с указателем в качестве входного параметра.

Класс 3. Существуют некоторые взаимозависимости между входными

параметрами, однако возможно

тестирование отдельной процедуры.

Пример: Процедура с двумя параметрами – массив и значение одного из элементов массива.



Класс 4. Процедуры не могут

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

Пример: Процедуры, реализующие операции со стеком, которые получают стек в качестве параметра.

Класс 5. Процедуры не могут тестироваться по отдельности. Часть входных и выходных данных скрыта, то есть пользователь не имеет к ним прямого доступа.

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

Расширение классов API для случая параллельного выполнения. Теоретически, процедуры всех классов должны

тестироваться параллельно на случай, когда





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

Пример: Процедуры, работающие с почтовыми ящиками (прием и передача сообщений и т.п.)



Расширение классов API для случая процедур, которые могут вызвать аварийное завершение программы. Существует специальный класс процедур, для которых аварийное завершение программы является корректной реакцией в некоторых случаях.

Пример: Процедура, в которой может произойти деление на нуль, полученный в качестве входного параметра. Если эта

процедура не возвращает никакого кода

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



2.5.2 Схема скрипт-драйвера. Пример

API класса 5

Вышеприведенная таксономия является хорошей основой для классификации способов генерации тестов. Для API класса

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

усилий по созданию MDC. Эти усилия

плавно возрастают от класса 2 к классу 5. Специальные расширения классов требуют больших усилий, чем сами классы.

Усилия по созданию MDC обусловлены сложностью написания и отладки скрипт- драйверов. Ниже мы рассматриваем только одну схему скрипт-драйвера – для API класса 5. Все скрипт-драйверы имеют похожую структуру. Основное различие в пропорции между объемом автоматически сгенерированных и созданных вручную компонент. Скрипт-драйверы класса 1 генерируются полностью автоматически, класса 2 – почти автоматически и т.д.

Скрипт-драйвер – это программа, которая составляется и компилируется по KVEST технологии. Общая схема скрипт- драйвера определена формальным описанием, которое называется скелетоном. Для каждого класса API имеется свой скелетон. Каждый скрипт-драйвер состоит из деклараций и тела. Декларации генерируются автоматически на основании списка тестируемых процедур и их спецификаций.

Тело скрипт-драйвера начинается с разбора параметров тестирования. Эти параметры определяют глубину

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

До начала тестирования производится инициализация. Например, до начала тестирования процедур записи/чтения

файла необходимо этот файл открыть.

Такая инициализация пишется вручную. После инициализации начинает работу основная часть скрипт-драйвера.

Скрипт-драйвер класса 5 реализует общий алгоритм обхода абстрактного конечного автомата (FSM – Finite State Machine). Цель алгоритма – обойти все состояния автомата и все переходы между состояниями. Состояния конечного автомата соответствуют классам состояний модели исходной подсистемы. Каждый переход соответствует вызову тестируемой процедуры.

Алгоритм скрипт-драйвера зависит только от модели исходной подсистемы, не используя никаких деталей реализации,

которых нет в спецификации.

Наиболее интересный аспект алгоритма скрипт-драйвера состоит в отсутствии явного описания конечного автомата. Прямое описание конечного автомата требует дополнительных усилий, которых по KVEST технологии можно избежать. Существуют попытки построения конечного автомата по имплицитным спецификациям [7]. Однако пока никто не смог предложить полностью автоматического способа такого построения.

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

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



Выбираем очередную процедуру из

группы.




Вызываем итераторы, которые

формируют набор значений входных

параметров для этой процедуры.

Если итераторам удалось сформировать

новый корректный набор значений,

удовлетворяющий предусловию,

скрипт-драйвер вызывает соответствующий базовый драйвер с этими параметрами.



Если корректного набора значений

сформировать не удалось, возвращаемся

к началу и повторяем попытку для следующей процедуры.

После того, как базовый драйвер

закончил работу, скрипт-драйвер

проверяет вынесенный им вердикт.

Если вердикт положительный

(элементарный шаг тестирования

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

2.5.3 Композиция тестового набора


Нам необходимо

5 скелетонов

для

последовательного

тестирования

API




Вернемся к вопросу соединения MDC и автоматически генерируемых компонент. Скрипт-драйверы создаются следуя требованиям соответствующего скелетона.


значениями по




умолчанию

для

инициализаторов

и

итераторов.

Если




классов 1-5; один скелетон для параллельного тестирования и пять скелетонов для тестирования процедур, которые могут вызвать аварийное завершение программы. На основе скелетона и спецификаций целевых процедур по KVEST технологии генерируется шаблон скрипт-драйвера. Для класса 1 шаблон представляет собой готовую программу. В шаблонах остальных классов имеются гнезда, заполненные

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

Базовые драйверы, вызываемые скрипт- драйверами, генерируются полностью автоматически. Единственные MDC, вызываемые из базовых драйверов – это

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

Рис. 3. Схема генерации тестового набора, независимого от целевого языка программирования

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

выходе текст на языке RSL. Единственные

компоненты, которые пишутся на языке реализации – это конвертеры данных. Эти компоненты находятся вне зоны ответственности генераторов тестов. Таким образом, результатом процесса генерации тестов является полный текст тестового набора на языке RSL, который затем транслируется в язык реализации. Чтобы перенести тестовый набор, построенный по KVEST технологии, с одного целевого языка в другой, пользователю необходимо переписать все конвертеры данных и предоставить транслятор с RSL в целевой язык, а также СПВВ. Схема генерации тестов находится на рис. 3.



Yüklə 332,91 Kb.

Dostları ilə paylaş:
1   2   3




Verilənlər bazası müəlliflik hüququ ilə müdafiə olunur ©www.genderi.org 2024
rəhbərliyinə müraciət

    Ana səhifə