Институт Системного Программирования Российской Академии Наук |
Инструмент тестирования CTesK |
Рабочие материалы слушателя курсов |
Москва 2004 |
Программа курса
1. Введение
Назначение инструмента CTesK. Тестирование. Целевая система, тестовая система, результаты тестирования.
Архитектура теста в CTesK. Генерируемые компоненты теста, библиотечные компоненты, компоненты, разрабатываемые в ручную.
Шаги разработки теста при помощи CTesK. Разработка спецификаций, разработка медиаторов, разработка сценариев, отладка и выполнение теста и анализ тестовых результатов.
Тестирование на соответствие требованиям. Формальные требования. Критерии покрытия.
2. Спецификация целевой системы
Спецификация данных. Типы с инвариантами, спецификационные типы, моделирование внутреннего состояния целевой системы в спецификации при помощи глобальных переменных, инварианты глобальных переменных.
Спецификация интерфейсных функций. Спецификационные функции, пред - и постусловия, критерии покрытия, пред - и пост-значения параметров и переменных в спецификационных функциях.
Спецификация отложенных реакций. Отложенные реакции, пред - и постусловия, пред‑ и пост-значения переменных в отложенных реакциях. Сериализация.
3. Медиаторы
Преобразования типов спецификационной модели в типы реализации и обратно. Вычисление значений аргументов вызова функции реализации. Вычисление результатов вызова спецификационной функции.
Синхронизация состояния спецификации с состоянием реализации. Вычисление состояния спецификации из состояния реализации ("открытое" состояние). Вычисление состояния спецификации без доступа к состоянию реализации ("скрытое" состояние).
Регистрация отложенных реакций. Сборщик реакций. Регистрация реакций. Каналы взаимодействий.
4. Тестовые сценарии
Определение последовательности тестовых воздействий на целевую систему при помощи сценария. Сценарий с одним состоянием. Сценарий с множеством различных состояний. Сценарные функции. Итерация значений аргументов вызова спецификационных функции в сценарных функциях. Процедуры инициализации и завершения сценария.
Обобщение состояния спецификации в сценарии.
Стационарное тестирование. Время ожидания стабилизации. Стационарные состояния.
5. Сборка и отладка теста, анализ результатов тестирования
Запуск инструмента CTesK. Опции командной строки. Сборка компонентов тестовой и целевой систем в исполняемый модуль. Шаги отладки тестовой системы. Дополнительная трассировка. Соответствие между спецификациями и компонентами тестовой системы. Виды ошибок. Способы улучшения покрытия.
Тема 1. Назначение CTesK. Архитектура теста в CTesK
Определения тестирования
Тестирование — это процесс воздействия на систему или компонент при специальных условиях, учета или записывания результатов и произведения оценки некоторых аспектов системы или компонента.
(Testing is the process of operating a system or component under specified conditions, observing or recording the results, and making an evaluation of some aspect of the system or component.)
[ANSI/IEEE standard 610.12-1990: glossary of software engineering terminology.]
Тестирование: Процесс анализа элемента программы с целью обнаружения отличий между существующими и требуемыми его свойствами (т. е. ошибок) и на предмет оценки отличительных характеристик этого элемента.
(testing: The process of analyzing a software item to detect the differences between existing and required conditions (that is, bugs) and to evaluate the features of the software item.
software feature: A distinguishing characteristic of a software item (e. g., performance, portability, or functionality).
software item: Source code, object code, job control code, control data, or a collection of these items.)
[IEEE Standard : IEEE Standard for Software Test Documentation.]
Тестирование программного обеспечения — это процесс выполнения программного обеспечения в управляемом режиме с целью получения ответа на вопрос: «Ведет ли себя программное обеспечение так, как специфицировано?»
(Testing of software is a process of software execution in controlled order to get the answer on the question: “Does software behave as specified?”)
[Methodic materials of IPL company]
Тестирование — процесс выполнения программы с намерением найти ошибки.
(Testing is the process of executing a program or system with the intent of finding errors.)
[G. Meiers Software reliability. Addison Wesley. 1979.]
Тестирование — проверка системы для того, чтобы убедиться в том, что все части анализируемой модели реализованы правильно, и что производительность системы отвечает требованиям.
(Testing is a checking of system to make certain that all parts of analysis model are implemented properly and that system performance conforms with requirements.)
[Ivar Jacobson. Object-oriented software engineering. Revised 4-th printed. Addison Wesley. 1994.]
Тестирование — это не деятельность. Это интеллектуальная дисциплина, имеющая целью получение надежного программного обеспечения без излишних усилий на проверку.
(Testing is not an activity. It’s a intellectual discipline having the goal of delivering robust software without unneeded effort for verification.)
[B. Beizer. Software Testing Techniques. Addison Wesley. 1989.]
Ключевые термины
Взаимодействие с целевой системой — обмен данными между целевой системой и ее окружением (например, тестовой системой): воздействия на целевую систему через ее интерфейс и получение от нее реакций.
Воздействие на целевую систему — передача данных извне через интерфейс системы (вызов функции прикладного программного интерфейса с некоторыми значениями параметров, передача сообщения, содержащего некоторые данные).
Время ожидания стабилизации — время, за которое целевая система переходит в стационарное состояние после завершения работы любой сценарной функции.
Итератор тестовых воздействий — компонент, определяющий набор воздействий в тесте.
Канал взаимодействий — набор взаимодействий с целевой системой, упорядоченный согласно порядку, в котором эти взаимодействия происходили.
Критерий тестового покрытия — метрика, при помощи которой оценивается полнота тестовой последовательности.
Медиатор — компонент тестовой системы, преобразующий интерфейс спецификации в интерфейс реализации и обратно.
Непосредственная реакция — реакция, наблюдаемая сразу после определенного воздействия на систему.
Обходчик — компонент тестовой системы, реализующий алгоритм построения тестовой последовательности.
Отложенная реакция — реакция, наблюдаемая через некоторое время после воздействий на систему.
Оракул — компонент тестовой системы, функциональность которого заключается в вынесении вердикта о корректности работы целевой системы при очередном тестовом воздействии.
Параметры воздействия — набор данных, определяющий воздействие (какая функция прикладного программного интерфейса и с какими значениями параметров вызывается, какой тип сообщения и с какими данными передается и т. д.).
Реакция — видимый снаружи результат работы целевой системы.
Сборщик реакций — компонент тестовой системы, ответственный за сбор всех отложенных реакций целевой системы.
Сериализация — процесс оценки корректности поведения целевой системы посредством анализа возможных вариантов упорядочивания взаимодействий.
Спецификация (формальная) — допускающее автоматическую обработку, однозначно интерпретируемое описание функциональных требований к целевой системе.
Стационарное состояние — состояние, в котором не ожидается ни одной отложенной реакции от целевой системы.
Тестовая последовательность — совокупность тестовых воздействий, проведенных во время прогона теста.
Тестовая система — комплекс программ, предназначенный для тестирования целевой системы.
Тестовое воздействие — однократное воздействие на целевую систему (вызов функции прикладного программного интерфейса с некоторыми значениями параметров, передача сообщения, содержащего некоторые данные) при прогоне теста, сбор и анализ всех результатов данного воздействия.
Тестовое покрытие — значение метрики (критерия тестового покрытия) для конкретного прогона теста.
Тестовый сценарий — набор данных, на основе которых обходчик строит тестовую последовательность.
Целевая система – программная система, которая должна быть протестирована. Синонимы и сокращения:
тестируемая система (SUT — System Under Test) тестируемая реализация (IUT — Implementation Under Test),часто просто — реализация (implementation)
Целевая система, реализующая на языке C очередь ограниченного размера для хранения данных типа int с поддержкой сервиса наблюдателей
Система предоставляет пользователю четыре интерфейсные функции, которые можно вызывать снаружи и получать наблюдаемые снаружи результаты работы системы:
- void queue_init (size_t size) — функция инициализации очереди устанавливает максимальное число элементов в очереди;
- int queue_put (int i) — функция помещения элемента в хвост очереди помещает элемент в нее, если количество элементов в очереди меньше максимального, помещенный элемент может быть извлечен после извлечения всех элементов, помещенных в очередь раньше него, если очередь полна возвращается ноль, иначе — число отличное от нуля;
- int queue_get (int *i) — функция удаления элемента из головы очереди удаляет элемент из очереди, если очередь не пуста, и возвращает его через переданный указатель, если очередь пуста возвращается ноль, иначе — число отличное от нуля;
- void queue_register (queue_observer_t obsvr) — функция регистрации наблюдателей регистрирует, переданный ей указатель на функцию определенного типа (typedef void (*queue_observer_t) (void)), которая должна вызваться в отдельной нити при каждом изменении количества элементов очереди.
Целевая система, реализующая на языке C стек ограниченного размера для хранения данных типа void*
Система предоставляет пользователю три интерфейсные функции:
- void push (void* item) — помещает элемент в голову стека, помещаемый элемент не должен быть нулевым указателем, функцию нельзя вызывать, если число элементов в стеке равно максимальному;
- void* pop () — извлекает элемент из головы стека и возвращает его, если стек пуст, то возвращается нулевой указатель;
- int isEmpty () — возвращает ненулевое значение, если стек пуст, и ноль в противном случае;
- void size () — возвращает количество элементов в стеке.
Специфицирование целевой системы

Ключевые конструкции спецификационного расширения языка C —
SeC (Specification Extension of C)
Типы данных и их инварианты
/* Определение спецификационного типа */ typedef specification <имя базового типа> <имя определяемого типа> =
{ .init = <указатель на функцию инициализации>
, .copy = <указатель на функцию копирования>
, .compare = <указатель на функцию сравнения>
, .to_string = <указатель на функцию преобразования в строку>
, .enumerate = <указатель на функцию, перечисляющую содержащиеся объекты>
, .destroy = <указатель на функцию, освобождающую ресурсы> };
/* Декларация типа с инвариантом */
typedef invariant <имя базового типа> <имя определяемого типа>;
/* Определение инварианта типа */
invariant(<имя типа> <имя аргумента>) {
/*
Набор инструкций, эквивалентный телу функции с аргументом типа, для
которого определяется инвариант, и возвращающей результат типа bool:
true, если для переданного значения инвариант типа выполняется (согласно
требованиям), и false — в противном случае.
*/
/* код, проверяющий выполнение инварианта */
return <значение типа bool>;
}
/* Декларация глобальной переменной с инвариантом */
invariant <декларация переменной>;
/* Определение инварианта глобальной переменной */
invariant(<имя переменной>) {
/*
Набор инструкций, эквивалентный телу функции без аргументов,
возвращающей результат типа bool: true, если для текущего значения
глобальной переменной инвариант выполняется (согласно требованиям), и
false — в противном случае.
*/
/* код, проверяющий выполнение инварианта */
return <значение типа bool>;
}
Спецификации
/* Определение спецификационной функции */
specification
<имя типа возвращаемого значения> <имя функции>(<список аргументов>)
<ограничения доступа>
{
pre {
/*
Набор инструкций, эквивалентный телу функции с аргументами,
совпадающими по значению с входными значениями аргументов
спецификационной функции, и возвращающей результат типа bool: true, если
при текущих значениях глобальных переменных допускается (согласно
требованиям) оказывать специфицируемое воздействие с переданными
значениями параметров, и false — в противном случае.
*/
/* код, проверяющий выполнение предусловия */
return <значение типа bool>;
}
coverage <имя покрытия> {
/*
Набор инструкций, эквивалентный телу функции, с аргументами,
совпадающими по значению с входными значениями аргументов
спецификационной функции, и возвращающей конструкцию
{<идентификатор>, <строковый литерал>}. Например:
if (<1ое условие на пре‑значения аргументов>)
return {1th_branch, "first branch"};
else if (<предпоследнее условие на пре‑значения аргументов >)
return {pre_last_branch, "pre-last branch"};
else
return {last_branch, "last branch"};
*/
/* код, определяющий ветви */
return {<идентификатор>, <строковый литерал>};
}
post {
/*
Набор инструкций, эквивалентный телу функции, с аргументами,
совпадающими с аргументами спецификационной функции, и возвращающей
результат типа bool: true, если входные данные воздействия
(входные значения параметров воздействия, значения глобальных переменных
до воздействия) соответствуют (согласно требованиям)
полученным выходным данным (значение возвращаемого результата, выходные
значения параметров воздействия, значения глобальных переменных после
взаимодействия), и false — в противном случае.
Значения аргументов и глобальных переменных после взаимодействия с целевой
системой доступны через их идентификаторы.
Значение возвращаемого результата доступно через идентификатор,
совпадающий с именем спецификационной функции.
Значения аргументов и глобальных переменных до взаимодействия с целевой
системой, доступны при помощи оператора @.
*/
/* код, проверяющий выполнение постусловия */
return <значение типа bool>;
}
}
/* Определение отложенной реакции */
reaction < имя типа возвращаемого значения > <имя функции>()
<ограничения доступа>
{
pre {
/*
Набор инструкций, эквивалентный телу функции без аргументов,
возвращающей значение типа bool: true, если возникновение реакции возможно
(не противоречит требованиям) в текущем состоянии (определяется
значениями глобальных переменных), и false — в противном случае.
*/
/* код, проверяющий выполнение предусловия */
return <значение типа bool>;
}
post {
/*
Набор инструкций, эквивалентный телу функции без аргументов,
возвращающей результат типа bool: true, если возникновение реакции и ее
значение не противоречит требованиям, и false — в противном случае.
Значения глобальных переменных после возникновения реакции доступны через
их идентификаторы.
Значение реакции доступно через идентификатор, совпадающий с именем
спецификационной функции отложенной реакции.
Значения глобальных переменных до возникновения реакции доступны, при
помощи оператора @.
*/
/* код, проверяющий выполнение постусловия */
return <значение типа bool>;
}
}
Медиаторы
/* Определение медиаторной функции */ mediator <имя медиаторной функции> for
<сигнатура спецификационной функции или отложенной реакции>
<ограничения доступа>
{
call {
/*
(Только для медиаторов спецификационных функций)
Набор инструкций, эквивалентный телу функции, с аргументами,
совпадающими с аргументами спецификационной функции, и возвращающей
результат того же типа. В блоке воздействия определяется
- преобразование значений аргументов спецификационной функции
в значения параметров воздействия на целевую систему
(например, значения аргументов вызова интерфейсной функции
реализации)
- воздействие на целевую систему (например, вызов интерфейсной функции
реализации)
- преобразование результатов взаимодействия с целевой системой в
значения возвращаемого результата и выходных значений аргументов
спецификационной функции.
*/
/* код воздействия */
return <результат вызова спецификационной функции>;
}
state {
/*
Набор инструкций, эквивалентный телу функции без возвращаемого
значения с аргументами, совпадающими с аргументами спецификационной
функции, или без аргументов в случае медиатора отложенной реакции.
В блоке синхронизации состояние спецификации (определяемое набором
значений глобальных переменных) вычисляется либо на основе состояния
реализации после взаимодействия (если оно доступно), либо на основе
состояния спецификации до взаимодействия, результатов взаимодействия и (в
случае медиатора спецификационной функции) параметров воздействия.
Возвращаемое из блока воздействия значение доступно через идентификатор,
совпадающий с именем спецификационной функции.
Значение реакции доступно через идентификатор, совпадающий с именем
реакции.
*/
/* код синхронизации состояний */
}
}
Тестовые сценарии
/* Определение сценария */ scenario dfsm <имя сценария>= {
.init = <имя функции инициализации теста типа bool(*PtrInit)(int, char**)>;
, .getState =
<имя функции вычисления состояния теста типа Object*(*PtrGetState)()>
, .actions = {<список имен сценарных функций>, NULL}
, .finish = <имя функции завершения теста типа void(*PtrFinish)()>
, .saveModelState =
<имя функции, сохраняющей состояние спецификации типа
Object*(*PtrSaveModelState)()
>
, .restoreModelState = <имя функции, восстанавливающей состояние спецификации типа
void(*PtrRestoreModelState)(Object*)
>
, .isStationaryState =
<имя функции, определяющей стационарность состояния спецификации типа
bool(*PtrIsStationaryState)()
>
};
/* Определение сценарной функции */
scenario bool <имя сценарной функции>() {
/*
Набор инструкций, эквивалентный телу функции без аргументов,
возвращающей значение булевского типа. В сценарной функции итерируются
параметры воздействий (спецификационных функций) и осуществляются
взаимодействия с целевой системой (путем вызовов спецификационных
функций). В каждом достигнутом состоянии теста происходит отдельная
итерация параметров.
*/
/* код итерации параметров и вызова спецификационных функций */
return <значение типа bool>;
}
/* оператор iterate */
iterate
( <инициализация итерации>
; <условие завершения>
; <вычисление значений следующего шага итерации в том же самом состоянии>
; <условие фильтрации>
) {
/* код итерации и вызовы спецификационных функций */
}
Структура курса

