Читать в оригинале

<< Предыдущая Оглавление Следующая >>


2.2. Организация тестирования

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

Оракул дает заключение о факте появления неправильной пары (х,ув) и ничего не говорит о том, каким образом она была вычислена или каков правильный алгоритм - он только сравнивает вычисленные и желаемые результаты. Оракулом может быть даже Заказчик или Программист, производящий соответствующие вычисления в уме, поскольку Оракулу нужен какой-либо альтернативный способ получения функции (X,Y) для вычисления эталонных значений Y.

В процессе тестирования Оракул последовательно получает элементы множества (X,Y) и соответствующие им результаты вычислений (Х^в) для идентификации фактов несовпадений (test incident).

При выявлении (x,yB)g(X,Y) запускается процедура исправления ошибки, которая заключается во внимательном анализе (просмотре) протокола промежуточных вычислений, приведших к (х,ув), с помощью следующих методов:

- «Выполнение программы в уме» (deskchecking).

- Вставка операторов протоколирования (печати) промежуточных результатов (logging).

- Пошаговое выполнение программы (single-step running).

- Выполнение с заказанными остановками (breakpoints), анализом трасс (traces) или состояний памяти - дампов (dump).

- реверсивное (обратное) выполнение (reversible execution)

 

2.2.1. Пример сравнения словесного описания пункта спецификации с результатом выполнения фрагмента кода

Пункт спецификации: «Метод Power должен принимать входные параметры: x - целое число, возводимое в степень, и n - неотрицательный порядок степени. Метод должен возвращать вычисленное значение xn». Выполняем метод со следующими параметрами: Power(2,2)

Проверка результата выполнения возможна, когда результат вычисления заранее известен - 4. Если результат выполнения 22 = 4, то он соответствует спецификации.

2.2.2. Пример вставки операторов протоколирования промежуточных результатов

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

// Метод вычисляет неотрицательную степень n числа x
static public double Power(double x, int n) {
         double z=1;
         for (int i=1;n>=i;i++) {
            z = z*x;
            Console.WriteLine("i = {0} z = {1}",i,z); \\ тестовый вывод
         }
         return z;
}

2.2.3. Пример пошагового выполнения программы

При пошаговом выполнении программы код выполняется строчка за строчкой. В среде Microsoft Visual Studio возможны следующие команды пошагового выполнения:

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

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

Step Out - предназначена для выхода из функции в вызывающую функцию. Эта команда продолжит выполнение функции и остановит выполнение на первой строчке после вызываемой функции.

Пошаговое выполнение до сих пор является мощным методом автономного тестирования и отладки небольших программ.

2.2.4. Пример выполнения программы с заказанными контрольными точками и анализом трасс и дампов

Контрольная точка (breakpoint) - точка программы, которая при ее достижении посылает отладчику сигнал. По этому сигналу либо временно приостанавливается выполнение отлаживаемой программы, либо запускается программа «агент», фиксирующая состояние заранее определенных переменных или областей в данный момент.

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

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

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

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

Рис. 7. Управляющий граф программы

Трасса, проходящая через вершины 0-1-3-4-5, зафиксирована в таблице (Таблица 1). Строки таблицы отображают вершины управляющего графа программы, или breakpoints, в которых фиксировались текущие значения заказанных пользователем переменных.

Таблица 1

№ верши-

Значение пе

Значение пе

Значение пе-

Значение пере

ны-

ременной x

ременной z

ременной n

менной i

оператора

 

 

 

 

0

3

1

2

не зафиксировано

1

3

1

2

не зафиксировано

3

3

1

2

1

4

3

3

2

2

5

3

3

2

не зафиксировано

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

 

2.2.5. Пример обратного выполнения программы

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

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

