Читаем Программирование. Принципы и практика использования C++ Исправленное издание полностью

  Color fcolor;         // цвет заполнения

  Shape(const Shape&);  // предотвращает копирование

  Shape& operator=(const Shape&);

};

Как приступить к тестированию этого класса? Сначала рассмотрим, чем класс Shape отличается от функции binary_search с точки зрения тестирования.

• Класс Shape имеет несколько функций.

• Состояние объекта класса Shape может изменяться (мы можем добавлять точки, изменять цвет и т.д.), т.е. одна функция может влиять на другую.

• Класс Shape имеет виртуальные функции. Другими словами, поведение объекта класса Shape зависит от того, какой производный класс был создан на его основе (если такой класс существует).

• Класс Shape не является алгоритмом.

• Изменение объекта класса Shape может влиять на содержимое экрана.

  Последний момент особенно неприятный. По существу, это значит, что мы должны посадить перед компьютером человека, который будет смотреть, правильно ли ведет себя объект класса Shape. Это не соответствует принципам систематичного, воспроизводимого и доступного тестирования. Как указывалось в разделе 26.3.4.1, мы часто прибегаем к разным уловкам, чтобы избежать этого. Однако пока будем предполагать, что существует наблюдатель, который замечает отклонения изображения от требуемого образца.

  Отметим важную деталь: пользователь может добавлять точки, но не может их удалять. Пользователь или функции класса Shape могут считывать точки, но не могут их изменять. С точки зрения тестирования все, что не вносит изменений (или, по крайней мере, не должно вносить), облегчает работу.

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

Ранее мы уже отметили, что объект класса Shape имеет состояние (значение), определенное четырьмя данными-членами.

vector points;

Color lcolor; // цвет линий и символов

Line_style ls;

Color fcolor; // цвет заполнения

Все, что мы можем сделать с объектом класса Shape, — внести в него изменения и посмотреть, что произойдет. К счастью, изменить данные-члены можно только с помощью интерфейса, определенного функциями-членами.

Простейшим объектом класса Shape является объект класса Line, поэтому начнем с создания одного такого объекта и внесем все возможные изменения (используя самый наивный стиль тестирования).

Line ln(Point(10,10), Point(100, 100));

ln.draw();  // смотрим, что произошло

// проверка точек:

if (ln.number_of_points() != 2)

  cerr << "Неправильное количество точек ";

if (ln.point(0)!=Point(10,10)) cerr << "Неправильная точка 1";

if (ln.point(1)!=Point(100,100)) cerr << "Неправильная точка 2";

for (int i=0; i<10; ++i) { // смотрим на перемещения объекта

  ln.move(i+5,i+5);

  ln.draw();

}

for (int i=0; i<10; ++i) { // проверяем, возвращается ли объект

                           // в исходное положение

  ln.move(i–5,i–5);

  ln.draw();

}

if (point(0)!=Point(10,10))

  cerr << "Неправильная точка 1 после перемещения";

if (point(1)!=Point(100,100))

  cerr << "Неправильная точка 2 после перемещения";

for (int i = 0; i<100; ++i) { // смотрим, правильно ли изменяются

                              // цвета

  ln.set_color(Color(i*100));

  if (ln.color() != Color(i*100))

    cerr << "Неправильное значение set_color";

  ln.draw();

}

for (int i = 0; i<100; ++i) { // смотрим, правильно ли изменяется

                              // стиль

  ln.set_style(Line_style(i*5));

  if (ln.style() != Line_style(i*5))

  cerr << "Неправильное значение set_style";

  ln.draw();

}

Перейти на страницу:

Похожие книги

Programming with POSIX® Threads
Programming with POSIX® Threads

With this practical book, you will attain a solid understanding of threads and will discover how to put this powerful mode of programming to work in real-world applications. The primary advantage of threaded programming is that it enables your applications to accomplish more than one task at the same time by using the number-crunching power of multiprocessor parallelism and by automatically exploiting I/O concurrency in your code, even on a single processor machine. The result: applications that are faster, more responsive to users, and often easier to maintain. Threaded programming is particularly well suited to network programming where it helps alleviate the bottleneck of slow network I/O. This book offers an in-depth description of the IEEE operating system interface standard, POSIX (Portable Operating System Interface) threads, commonly called Pthreads. Written for experienced C programmers, but assuming no previous knowledge of threads, the book explains basic concepts such as asynchronous programming, the lifecycle of a thread, and synchronization. You then move to more advanced topics such as attributes objects, thread-specific data, and realtime scheduling. An entire chapter is devoted to "real code," with a look at barriers, read/write locks, the work queue manager, and how to utilize existing libraries. In addition, the book tackles one of the thorniest problems faced by thread programmers-debugging-with valuable suggestions on how to avoid code errors and performance problems from the outset. Numerous annotated examples are used to illustrate real-world concepts. A Pthreads mini-reference and a look at future standardization are also included.

David Butenhof

Программирование, программы, базы данных