Архитектура тестовой системы в CTesK

Задание:
Провести связи между компонентами. Отметить буквами следующие компоненты системы:А — библиотечные
В — сгенерированные
С — сделанные вручную
Таблица соответствия шагов разработки теста при помощи CTesK и компонентов тестовой системы
Шаги разработки теста при помощи CTesK | Содержание шага | Компоненты тестовой системы |
| Спецификация целевой системы | ® Определение множества специфицируемых функций ® Спецификация данных: модельного состояния системы и модельных параметров ® Спецификация функций ® Генерация компонентов | |
Разработка медиаторов | ® Определение преобразований типов из модельных в реализационные и обратно ® Преобразование или вычисление состояния ® Генерация компонентов | |
Разработка тестовых сценариев | ® Определение набора функций, тестируемых в каждом сценарии ® Обобщение состояния ® Определение итерации параметров ® Генерация компонентов | |
Отладка тестовой системы | При отладке возможен возврат к любому из предыдущих шагов | |
Прогон тестов, сбор и анализ результатов |
Вопросы:
Тема 2. Тестирование функциональности, независящей от истории взаимодействий системы с окружением
Постановка задачи
Требуется построить тест для функции, которая произвольное смешанное число (например,
) приводит к числу с правильной дробной частью (для приведенного примера —
).
В реализации смешанные числа представляются в виде структуры:
typedef struct mix_num {
int integral; /* целая часть смешанного числа */
int num; /* числитель дробной части смешанного числа */
int denom; /* знаменатель дробной части смешанного числа */
} mix_num;
Поле denom должно быть не меньше нуля. Если смешанное число положительное, то поля integral и num должны быть не меньше нуля. Если смешанное число отрицательное, то поля integral и num должны быть не больше нуля. Если смешанное число равно нулю, то поля integral и num должны быть равны нулю.
Реализация предоставляет интерфейсную функцию mix_num trunc(mix_num *mn), которая в качестве входного параметра принимает указатель на смешанное число (указатель на тип mix_num) и возвращает в качестве результата смешанное число (значение того же типа mix_num).
Должны выполняться следующие требования:
- значение возвращаемого результата должно быть равно значению по переданному указателю после выполнения функции; поле denom по переданному указателю не изменяется; в возвращаемой структуре абсолютное значение поля num должно быть меньше значения поля denom; возвращаемое смешанное число должно быть равно смешанному числу, переданному через указатель, то есть сумма числителя дробной части (поле num) и произведения целой части (поле integral) на знаменатель дробной части (поле denom) возвращаемого смешанного числа должна быть равна сумме числителя дробной части и произведения целой части на знаменатель дробной части смешанного числа по переданному указателю до выполнения функции.
Основные элементы спецификации
Спецификационная функция:
Предусловие (семантика кода в предусловии, какие аргументу могут использоваться):
Критерии покрытия: (семантика кода в критериях покрытия, какие аргументу могут использоваться):
Постусловие: (семантика кода в постусловии, какие аргументу могут использоваться)
Инвариант типа: (семантика кода в теле инварианта)
Медиаторы
Медиатор: (семантика кода медиатора, функциональность медиатора)
Тестовые сценарии
Тестовый сценарий: (структура)
Сценарная функция: (семантика кода)
Оператор iterate: (семантика кода)
Функция инициализации: (тип, функциональность)
Функция завершения: (тип, функциональность)
Вопросы:
Тема 3. Тестирование функциональности, зависящей от истории взаимодействий системы с окружением
Работа с текстом “Тестирование функциональности, зависящей от истории взаимодействий системы с окружением” | “?” осталось непонятным | В тексте разместить значками: “V” – места, в которых все понятно и нет ничего нового; “–” – места, которые противоречат первоначальным знаниям читателя; “+” – места, в которых читатель получил новые знания и понял их; “?” – места, которые остались непонятными | |
“+” новая информация | |||
“–” информация противоречит моему первоначальному знанию | |||
“V” информация не противоречит моему первоначальному знанию |
Постановка задачи
Построить тест для системы, реализующей мультимножество целых чисел, то есть множество, в которое элементы могут входить несколько раз. Считается, что элемент, не содержащийся в мультимножестве, входит в него с нулевой кратностью.
Система предоставляет следующий интерфейс:
o struct MultiSet *multiset_create () —
создает мультимножество и возвращает указатель на него;
o void multiset_destroy (struct MultiSet *ms) —
уничтожает мультимножество по переданному указателю;
o void multiset_add (struct MultiSet *ms, int i) —
добавляет элемент в мультимножество;
o void multiset_remove (struct MultiSet *ms, int i) —
удаляет элемент из мультимножества;
o int multiset_contains (struct MultiSet *ms, int i) —
проверяет, содержится ли данный элемент в мультимножестве.
Требуется протестировать функции multiset_add(), multiset_remove() и multiset_contains().
К интерфейсным функциям предъявляются следующие требования:
1. Функция multiset_add() получает на вход указатель на созданное ранее с помощью функции multiset_create() мультимножество и элемент (целое число). В результате работы функции кратность вхождения элемента в мультимножество увеличивается на единицу.
2. Функция multiset_remove() получает на вход указатель на созданное ранее с помощью функции multiset_create() мультимножество и элемент (целое число). В результате работы функции кратность вхождения элемента в мультимножество уменьшается на единицу. Если элемент входил в мультимножество с нулевой кратностью, мультимножество не изменяется.
3. Функция multiset_contains() получает на вход указатель на созданное ранее с помощью функции multiset_create() мультимножество и элемент (целое число). Функция возвращает 1, если элемент входит в мультимножество с ненулевой кратностью, и 0 в противном случае.
Вопросы:
Тема 4. Тестирование с обобщенным состоянием
Работа с текстом “ Тестирование с обобщенным состоянием ” | “?” осталось непонятным | В тексте разместить значками: “V” – места, в которых все понятно и нет ничего нового; “–” – места, которые противоречат первоначальным знаниям читателя; “+” – места, в которых читатель получил новые знания и понял их; “?” – места, которые остались непонятными | |
“+” новая информация | |||
“–” информация противоречит моему первоначальному знанию | |||
“V” информация не противоречит моему первоначальному знанию |
Постановка задачи
Построить тест для системы, реализующей очередь с приоритетами, то есть очередь, элементам которой сопоставлены приоритеты. Элементами очереди являются указатели типа void*, приоритет задается целым числом.
Приоритетная очередь представлена в реализации списком приоритетов, элементы которого являются списками данных с данным приоритетом. Структура MPQueue содержит указатели на элементы списка приоритетов, соответствующие началу и концу очереди:
struct MPQueue {
struct PLink *first;
struct PLink *last;
};
Список приоритетов является двунаправленным, элемент такого списка представлен структурой PLink, содержащей указатели на следующий и предыдущий элементы (nxt и prv соответственно), значение приоритета (priority) и указатели на элементы списка данных, соответствующие началу и концу очереди (first и last):
struct PLink {
struct PLink *nxt;
struct PLink *prv;
int priority;
struct Link *first;
struct Link *last;
};
Список данных также является двунаправленным. Элемент списка данных представлен структурой Link, содержащей указатели на следующий и предыдущий элементы (nxt и prv соответственно) и значение (item):
struct Link {
struct Link *nxt;
struct Link *prv;
void *item;
};
Список приоритетов всегда упорядочен по убыванию значений приоритета (т. е. начало списка содержит наибольший приоритет). Список данных всегда упорядочен по порядку поступления элементов в очередь (т. е. начало списка содержит элемент, поступивший ранее других).
Система предоставляет следующий интерфейс:
o struct MPQueue *createMPQueue () —
создает очередь и возвращает ссылку на нее;
o void destroyMPQueue (struct MPQueue *mpq) —
уничтожает очередь по переданной ссылке;
- void enq (struct MPQueue *mpq, void *item) —
помещает элемент в очередь с минимальным приоритетом; void enqp (struct MPQueue *mpq, void *item, int p) —
помещает элемент в очередь с указанным приоритетом; void *deq (struct MPQueue *mpq) —
исключает элемент из очереди и возвращает его.
Требуется протестировать функции enq(), enqp() и deq().
К интерфейсным функциям предъявляются следующие требования:
1. Функция enq() получает на вход указатель на созданную ранее с помощью функции createMPQueue() очередь и ненулевой элемент (типа void*). В очередь добавляется переданный элемент, которому сопоставляется минимальный приоритет (константа MIN_PRIORITY).
2. Функция enqp() получает на вход указатель на созданную ранее с помощью функции createMPQueue() очередь, ненулевой элемент (типа void*) и приоритет (целое число). В очередь добавляется переданный элемент с указанным приоритетом. Приоритет должен находиться в диапазоне от MIN_PRIORITY до MAX_PRIORITY включительно.
3. Функция deq() получает на вход указатель на созданную ранее с помощью функции createMPQueue() очередь. Функция исключает из очереди элемент, имеющий наибольший приоритет и помещенный ранее всех элементов с тем же приоритетом, и возвращает его. Если очередь пуста, возвращается нулевой указатель.
Шаги разработки теста для системы с прикладным программным интерфейсом (API) при помощи CTesK
1. Разработка спецификаций
- Спецификация данных
- Определение типов данных и их инвариантов для входных и выходных аргументов интерфейсных функций Определение типов данных для глобальных переменных, определяющих состояние спецификации, определение инвариантов этих типов Определение глобальных переменных и их инвариантов
- Определение предусловия (тело предусловия должно быть эквивалентно телу функции без видимых побочных эффектов, которая имеет те же аргументы, что и спецификационная функция, и возвращает true, если значения аргументов являются допустимыми (согласно требованиям) в текущем состоянии спецификации (при текущих значениях глобальных переменных), и false в противном случае) Определение постусловия (тело постусловия должно быть эквивалентно телу функции без видимых побочных эффектов, которая имеет те же аргументы, что и спецификационная функция, и возвращает true, если результаты (пост‑значения аргументов и возвращаемое значение) и пост‑состояние (пост‑значения глобальных переменных) соответствуют (согласно требованиям) пре‑значениям аргументов и глобальных переменных, и false в противном случае) Определение ветвей функциональности (тело критерия покрытия должно быть эквивалентно телу функции без видимых побочных эффектов, которая имеет те же аргументы, что и спецификационная функция, и возвращает идентификатор ветви и строковый литерал с коротким описанием ветви, заключенные в фигурные скобки и разделенные запятой, соответствующие функциональности при переданных значениях аргументов и текущем состоянии спецификации)
2. Разработка медиаторов
o Определение вызова интерфейсной функции реализации (тело блока вызова должно быть эквивалентно телу функции без видимых побочных эффектов, которая имеет те же аргументы, что и спецификационная функция, возвращает значение того же типа, что и спецификационная функция, и реализует:
§ преобразование аргументов спецификационной функции в аргументы интерфейсной функции реализации
§ вызывает интерфейсную функцию реализации
§ преобразует результаты вызова интерфейсной функции реализации (выходные значения аргументов и возвращаемое значение) в результаты вызова спецификационной функции (выходные значения аргументов и возвращаемое значение)
o Синхронизация состояния спецификации с состоянием тестируемой реализации (тело блока синхронизации должно быть эквивалентно телу функции без возвращаемого значения, не имеющей видимых побочных эффектов, которая имеет те же аргументы, что и спецификационная функция, и вычисляет состояние спецификации после взаимодействия либо на основе состояния реализации после взаимодействия (если оно доступно), либо на основе состояния спецификации до взаимодействия, результатов взаимодействия и параметров воздействия (в случае медиатора спецификационной функции).
3. Разработка тестовых сценариев
- Определение состояния теста
- Определение типа (должен быть спецификационным типом) состояния теста в соответствии с требованиями детерминированности и связности Определение функции преобразования состояния спецификации в состояние теста (функция должна не иметь аргументов и возвращать ссылку на спецификационный тип, определенный для состояния теста)
- Определение итерации значений аргументов спецификационных функций в каждом достижимом состоянии теста при помощи оператора iterate в соответствии с требованиями детерминированности и связности
- Анализ и обработка параметров командной строки запуска теста Инициализация тестируемой реализации Инициализация состояния спецификации
- Корректное завершение работы тестируемой реализации и тестовой системы
4. Компиляция, сборка, выполнение теста, генерация отчетов, воспроизведение трассы и анализ результатов
Тема 5. Тестирование систем с отложенными реакциями
Семафоры
Подсистема работы с семафорами предназначена для синхронизации работы потоков управления внутри одного процесса.
Подсистема работы с семафорами состоит из пяти функций:
· sem_open
· sem_close
· sem_wait
· sem_post
· sem_getvalue
sem_open
Имя
sem_open – открытие именованного семафора
Синтаксис
#include <semaphore. h>
sem_t sem_open(const char *name, unsigned init_value);
Аргументы
Name | указатель на имя семафора; |
init_value | значение, которое присваивается семафору при создании. |
Возвращаемые значения
При успешном завершении функция возвращает дескриптор семафора. В противном случае функция возвращает значение SEM_FAILED и присваивает переменной errno код ошибки:
[EINVAL] | значение указателя на имя равно NULL или значение аргумента init_value превышает MAX_SEM_VALUE; |
[ENFILE] | в текущий момент в системе открыто слишком много семафоров; |
[ENOSPC] | недостаточно памяти для создания нового именованного семафора. |
Описание
Функция sem_open() обеспечивает поиск семафора по его имени, а если требуется, создает семафор. При успешном открытии функция sem_open() возвращает дескриптор семафора, который может использоваться в функциях sem_wait(), sem_post() и sem_getvalue() до тех пор, пока семафор не будет закрыт в результате успешного выполнения функции sem_close().
Аргумент name указывает на строку с именем семафора. Если указатель равен NULL, то функция возвратит SEM_FAILED с соответствующим кодом ошибки.
Если в программе выполняется несколько вызовов функции sem_open() с одним и тем же значением аргумента name, при каждом успешном вызове будет возвращаться дескриптор одного и того же семафора, если для данного семафора не вызывалась функция sem_close().
Аргумент init_value задает значение семафора, которое должно быть присвоено семафору при создании. Это значение не должно превышать MAX_SEM_VALUE.
sem_close
Имя
sem_close - закрытие именованного семафора
Синтаксис
#include <semaphore. h>
int sem_close(sem_t sem);
Аргумент
Sem | дескриптор семафора. |
Возвращаемые значения
При успешном завершении функция возвращает 0. Если обнаружена ошибка, то функция возвращает значение -1, а переменной errno присваивается код ошибки:
[EINVAL] | аргумент sem не является корректным дескриптором семафора; |
[EBUSY] | имеются потоки управления, ожидающие освобождения семафора. |
Описание
Функция sem_close() удаляет дескриптор семафора, на который ссылается аргумент sem. Если для этого семафора не осталось ни одного дескриптора, то будет уничтожен и сам семафор. Использовать дескриптор семафора sem после успешного выполнения функции sem_close() не разрешается.
sem_wait
Имя
sem_wait – захват семафора
Синтаксис
#include <semaphore. h>
int sem_wait(sem_t sem);
Аргумент
Sem | дескриптор семафора. |
Возвращаемые значения
При успешном завершении функция возвращает 0. Если обнаружена ошибка, то функция возвращает значение -1, а переменной errno присваивается код ошибки:
[EINVAL] | аргумент sem не является корректным дескриптором семафора. |
Описание
Функция sem_wait() захватывает семафор, заданный аргументом sem. В начале проверяется счетчик семафора. Если значение счетчика больше нуля, то оно уменьшается на 1, и семафор считается захваченным. Если счетчик равен 0, то это означает, что в настоящее время семафор не может быть захвачен. В таком случае функция sem_wait() приостанавливает поток управления (устанавливает его в очередь к семафору) до освобождения семафора.
Для освобождения семафора предназначена функция sem_post().
Если функция sem_wait() завершается с ошибкой, то состояние семафора в результате ее вызова не меняется.
sem_post
Имя
sem_post - освобождение семафора
Синтаксис
#include <semaphore. h>
int sem_post(sem_t sem);
Аргументы
Sem | дескриптор семафора. |
Возвращаемые значения
При успешном завершении функция возвращает 0. Если обнаружена ошибка, то функция возвращает значение -1, а переменной errno присваивается код ошибки:
[EINVAL] | аргумент sem не является корректным дескриптором семафора. |
Описание
Функция sem_post() освобождает семафор, заданный аргументом sem. При освобождении семафора в начале проверяется, имеются ли потоки, ожидающие освобождения семафора. Если таких потоков нет, счетчик семафора увеличивается на 1. В противном случае значение счетчика не меняется, а из очереди к семафору выбирается поток управления и объявляется работоспособным. При этом выбирается поток с наибольшим приоритетом, а среди них тот, который дольше других находился в очереди к семафору.
sem_getvalue
Имя
sem_getvalue - опрос счетчика семафора
Синтаксис
#include <semaphore. h>
int sem_getvalue(sem_t sem, int *sval);
Аргументы
sem | дескриптор семафора; |
sval | указатель на переменную, которой будет присвоено значение счетчика семафора. |
Возвращаемые значения
При успешном завершении функция возвращает 0. Если обнаружена ошибка, то функция возвращает значение -1, а переменной errno присваивается код ошибки:
[EINVAL] | аргумент sem не является корректным дескриптором семафора. |
Описание
Функция sem_getvalue() присваивает переменной, на которую указывает аргумент sval, значение счетчика семафора, заданного аргументом sem, не изменяя при этом состояние семафора. Записанное значение представляет собой фактическое значение счетчика семафора в некоторый момент времени в период выполнения функции, но оно не обязано совпадать с фактическим значением счетчика семафора в момент возврата управления.
Если семафор sem захвачен, значение, возвращаемое sem_getvalue(), либо равно нулю, либо отрицательное число, абсолютная величина которого равна количеству потоков управления, ожидающих данный семафор.
Диаграмма взаимодействий 1

Диаграмма взаимодействий 2
Диаграмма взаимодействий 3

Отличия в разработке спецификаций для систем с отложенными реакциями
№ | Системы без отложенных реакций | Системы с отложенными реакциями |
1 | Описания типов данных параметров спецификационных функций и возвращаемых результатов | |
2 | Инварианты типов данных параметров спецификационных функций и возвращаемых результатов | |
3 | Описания типов данных для состояния системы | |
4 | Инварианты типов данных состояния системы | |
5 | Декларации переменных состояния | |
6 | Инварианты переменных состояния | |
7 | Определение спецификационных функций | |
8 | Описания доступа к параметрам спецификационной функции и переменным состояния | |
9 | Описание предусловий спецификационных функций | |
10 | Описание критериев покрытия спецификационных функций | |
11 | Описание постусловий спецификационных функций | Описание постусловий спецификационных функций и реакций |
Отличия в разработке медиаторов для систем с отложенными реакциями
№ | Системы без отложенных реакций | Системы с отложенными реакциями |
1 | Медиатор спецификационной функции должен преобразовывать входные и изменяемые параметры в реализационные типы, вызывать целевую функцию, преобразовывать результаты (выходные и изменяемые параметры и возвращаемый результат) в типы спецификации и синхронизировать модельное состояние с состоянием целевой системы. | Медиатор спецификационной функции должен преобразовывать входные и изменяемые параметры в реализационные типы, осуществить тестовое воздействие на целевую систему, преобразовывать непосредственную реакцию на стимул в типы спецификации и синхронизировать модельное состояние с состоянием целевой системы. |
2 | Медиаторы отложенных реакций | |
3 |
Отличия в разработке сценариев для систем с отложенными реакциями
№ | Системы без отложенных реакций | Системы с отложенными
|
1 | Функция инициализации разбирает параметры сценария, устанавливает медиаторы для всех спецификационных функций, участвующих в данном сценарии, и инициализирует модельное состояние системы. | |
2 | Функция завершения освобождает ресурсы сценария и модельного состояния. | |
3 | Функция построения состояния сценария возвращает состояние сценария, являющееся значением спецификационного типа. | |
4 | Функция сохранения модельного состояния | |
5 | Функция | |
6 | Функция | |
7 | Сценарные функции описывают набор сценариев вызова спецификационных функций с различными параметрами. | |
8 | Определяется сценарий тестирования, в котором инициализируется поле, содержащее массив сценарных функций, и, возможно, поля, соответствующие функциям инициализации сценария, построения состояния сценария и завершения сценария. |
Оценка курса

Трансфертный лист курса.
Мне понравилось: | Хотелось бы посоветовать: |
Мне будет легко: | У меня будут проблемы: |


