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

Спецификация класса binary_search ясно указывает на то, что последовательность, в которой выполняется поиск, должна быть упорядоченной. Это не позволяет нам создавать многие изощренные модульные тесты. Однако очевидно, что существует возможность написать неправильный код, для которого мы не сможем изобрести тест, идентифицирующий ошибки (за исключением системных тестов). Можем ли мы использовать свое знание системных модулей (функций, классов и т.п.) для того, чтобы изобрести более хорошие тесты?

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

Рассмотрим функцию binary_search еще раз: мы не можем проверить, что входная последовательность [first:last] действительно является последовательностью и что она была упорядочена (см. раздел 26.3.2.2). Однако можем написать функцию, которая выполняет эту проверку.

template

bool b2(Iter first, Iter last, const T& value)

{

  // проверяем, является ли диапазон [first:last)

  // последовательностью:

  if (last

  // проверяем, является ли последовательность упорядоченной :

  for (Iter p = first+1; p

    if (*p<*(p–1)) throw Not_ordered;

  // все хорошо, вызываем функцию binary_search:

  return binary_search(first,last,value);

}

Перечислим причины, по которым функция binary_search не содержала таких проверок.

• Условие last нельзя проверить для однонаправленного итератора; например, итератор контейнера std::list не имеет оператора < (раздел Б.3.2). В общем, на самом деле хорошего способа проверки того, что пара итераторов определяет последовательность, не существует (начинать перемещение с итератора first, надеясь достигнуть итератора last, — не самая хорошая идея).

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

Что же мы могли бы сделать? Мы могли бы при тестировании заменить функцию binary_search функцией b2 (впрочем, только для вызовов функции binary_search с помощью итераторов произвольного доступа). В качестве альтернативы мы могли бы взять у разработчика функции binary_search ее код, чтобы вставить в нее свой фрагмент.

template // предупреждение:

                              // содержит псевдокод

bool binary_search (Iter first, Iter last, const T& value)

{

  if ( тест включен ) {

    if (Iter является итератором произвольного доступа) {

      // проверяем, является ли [first:last)

      // последовательностью :

      if (last

    }

    // проверяем является ли последовательность

    // упорядоченной:

    if (first!=last) {

      Iter prev = first;

      for (Iter p = ++first; p!=last; ++p, ++ prev)

        if (*p<*prev) throw Not_ordered;

    }

  }

  // теперь выполняем функцию binary_search

}

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже