- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп
Шрифт:
Интервал:
Закладка:
Чаще всего мы считаем, что знаем, как создать надежную систему из ненадежных частей. Мы тяжело работаем над каждой программой, каждым классом и каждой функцией, но, как правило, терпим неудачу при первом же испытании. Затем мы отлаживаем, тестируем и заново проектируем программу, устраняя в ней как можно больше ошибок. Однако в любой нетривиальной системе остается несколько скрытых ошибок. Мы знаем о них, но не можем найти или (реже) не можем найти их вовремя. После этого мы заново проектируем систему, чтобы выявить неожиданные и “невозможные” события. В результате может получиться система, которая выглядит надежно. Отметим, что такая система может по-прежнему скрывать ошибки (как правило, так и бывает) и работать меньше, чем ожидалось. Тем не менее она не выходит из строя окончательно и выполняет минимально возможные функции. Например, при исключительно большом количестве звонков телефонная система может не справляться с правильной обработкой каждого звонка, но никогда не отказывает окончательно.
Можно было бы пофилософствовать и подискутировать о том, следует ли считать неожиданные ошибки реальными ошибками, но давайте не будем этого делать. Для разработчиков системы выгоднее сразу выяснить, как сделать свои системы более надежными.
26.1.1. Предостережение
Тестирование — необъятная тема. Существует несколько точек зрения на то, как осуществлять тестирование, причем в разных прикладных областях — свои традиции и стандарты тестирования. И это естественно: нам не нужны одинаковые стандарты надежности для видеоигр и программного обеспечения для бортовых компьютеров авиалайнеров, но в итоге возникает путаница в терминах и избыточное разнообразие инструментов. Эту главу следует рассматривать как источник идей, касающихся как тестирования ваших персональных проектов, так и крупных систем. При тестировании больших систем используются настолько разнообразные комбинации инструментов и организационных структур, что описывать их здесь совершенно бессмысленно.
26.2. Доказательства
Постойте! Почему бы просто не доказать, что наши программы корректны, и не возиться с тестами? Как лаконично указал Эдсгер Дейкстра (Edsger Dijkstra): “Тестирование может выявить наличие ошибок, а не их отсутствие”. Это приводит к очевидному желанию доказать корректность программ так, как математики доказывают теоремы.
К сожалению, доказательство корректности нетривиальных программ выходит за пределы современных возможностей (за исключением некоторых очень ограниченных прикладных областей), само доказательство может содержать ошибки (как и математические теоремы), и вся теория и практика доказательства корректности программ являются весьма сложными. Итак, поскольку мы можем структурировать свои программы, то можем раздумывать о них и убеждаться, что они работают правильно. Однако мы также тестируем программы (раздел 26.3) и пытаемся организовать код так, чтобы он был устойчив к оставшимся ошибкам (раздел 26.4).
26.3. Тестирование
В разделе 5.11 мы назвали тестирование систематическим поиском ошибок. Рассмотрим методы такого поиска.
Различают тестирование модулей (unit testing) и тестирование систем (system testing). Модулем называется функция или класс, являющиеся частью полной программы. Если мы тестируем такие модули по отдельности, то знаем, где искать проблемы в случае обнаружения ошибок; все ошибки, которые мы можем обнаружить, находятся в проверяемом модуле (или в коде, который мы используем для проведения тестирования). Это контрастирует с тестированием систем, в ходе которого тестируется полная система, и мы знаем, что ошибка находится “где-то в системе”. Как правило, ошибки, найденные при тестировании систем, — при условии, что мы хорошо протестировали отдельные модули, — связаны с нежелательными взаимодействиями модулей. Ошибки в системе часто найти труднее, чем в модуле, причем на это затрачивается больше сил и времени.
Очевидно, что модуль (скажем, класс) может состоять из других модулей (например, функций или других классов), а системы (например, электронные коммерческие системы) могут состоять из других систем (например, баз данных, графического пользовательского интерфейса, сетевой системы и системы проверки заказов), поэтому различия между тестированием модулей и тестированием систем не так ясны, как хотелось бы, но общая идея заключается в том, что при правильном тестировании мы экономим силы и нервы пользователей.
Один из подходов к тестированию основан на конструировании нетривиальных систем из модулей, которые, в свою очередь, сами состоят из более мелких модулей. Итак, начинаем тестирование с самых маленьких модулей, а затем тестируем модули, которые состоят из этих модулей, и так до тех пор, пока не приступим к тестированию всей системы. Иначе говоря, система при таком подходе рассматривается как самый большой модуль (если он не используется как часть более крупной системы).
Прежде всего рассмотрим, как тестируется модуль (например, функция, класс, иерархия классов или шаблон). Тестирование проводится либо по методу прозрачного ящика (когда мы можем видеть детали реализации тестируемого модуля), либо по методу черного ящика (когда мы видим только интерфейс тестируемого модуля). Мы не будем глубоко вникать в различия между этими методами; в любом случае следует читать исходный код того, что тестируется. Однако помните, что позднее кто-то перепишет эту реализацию, поэтому не пытайтесь использовать информацию, которая не гарантируется в интерфейсе. По существу, при любом виде тестирования основная идея заключается в исследовании реакции интерфейса на ввод информации.
Говоря, что кто-то (может быть, вы сами) может изменить код после того, как вы его протестируете, приводит нас к идее регрессивного тестирования. По существу, как только вы внесли изменение, сразу же повторите тестирование, чтобы убедиться, что вы ничего не разрушили. Итак, если вы улучшили модуль, то должны повторить его тестирование и, перед тем как передать законченную систему кому-то еще (или перед тем, как использовать ее самому), должны выполнить тестирование полной системы. Выполнение такого полного тестирования системы часто называют регрессивным тестированием (regression testing), поскольку оно подразумевает выполнение тестов, которые ранее уже выявили ошибки, чтобы убедиться, что они не возникли вновь. Если они возникли вновь, то программа регрессировала и ошибки следует устранить снова.
26.3.1. Регрессивные тесты
Создание крупной коллекции тестов, которые в прошлом оказались полезными для поиска ошибок, является основным способом конструирования эффективного тестового набора для системы. Предположим, у вас есть пользователи, которые будут сообщать вам

