Тестовое окружение для программного кода на структурных языках программирования состоит из двух компонентов – драйвера, который обеспечивает запуск и выполнение тестируемого модуля и заглушек, которые моделируют функции, вызываемые из данного модуля. Разработка тестового драйвера представляет собой отдельную задачу тестирования, сам драйвер должен быть протестирован, дабы исключить неверное тестирование. Драйвер и заглушки могут иметь различные уровни сложности, требуемый уровень сложности выбирается в зависимости от сложности тестируемого модуля и уровня тестирования. Так, драйвер может выполнять следующие функции:
1. Вызов тестируемого модуля
2. 1 + передача в тестируемый модуль входных значений и прием результатов
3. 2 + вывод выходных значений
4. 3 + протоколирование процесса тестирования и ключевых точек программы
Заглушки могут выполнять следующие функции:
1. Не производить никаких действий (такие заглушки нужны для корректной сборки тестируемого модуля и
|
|
2. Выводить сообщения о том, что заглушка была вызвана
3. 1 + выводить сообщения со значениями параметров, переданных в функцию
4. 2 + возвращать значение, заранее заданное во входных параметрах теста
5. 3 + выводить значение, заранее заданное во входных параметрах теста
6. 3 + принимать от тестируемого ПО значения и передавать их в драйвер [10].
Для тестирования программного кода, написанного на процедурном языке программирования используются драйверы, представляющие собой программу с точкой входа (например, функцией main()), функциями запуска тестируемого модуля и функциями сбора результатов. Обычно драйвер имеет как минимум одну функцию – точку входа, которой передается управление при его вызове.
Функции-заглушки могут помещаться в тот же файл исходного кода, что и основной текст драйвера. Имена и параметры заглушек должны совпадать с именами и параметрами «заглушаемых» функций реальной системы. Это требование важно не столько с точки зрения корректной сборки системы (при сборке тестового драйвера и тестируемого ПО может использоваться приведение типов), сколько для того, чтобы максимально точно моделировать поведение реальной системы по передаче данных. Так, например, если в реальной системе присутствует функция вычисления квадратного корня
double sqrt(double value);
то с точки зрения сборки системы вместо типа double может использоваться и float, но снижение точности может вызвать непредсказуемые результаты в тестируемом модуле.
В качестве примера драйвера и заглушек рассмотрим реализацию стека на языке C, причем значения, помещаемые в стек, хранятся не в оперативной памяти, а помещаются в ППЗУ при помощи отдельного модуля, содержащего две функции – записи данных в ППЗУ по адресу и чтения данных по адресу.
|
|
Формат этих функций следующий:
void NV_Read(char *destination, long length, long offset);
void NV_Write(char *source, long length, long offset);
Здесь destination – адрес области памяти, в которую записывается значение, считанное из ППЗУ, source – адрес области памяти, из которой записывается значение в ППЗУ, length – длина записываемой области памяти, offset – смещение относительно начального адреса ППЗУ.
Реализация стека с использованием этих функций выглядит следующим образом:
long currentOffset;
void initStack()
{
currentOffset=0;
}
void push(int value)
{
NV_Write((int*)&value,sizeof(int),currentOffset);
currentOffset+=sizeof(int);
}
int pop()
{
int value;
if (currentOffset>0)
{
NV_Read((int*)&value,sizeof(int),currentOffset;
currentOffset-=sizeof(int);
}
}
При выполнении этого кода на реальной системе происходит запись в ППЗУ, однако, если мы хотим протестировать только реализацию стека, изолировав ее от реализации модуля работы с ППЗУ, необходимо использовать заглушки вместо реальных функций. Для имитации работы ППЗУ можно выделить достаточно большой участок оперативной памяти, в которой и будет производиться запись данных, получаемых заглушкой.
Заглушки для функций могут выглядеть следующим образом:
char nvrom[1024];
void NV_Read(char *destination, long length, long offset)
{
printf(“NV_Read called\n”);
memcpy(destination, nvrom+offset, length);
}
void NV_Write(char *source, long length, long offset);
{
printf(“NV_Write called\n”);
memcpy(nvrom+offset, source, length);
}
Каждая из заглушек выводит трассировочное сообщение и перемещает переданное значение в память, эмулирующую ППЗУ (функция NV_Write) или возвращает по ссылке значение, хранящееся в памяти, эмулирующей ППЗУ (функция NV_Read).
Схема взаимодействия тестируемого ПО (функций работы со стеком) с реальным окружением (основной частью системы и модулем работы с ППЗУ) и тестовым окружением (драйвером и заглушками функций работы с ППЗУ) показана на Рис. 10 и Рис. 11.
Рис. 10 Схема взаимодействия частей реальной системы
Рис. 11 Схема взаимодействия тестового окружения и тестируемого ПО