// Метод вычисляет неотрицательную степень n числа x
static public double PowerNonNeg(double x, int n) {
         double z=1;
         Console.WriteLine("x={0} z={1} n={2}",x,z,n);
         if (n>0) {
            Console.WriteLine("x={0} z={1} n={2}",x,z,n);
            for (int i=1;n>=i;i++) {
                        z = z*x;
                        Console.WriteLine("x={0} z={1} n={2} i={3}",x,z,n,i);
            }
         }
         else Console.WriteLine("Ошибка ! Степень числа n должна быть больше 0.");
         return z;
}

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

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

Тестирование заканчивается, когда выполнилось или «прошло» (pass) успешно достаточное количество тестов в соответствии с выбранным критерием тестирования.

2.2.6. Сквозной пример тестирования

Возьмем несколько отличающуюся от предыдущей (п. 2.2.5.) программу:

// Метод вычисляет степень n числа x static
public double Power(int x, int n)
{
         int z=1;
         for (int i=1;n>=i;i++) {
            z = z*x;
         }
         return z;
}
[STAThread]
static void Main(string[] args) {
         int x;
         int n;
         try {
            Console.WriteLine("Введите число x:");
            x=Convert.ToInt32(Console.ReadLine());
            if ((x>=0) & (x<=999)) {
            Console.WriteLine("Введите степень числа х - число n:");
            n=Convert.ToInt32(Console.ReadLine());
                        if ((n>=1) & (n<=100)) {
                                   Console.WriteLine("Число х в степени n равно {0}", Power(x,n));
                                   Console.ReadLine();
                        }
                        else {
                                   Console.WriteLine("Ошибка : n должно быть из отрезка [1..100]");
                                   Console.ReadLine();
                        }
            }
            else {
               Console.WriteLine("Ошибка : x должно быть из отрезка [0..999]");
               Console.ReadLine();
            }
         }  \\ try-блок
         catch (Exception e) {
            Console.WriteLine("Ошибка : вводите числа.");
            Console.ReadLine();
         }
}

Для приведенной программы, вычисляющей степень числа, воспроизведем последовательность действий, необходимых для тестирования.

Спецификация программы

На вход программа принимает два параметра: x - число, n - степень. Результат вычисления выводится на консоль.

Значения числа и степени должны быть целыми.

Значения числа, возводимого в степень, должны лежать в диапазоне - [0..999].

Значения степени должны лежать в диапазоне - [1..100].

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

Разработка тестов

Определим области эквивалентности входных параметров. Для x, числа, возводимого в степень, определим классы возможных значений:

1) x < 0    (ошибочное)
2) x > 999 (ошибочное)
3) x – не число (ошибочное)
4) 0 <=
x <= 999 (корректное)

Для n - степени числа:

5) n < 1 (ошибочное)
6) n > 100 (ошибочное)
7) n – не число (ошибочное)
8) 1 <=
n <= 100 (корректное)

Анализ тестовых случаев

Входные значения: (x = 2, n = 3) (покрывают классы 4, 8). Ожидаемый результат: Число х в степени n равно 8.
Входные значения: {(x = -1, n = 2),(x = 1000, n = 5 )} (покрывают классы 1, 2).
Ожидаемый результат: Ошибка : x должно быть из отрезка [0..999].
Входные значения: {(x = 100, n = 0),(x = 100, n = 200)} (покрывают классы 5, 6).
Ожидаемый результат: Ошибка : n должно быть из отрезка [1..100].
Входные значения: (x = ADS n = ASD) (покрывают классы 3, 7).
Ожидаемый результат: Ошибка : вводите числа.

Проверка на граничные значения:

1.1. Входные значения: (x = 999 n = 1).
Ожидаемый результат: Число х в степени n равно 999.
1.2. Входные значения: (x = 0 n = 100).
Ожидаемый результат: Число х в степени n равно 0.

Выполнение тестовых случаев

Запустим программу с заданными значениями аргументов.

Оценка результатов выполнения программы на тестах

В процессе тестирования Оракул последовательно получает элементы множества (X,Y) и соответствующие им результаты вычислений Yв. В процессе тестирования производится оценка результатов выполнения путем сравнения получаемого результата с ожидаемым.

 



<< Предыдущая Оглавление Следующая >>