Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка ПИ_ИКТ Программирование по С++ (1 семестр) _Хотов.docx
Скачиваний:
1
Добавлен:
01.07.2025
Размер:
5.83 Mб
Скачать

Упражнения

  1. Приведите примеры ошибок, которые выявляются не сразу, а после вы­полнения нескольких следующих операторов.

  2. Приведите примеры ошибок, которые не может обнаружить компилятор.

  3. Вам нужно найти ошибку в программе, вычисляющей корни квадратно­го уравнения по обычной школьной формуле. Расставьте в исходном ко­де отладочную печать.

  4. Выясните, каково наибольшее и наименьшее целое число на вашем компьютере. Что происходит при выходе за эти значения?

  5. Найдите наибольшее по абсолютной величине действительное число, которое ваш компьютер воспринимает как ноль ("машинный ноль") и ответьте на вопрос, почему сравнение с нулем действительных чисел, вроде if (х == 0.0), часто приводит к ошибке.

  6. Проверьте, при всех ли значениях х выполняется тождество cos2(jc) + sin2 (jc) = 1 на вашем компьютере.

  7. Найдите с максимальной возможной на вашем компьютере точностью две суммы, отличающиеся порядком следования слагаемых:

5[ = 1 + —+ — + ...+—-—н

2 3 999999 1000000

и

1 1 1 ,

S2 = + + ... + - + 1.

1000000 999999 2

Посмотрите, совпадут ли значения ij и 02-

Тестирование

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

Классическое определение тестирования, данное Гленфордом Дж. Майер- сом (Glenford J. Myers), звучит так: "Тестирование — процесс выполнения программы с намерением найти ошибки". Новейшие методы тестирования не только запускают программу с различными исходными и промежуточ­ными данными, но и проверяют ее исходный текст. Поэтому определение Майерса уже устарело и под тестированием сейчас понимаются любые дей­ствия, направленные на поиск ошибок в программе.

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

Тестирование не следует отождествлять с отладкой, хотя они тесно связаны. Задача тестирования — выявить наличие дефектов в программе, а задача отладки — отыскать их местоположение и устранить ошибки. Сначала с помощью тестирования надо найти ошибки, а потом, во время отладки, устранить их. Иногда тестирование и отладка выполняются одним специа­листом в одном процессе, чаще их осуществляют разные люди.

Unit-тестирование

По сути дела, тестированием своего участка программы занимается каждый разработчик программного обеспечения. Написав какой-либо класс, про­цедуру или несколько процедур, программист обязательно проверяет их работу на характерных для этого кода наборах данных. Появившаяся недавно методика unit-тестирования возводит эту привычку в абсолютное правило. Эта методика предписывает проводить тестирование после написания каждой процедуры или класса. Более того, unit-тестирование обязывает писать тесты еще до создания исходного кода программы!

Допустим, мы решили написать класс комплексных чисел complex. По ме­тодике unit-тестирования мы начинаем с того, что пишем пустой класс complex и вместе с ним сразу же пишем класс Testcomplex, который будет впоследствии содержать тесты.

class Complex{};

class TestComplex{

Complex z; public:

TestComplex(Complex z){ this.z = z;

}

void runTest(){ }

} ;

Весь этот код сразу компилируется, чтобы убедиться в правильности напи­санной конструкции. Затем начинаем разработку класса complex. В процес­се разработки каждый создаваемый метод класса complex записывается еще и в тестовый класс Testcomplex, например, следующим образом:

#include <iostream>

class Complex{

double re, im; public:

Complex(double a = 0.0, double b = 0.0){ re = a; im = b;

}

double mod(){

return sqrt(re * re + im * im) ;

}

} ;

class TestComplex{

Complex z; public:

TestComplex(Complex z) { this.z = z;

}

void runTest(double result){

cout « testMod(result) « endl;

}

bool testMod(double result){ return z.modO == result;

}

> ;

void main(){

Complex zl(), z2(0.0, 1.0), z3(3.0, -4.0);

TestComplex tl(zl), t2(z2), t3(z3); tl.runTest(0.0); t2.runTest(1.0); t2.runTest(5.0);

}

После компиляции и отладки этого кода сразу же начинается тестирование. Только после того, как все тесты выполнены успешно, продолжается созда­ние класса.

Такая методика программирования получила название программирования, управляемого тестами (TDP, test-driven programming). Она вошла обязатель­ной составной частью в быстро получившую популярность среди разработ­чиков свободного программного обеспечения методику экстремального про­граммирования ХР (extreme programming). Unit-тестирование первоначально возникло в технологии Java. Не удивительно, что и наибольшее развитие получил свободно распространяемый программный продукт JUnit, автома­тизирующий unit-тестирование Java-ioiaccoB. Для разработчиков, пишущих программы на языке С++, по аналогии с этим программным продуктом, создана библиотека классов, названная CppUnit.

Сейчас в распоряжении программистов есть множество программных продук­тов, облегчающих unit-тестирование. Более того, есть продукты, генерирующие наборы тестов. Например, фирмой Parasoft Corporation создан и распространя­ется программный продукт JTest, подготавливающий тесты для JUnit.