Вход/Регистрация
Программирование. Принципы и практика использования C++ Исправленное издание
вернуться

Страуструп Бьерн

Шрифт:

Test t;

while (is>>t) {

bool r = binary_search( t.seq.begin, t.seq.end, t.val);

if (r !=t.res) {

cout << "отказ: тест " << t.label

<< "binary_search: "

<< t.seq.size << "элементов, val==" << t.val

<< " –> " << t.res << '\n';

++error_count;

}

}

return error_count;

}

int main

{

int errors = test_all(ifstream ("my_test.txt");

cout << "Количество ошибок: " << errors << "\n";

}

Вот как выглядят некоторые тестовые данные.

{ 1.1 1 { 1 2 3 5 8 13 21 } 1 }

{ 1.2 5 { 1 2 3 5 8 13 21 } 1 }

{ 1.3 8 { 1 2 3 5 8 13 21 } 1 }

{ 1.4 21 { 1 2 3 5 8 13 21 } 1 }

{ 1.5 –7 { 1 2 3 5 8 13 21 } 0 }

{ 1.6 4 { 1 2 3 5 8 13 21 } 0 }

{ 1.7 22 { 1 2 3 5 8 13 21 } 0 }

{ 2 1 { } 0 }

{ 3.1 1 { 1 } 1 }

{ 3.2 0 { 1 } 0 }

{ 3.3 2 { 1 } 0 }

Здесь видно, почему мы использовали строковую метку, а не число: это позволяет более гибко нумеровать тесты с помощью десятичной точки, обозначающей разные тесты для одной и той же последовательности. Более сложный формат тестов позволяет исключить необходимость повторения одной и той же тестовой последовательности в файле данных.

26.3.2.3. Случайные последовательности

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

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

cout
с помощью функции
randint
из раздела 24.7 и заголовочного файла
std_lib.facilities.h
.

void make_test(const string& lab,int n,int base,int spread)

// записывает описание теста с меткой lab в поток cout

// генерирует последовательность из n элементов, начиная

// с позиции base

// среднее расстояние между элементами равномерно распределено

// на отрезке [0, spread]

{

cout << "{ " << lab << " " << n << " { ";

vector<int> v;

int elem = base;

for (int i = 0; i<n; ++i) { // создаем элементы

elem+= randint(spread);

v.push_back(elem);

}

int val = base + randint(elem–base); // создаем искомое значение

bool found = false;

for (int i = 0; i<n; ++i) { // печатаем элементы и проверяем,

// найден ли элемент val

if (v[i]==val) found = true;

cout << v[i] << " ";

}

cout << "} " << found << " }\n";

}

Отметим, что для проверки, найден ли элемент

val
в случайной последовательности, мы не использовали функцию
binary_search
. Для того чтобы обеспечить корректность теста, мы не должны использовать функцию, которую проверяем.

На самом деле функция

binary_search
не самый удобный пример для тестирования с помощью наивного подхода на основе случайных чисел. Мы сомневаемся, что сможем найти какие-то новые ошибки, пропущенные на ранних этапах с помощью тестов, разработанных “вручную”, тем не менее этот метод довольно часто оказывается полезным. В любом случае следует выполнить несколько случайных тестов.

  • Читать дальше
  • 1
  • ...
  • 425
  • 426
  • 427
  • 428
  • 429
  • 430
  • 431
  • 432
  • 433
  • 434
  • 435
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: