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

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

Какими недостатками обладают указанные тесты?

• Один и тот же код приходится писать несколько раз.

• Тесты пронумерованы вручную.

• Вывод минимальный (мало информативный).

Поразмыслив, мы решили записать тесты в файл. Каждый тест должен иметь идентифицирующую метку, искомое значение, последовательность и ожидаемый результат. Например:

{ 27 7 { 1 2 3 5 8 13 21} 0 }

Это тест под номером 27. Он ищет число 7 в последовательности { 1,2,3,5,8,13,21 }, ожидая, что результатом является 0 (т.е. false). Почему мы записали этот тест в файл, а не в текст программы? В данном случае мы вполне могли написать этот тест прямо в исходном коде, но большое количество данных в тексте программы может ее запутать. Кроме того, тесты часто генерируются другими программами. Как правило, тесты, сгенерированные программами, записываются в файлы. Кроме того, теперь мы можем написать тестовую программу, которую можно запускать с разными тестовыми файлами.

struct Test {

  string label;

  int val;

  vector seq;

  bool res;

};

istream& operator>>(istream& is, Test& t); // используется описанный

                                           // формат

int test_all(istream& is)

{

  int error_count = 0;

  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 }

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

<p id="AutBody_Root516"><strong>26.3.2.3. Случайные последовательности</strong></p>

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

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

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

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

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

 // с позиции base

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

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

97 этюдов для архитекторов программных систем
97 этюдов для архитекторов программных систем

Успешная карьера архитектора программного обеспечения требует хорошего владения как технической, так и деловой сторонами вопросов, связанных с проектированием архитектуры. В этой необычной книге ведущие архитекторы ПО со всего света обсуждают важные принципы разработки, выходящие далеко за пределы чисто технических вопросов.?Архитектор ПО выполняет роль посредника между командой разработчиков и бизнес-руководством компании, поэтому чтобы добиться успеха в этой профессии, необходимо не только овладеть различными технологиями, но и обеспечить работу над проектом в соответствии с бизнес-целями. В книге более 50 архитекторов рассказывают о том, что считают самым важным в своей работе, дают советы, как организовать общение с другими участниками проекта, как снизить сложность архитектуры, как оказывать поддержку разработчикам. Они щедро делятся множеством полезных идей и приемов, которые вынесли из своего многолетнего опыта. Авторы надеются, что книга станет источником вдохновения и руководством к действию для многих профессиональных программистов.

Билл де Ора , Майкл Хайгард , Нил Форд

Программирование, программы, базы данных / Базы данных / Программирование / Книги по IT
Программирование. Принципы и практика использования C++ Исправленное издание
Программирование. Принципы и практика использования C++ Исправленное издание

Специальное издание самой читаемой и содержащей наиболее достоверные сведения книги по C++. Книга написана Бьярне Страуструпом — автором языка программирования C++ — и является каноническим изложением возможностей этого языка. Помимо подробного описания собственно языка, на страницах книги вы найдете доказавшие свою эффективность подходы к решению разнообразных задач проектирования и программирования. Многочисленные примеры демонстрируют как хороший стиль программирования на С-совместимом ядре C++, так и современный -ориентированный подход к созданию программных продуктов. Третье издание бестселлера было существенно переработано автором. Результатом этой переработки стала большая доступность книги для новичков. В то же время, текст обогатился сведениями и методиками программирования, которые могут оказаться полезными даже для многоопытных специалистов по C++. Не обойдены вниманием и нововведения языка: стандартная библиотека шаблонов (STL), пространства имен (namespaces), механизм идентификации типов во время выполнения (RTTI), явные приведения типов (cast-операторы) и другие. Настоящее специальное издание отличается от третьего добавлением двух новых приложений (посвященных локализации и безопасной обработке исключений средствами стандартной библиотеки), довольно многочисленными уточнениями в остальном тексте, а также исправлением множества опечаток. Книга адресована программистам, использующим в своей повседневной работе C++. Она также будет полезна преподавателям, студентам и всем, кто хочет ознакомиться с описанием языка «из первых рук».

Бьерн Страуструп , Бьёрн Страуструп , Валерий Федорович Альмухаметов , Ирина Сергеевна Козлова

Программирование, программы, базы данных / Базы данных / Программирование / Учебная и научная литература / Образование и наука / Книги по IT