Проверка входных данных подпрограмм и тестирование — различия между версиями

Материал из Вики ИТ мехмата ЮФУ
Перейти к: навигация, поиск
(Новая страница: «Категория:Основы программирования = Введение = Рассмотрим задачу: <br /> <code>Описать про…»)
 
Строка 19: Строка 19:
 
</source>
 
</source>
  
= Тестирование подпрограммы =
+
= Тестирование подпрограммы с помощью Assert =
  
 +
Прелесть алгоритма, заключенного в подпрограмме, состоит в том, что его легко вызывать многократно с разными входными значениями. Это позволяет нам перейти к более надежному способу тестирования. Теперь мы можем «зашить» в основную программу вызовы подпрограммы с необходимыми тестовыми значениями.
  
 +
=== Пример ===
 +
Итак, пусть процедура <code>Mean</code> написана. У неё два входных и два выходных параметра. Значит '''каждый тестовый пример''' должен проверять, что при заданных значениях <code>X</code> и <code>Y</code> ''оба выходных параметра имеют ожидаемые значения''. То есть:
 +
# нужно задать значения входных параметров (<code>X, Y</code>);
 +
# вызвать процедуру <code>Mean</code>, передав ей эти входные значения;
 +
# проверить, что значения выходных параметров (<code>AMean, GMean</code>) совпадают с ожидаемыми.
 +
Попробуем это запрограммировать. Начнём с простейшего примера: для <code>X, Y | X = Y</code> дожны быть получены значения <code>AMean = X, GMean = X</code>.
 +
<source lang="Pascal">
 +
var x, y: real;
 +
var am, gm: real;
 +
 +
// (1) задаём значения входных параметров
 +
x := 2;
 +
y := x;
 +
// (2) вызываем процедуру
 +
Mean(x, y, am, gm);
 +
// (3) проверяем корректность выходных значений
 +
</source>
 +
 +
<u>Вопрос</u>: как будем выполнять проверку (шаг 3)?  Вспомним, что при решении задач с рядами мы уже выполняли проверку правильности найденного значения с помощью оператора <code>Assert</code>. В качестве параметра нужно передать логическое выражение, значение которого истинно, если решение верно. Нам нужно проверить, что <code>AMean = X, GMean = X</code>. Может быть так?
 +
<source lang="Pascal">
 +
// (3) проверяем корректность выходных значений
 +
Assert((am = x) and (gm = x));
 +
</source>
 +
Математически это верно, но ''вещественные'' числа так не сравнивают на равенство. А у нас как раз вещественные числа. Исправим. Введем некоторую константу <code>Eps</code> (равную, например, значению 0.00000001), тогда проверка будет выглядеть так:
 +
<source lang="Pascal">
 +
// (3) проверяем корректность выходных значений
 +
Assert((Abs(am - x) < Eps) and (Abs(gm - x) < Eps));
 +
</source>
 +
 +
Сравнивать вещественные значения нам понадобится не один раз (по крайней мере нужно написать ещё несколько тестов). Это отличный претендент на подпрограмму. Для двух данных вещественных чисел нам нужно знать, равны они или нет. Значит подпрограмма должны иметь два входных вещественных параметра и один выходной — логического типа (нам нужен только ответ да/нет). Раз выходной
  
 
= Ссылки =
 
= Ссылки =
 
* [[Процедуры и функции, формальные и фактические параметры]]
 
* [[Процедуры и функции, формальные и фактические параметры]]

Версия 21:07, 21 октября 2013


Введение

Рассмотрим задачу:
Описать процедуру Mean(X, Y, AMean, GMean), вычисляющую среднее арифметическое AMean = (X+Y)/2 и среднее геометрическое GMean = (X·Y)1/2 двух положительных чисел X и Y (X и Y — входные, AMean и GMean — выходные параметры вещественного типа).

Проверка входных данных: Assert

Обратите внимание, что положительность параметров X и Y нужна для вычисления среднего геометрического, которое происходит внутри процедуры Mean. Никто не гарантирует, что на вход процедуре будут передаваться только корректные входные данные, но правильная работа самой процедуры — забота разработчика этой процедуры. Он должен «обезопасить» себя от неверных входных данных, поэтому их проверка должна находиться именно внутри процедуры Mean.

Мы знаем, как проверять входные данные: можно использовать оператор Assert. Рекомендуется использовать оператор Assert для каждого параметра отдельно. То есть в данном примере должно быть два оператора:

Assert(x > 0);
Assert(y > 0);

а не

Assert((x > 0) and (y > 0));

Тестирование подпрограммы с помощью Assert

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

Пример

Итак, пусть процедура Mean написана. У неё два входных и два выходных параметра. Значит каждый тестовый пример должен проверять, что при заданных значениях X и Y оба выходных параметра имеют ожидаемые значения. То есть:

  1. нужно задать значения входных параметров (X, Y);
  2. вызвать процедуру Mean, передав ей эти входные значения;
  3. проверить, что значения выходных параметров (AMean, GMean) совпадают с ожидаемыми.

Попробуем это запрограммировать. Начнём с простейшего примера: для X, Y | X = Y дожны быть получены значения AMean = X, GMean = X.

var x, y: real;
var am, gm: real;

// (1) задаём значения входных параметров
x := 2;
y := x;
// (2) вызываем процедуру
Mean(x, y, am, gm);
// (3) проверяем корректность выходных значений

Вопрос: как будем выполнять проверку (шаг 3)? Вспомним, что при решении задач с рядами мы уже выполняли проверку правильности найденного значения с помощью оператора Assert. В качестве параметра нужно передать логическое выражение, значение которого истинно, если решение верно. Нам нужно проверить, что AMean = X, GMean = X. Может быть так?

// (3) проверяем корректность выходных значений
Assert((am = x) and (gm = x));

Математически это верно, но вещественные числа так не сравнивают на равенство. А у нас как раз вещественные числа. Исправим. Введем некоторую константу Eps (равную, например, значению 0.00000001), тогда проверка будет выглядеть так:

// (3) проверяем корректность выходных значений
Assert((Abs(am - x) < Eps) and (Abs(gm - x) < Eps));

Сравнивать вещественные значения нам понадобится не один раз (по крайней мере нужно написать ещё несколько тестов). Это отличный претендент на подпрограмму. Для двух данных вещественных чисел нам нужно знать, равны они или нет. Значит подпрограмма должны иметь два входных вещественных параметра и один выходной — логического типа (нам нужен только ответ да/нет). Раз выходной

Ссылки