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

Чем более сложными являются варианты использования инструкций if, тем вероятнее становятся ошибки. Тестировщики анализируют такие коды и стараются не пропустить ни одной ветви. Для функции do_branch1() набор тестов очевиден.

do_branch1(–1,–1);

do_branch1(–1, 1);

do_branch1(1,–1);

do_branch1(1,1);

do_branch1(–1,0);

do_branch1(0,–1);

do_branch1(1,0);

do_branch1(0,1);

do_branch1(0,0);

По существу, это наивный подход “перебора всех альтернатив”, которой мы применили, заметив, что функция do_branch1() сравнивает значения с нулем с помощью операторов < и >. Для того чтобы выявить неправильные действия при положительных значениях переменной x, мы должны объединить вызовы функции с желаемыми результатами.

Обработка инструкций switch аналогична обработке инструкций if.

void do_branch1(int x, int y)  // плохая функция

 // неправильное использование инструкции switch

{

  if (y<0 && y<=3)

  switch (x) {

  case 1:

    cout << "Один\n";

    break;

  case 2:

    cout << "Два\n";

    case 3:

  cout << "Три\n";

  }

}

Здесь сделаны четыре классические ошибки.

• Мы проверяем значения неправильной переменной (y, а не x).

• Мы забыли об инструкции break, что приводит к неправильному действию при x==2.

• Мы забыли о разделе default (считая, что он предусмотрен инструкцией if).

• Мы написали y<0, хотя имели в виду 0.

  Как тестировщики мы всегда ищем непредвиденные варианты. Пожалуйста, помните, что просто устранить проблему недостаточно. Она может возникнуть снова, когда мы ее не ожидаем. Мы хотим писать тесты, которые систематически выявляют ошибки. Если мы просто исправим этот простой код, то можем либо неправильно решить задачу, либо внести новую ошибку. Цель анализа кода заключается не только в выявлении ошибок (хотя это всегда полезно), а в разработке удобного набора тестов, позволяющих выявить все ошибки (или, говоря более реалистично, большинство ошибок).

  Подчеркнем, что циклы всегда содержат неявные инструкции if: они выполняют проверку условия выхода из цикла. Следовательно, циклы также являются инструкциями ветвления. Когда мы анализируем программы, содержащие инструкции ветвления, первым возникает следующий вопрос: все ли ветви мы проверили? Удивительно, но в реальной программе это не всегда возможно (потому что в реальном коде функции вызываются так, как удобно другим функциям, и не всегда любыми способами). Затем возникает следующий вопрос: какую часть кода мы проверили? И в лучшем случае мы можем ответить: “Мы проверили большинство ветвей”, объясняя, почему мы не смогли проверить остальные ветви. В идеале при тестировании мы должны проверить 100% кода.

<p id="AutBody_Root522"><strong>26.3.4. Системные тесты</strong></p>

  Тестирование любой более или менее значимой системы требует опыта. Например, тестирование компьютеров, управляющих телефонной системой, проводится в специально оборудованных комнатах с полками, заполненными компьютерами, имитирующими трафик десятков тысяч людей. Такие системы стоят миллионы долларов и являются результатом работы коллективов очень опытных инженеров. Предполагается, что после их развертывания основные телефонные коммутаторы будут непрерывно работать двадцать лет, а общее время их простоя составит не более двадцати минут (по любым причинам, включая исчезновение энергопитания, наводнения и землетрясения). Мы не будем углубляться в детали — легче научить новичка, не знающего физики, вычислить поправки к курсу космического аппарата, спускающегося на поверхность Марса, — но попытаемся изложить идеи, которые могут оказаться полезными при тестировании менее крупных проектов или для понимания принципов тестирования более крупных систем.

  Прежде всего следует вспомнить, что целью тестирования является поиск ошибок, особенно часто встречающихся и потенциально опасных. Написать и выполнить большое количество тестов не просто. Отсюда следует, что для тестировщика крайне желательно понимать сущность тестируемой системы. Для эффективного тестирования систем знание прикладной области еще важнее, чем для тестирования отдельных модулей. Для разработки системы необходимо знать не только язык программирования и компьютерные науки, но и прикладную область, а также людей, которые будут использовать приложение. Это является одной из мотиваций для работы с программами: вы увидите много интересных приложений и встретите много интересных людей.

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

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

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

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