План:
Самостоятелно тестване на функции
Подбор на тестови примери
Оценка на резултатите от тестването
Макрос assert
Трасиране на програмата
** Самостоятелно тестване на функции.
* Данните, с които ще се тества функцията, се получават по 3
начина:
-- от входния поток (от клавиатура или от текстов
файл с пренасочване на входния поток);
-- като стойности, получени от цикъл;
-- случайни числа.
* Примери за тестване на функцията squareroot за намиране на
квадратен корен по метода на Херон.
Първи пример - данните идват от входния поток:
// sqrtest1.cpp
#include <iostream>
#include <cmath>
using namespace std;
/**
Tests whether two floating-point numbers are
approximately equal.
@param x a floating-point number
@param y another floating-point number
@return true if x and y are approximately equal
*/
bool approx_equal(double x, double y)
{ const double EPSILON = 1E-14;
if (x == 0) return fabs(y) <= EPSILON;
if (y == 0) return fabs(x) <= EPSILON;
return fabs(x - y) / max(fabs(x), fabs(y)) <= EPSILON;
}
/* Function to be tested */
/**
Computes the square root using Heron's formula
@param a an integer >= 0
@return the square root of a
*/
double squareroot(double a)
{ if (a == 0) return 0;
double xnew = a;
double xold;
do
{ xold = xnew;
xnew = (xold + a / xold) / 2;
}
while (!approx_equal(xnew, xold));
return xnew;
}
/* Test harness */
int main()
{ double x;
while (cin >> x)
{ double y = squareroot(x);
cout << "squareroot of " << x << " = " << y << "\n";
}
return 0;
}
25 squareroot of 25 = 5 3 squareroot of 3 = 1.73205 q |
Втори пример - входните стойности на функцията се генерират от цикъл.
// sqrtest2.cpp
/* Test harness */
int main()
{ double x;
for (x = 0; x <= 10; x = x + 0.5)
{ double y = squareroot(x);
cout << "squareroot of " << x << " = " << y << "\n";
}
return 0;
}
squareroot of 0 = 0 squareroot of 0.5 = 0.707107 squareroot of 1 = 1 squareroot of 1.5 = 1.22474 squareroot of 2 = 1.41421 |
Трети пример - входните стойности
се получават от генератор за случайни числа.
// sqrtest3.cpp
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <ctime>
using namespace std;
/**
Sets the seed of the random number generator.
*/
void rand_seed()
{ int seed = static_cast<int>(time(0));
srand(seed);
}
/**
Compute a random floating point number in a range
@param a the bottom of the range
@param b the top of the range
@return a random floating point number x,
a <= x and x <= b
*/
double rand_double(double a, double b)
{ return a + (b - a) * rand() * (1.0 / RAND_MAX);
}
/**
Tests whether two floating-point numbers are
approximately equal.
@param x a floating-point number
@param y another floating-point number
@return true if x and y are approximately equal
*/
bool approx_equal(double x, double y)
{ const double EPSILON = 1E-14;
if (x == 0) return fabs(y) <= EPSILON;
if (y == 0) return fabs(x) <= EPSILON;
return fabs(x - y) / max(fabs(x), fabs(y)) <= EPSILON;
}
/* Function to be tested */
/**
Computes the square root using Heron's formula
@param a an integer >= 0
@return the square root of a
*/
double squareroot(double a)
{ if (a == 0) return 0;
double xnew = a;
double xold;
do
{ xold = xnew;
xnew = (xold + a / xold) / 2;
}
while (!approx_equal(xnew, xold));
return xnew;
}
/* Test harness */
int main()
{ rand_seed();
int i;
for (i = 1; i <= 100; i++)
{ double x = rand_double(0, 1E6);
double y = squareroot(x);
cout << "squareroot of " << x << " = " << y << "\n";
}
return 0;
}
squareroot of 185949 =
431.218 squareroot of 680715 = 825.055 squareroot of 17883.8 = 133.73 squareroot of 238868 = 488.742 |
** Подбор на
тестови примери.
1. Докато се пише програмата, трябва да имаме прост тестов пример,
на който знаем решението.
2. Програмата се проверява с други тестови примери, също с
известни решения - позитивни тестове.
3. Включват се и граничните случаи.
- За функцията squareroot това са 0,
големи числа (напр. 1Е20)
и числа, близки до 0 (напр. 1е-20).
Целта е да се определят границите на параметрите, за които
функцията работи вярно.
4. Функцията се проверява с негативни тестови примери - некоректни
входни данни.
- Такива за squareroot са отрицателни
стойности на параметъра.
Използване на файл за запазване на тестовия вход и изпълнение с
пренасочване на входния и изходния потоци.
>sqrtest1 < test.in > test.out
// sqrtest4.cpp* За оракул можем да използваме стандартната аритметична функция pow(x,0.5)или функцията sqrt(x).
/* Test harness */
int main()
{ int i;
for (i = 1; i <= 100; i++)
{ double x = rand_double(0, 1E6);
double y = squareroot(x);
if (!approx_equal(y * y, x))
cout << "Test failed. ";
else
cout << "Test passed. ";
cout << "squareroot of " << x << " = " << y << "\n";
}
return 0;
}
void raise_salary(Employee& e, double by)Ако условието не е изпълнено, програмата завършва с полезно съобщение за грешка и показва номера на реда в текста на програмата.
{
assert(e.get_salary() >= 0 );
assert(by >= -100);
double new_salary = e.get_salary() * (1 + by / 100);
e.set_salary(new_salary);
}
assertion failed in file finclac.cpp line 61: by >= -100Това е сигнал, че нещо се е объркало другаде и че програмата се нуждае от по-нататъшно тестване.
string int_name(int n)[trace.cpp]
{ cout << "Entering digit_name. n = " << n << "\n";
...
cout << "Exiting digit name. Return value = "
<< s << "\n";
return s;
}