Эндрю Хант - Программист-прагматик. Путь от подмастерья к мастеру
Как только все соответствующие модули прошли индивидуальное тестирование, вы готовы к новому этапу. Вам придется проверить, как модули используют друг друга и взаимодействуют между собой по всей системе.
Комплексное тестированиеКомплексное тестирование показывает, что основные подсистемы, из которых состоит проект, работают и нормально взаимодействуют друг с другом. При наличии удачных и хорошо проверенных контрактов обнаружить любые проблемы интеграции не составляет особого труда. В противном случае интеграция становится благодатной почвой для размножения дефектов. Фактически в многих случаях она является единственным и самым крупным источником дефектов в системе.
В реальности комплексное тестирование является продолжением модульного тестирования, описанного выше, с той лишь разницей, что теперь вы проверяете, как целые подсистемы соблюдают свои контракты.
Подтверждение правильности и верификацияКак только в вашем распоряжении появляется рабочий пользовательский интерфейс или прототип, вам приходится отвечать на существенный вопрос: пользователи сказали вам, что они хотели бы увидеть, но то ли это на самом деле?
Отвечает ли продукт функциональным требованиям системы? Это также нуждается в тестировании. Бездефектная система, которая отвечает на неправильные вопросы, не приносит пользы. Необходимо осознавать схемы доступа конечного пользователя и их отличие от тестовых данных разработчика (в качестве примера обратите внимание на историю о рисовании кистью из раздела "Отладка")
Тестирование в условиях нехватки ресурсов, ошибки и их исправление.Теперь вы понимаете, что система будет вести себя корректно в идеальных условиях, вам придется испытать, как она ведет себя в реальных условиях. В реальном мире ресурсы ваших программ не безграничны – они исчерпываются. Ваша программа может столкнуться со следующими ограничениями:
• Объем памяти
• Объем дискового пространства
• Мощность процессора
• Тактовая частота
• Скорость дискового обмена
• Пропускная способность сети
• Цветовая палитра
• Разрешающая способность экрана
Вы можете реально проверить нехватку дискового пространства или объема памяти, но как часто вы проверяете другие ограничения? Будет ли ваше приложение работать на экране с разрешением 640*480 и 256 цветами? Может ли оно выполняться на экране с разрешением 1600*1280 с 24-битным цветом и при этом не быть размером с почтовую марку? Завершится ли пакетное задание до момента запуска программы архивации?
Вы можете обнаружить наличие ограничений в операционной среде, таких как спецификация видеоподсистемы, и приспособиться к ним соответствующим образом. Однако не все сбои можно восстановить. Если программа обнаруживает нехватку памяти, то вы ограничены в своих действиях: вам не хватит ресурсов, чтобы завершить программу способом, отличным от аварийного завершения.
Когда система выходит из строя [50], будет ли это делаться изящно? Постарается ли она сделать лучшее, на что она способна в данной ситуации, – сохранить свое состояние и предотвратить потерю данных? Или она выдаст пользователю сообщения типа "Общая ошибка защиты" или "core dump" (отключение ядра системы)?
Тестирование производительностиТестирование производительности, нагрузочное тестирование или тестирование в реальных условиях эксплуатации может также оказаться важным аспектом проекта.
Задайте себе вопрос, отвечает ли программа требованиям производительности в условиях реального мира – с ожидаемым числом пользователей, подключений или транзакций в единицу времени. Является ли она масштабируемой?
При работе с некоторыми приложениями вам могут понадобиться специализированные тестовая аппаратура или программное обеспечение для реалистичной имитации нагрузок.
Тестирование удобства использованияТестирование удобства использования отличается от процедур тестирования, обсужденных выше. Оно осуществляется с реальными пользователями в реальных условиях окружающей среды.
Рассмотрим удобство использования с точки зрения человеческого фактора. Имелись ли какие-либо недоразумения в ходе анализа требований, на которые необходимо обратить внимание? Подходит ли программное обеспечение пользователю, становясь продолжением его рук? (Мы хотим, чтобы не только наши собственные инструменты были изготовлены по руке, но чтобы и те, которые мы создаем для пользователей, подходили им.)
Как и при подтверждении правильности и верификации, вам приходится осуществлять тестирование удобства использования как можно раньше, пока есть время на внесение изменений. Для крупномасштабных проектов вы можете привлечь специалистов в области человеческого фактора.
Несоответствие критериям удобства использования является дефектом такого же порядка, как деление на ноль.
Как проводить тестирование
Мы рассмотрели то, что подлежит тестированию. Теперь мы обратим внимание на то, как это делается, включая следующее:
• Регрессионное тестирование
• Тестовые данные
• Тестирование систем с графическим интерфейсом
• Тестирование самих тестов
• Исчерпывающее тестирование
Тестирование проектных решений/методологииМожете ли вы провести тестирование проектных решений в самой программе и методологии, которую вы использовали при сборке программного обеспечения? Некоторым образом можете. Вы делаете это, анализируя метрики – измерения различных аспектов программы. Самой простой метрикой (и чаще всего, наименее интересной) является число строк кода – насколько велика сама программа?
Существует большое количество других метрик, которые вы можете использовать для исследования программы:
• Показатель цикломатической сложности Маккейба (измеряет сложность структуры решений)
• Коэффициент разветвления по входу при наследовании (количество базовых классов) и по выходу (количество производных модулей; используется в качестве родителя)
• Набор откликов (см. раздел "Несвязанность и закон Деметера")
• Отношения связывания класса (см. [URL 48])
Некоторые метрики предназначены для того, чтобы дать вам "проходной балл", тогда как другие полезны только в сравнении. Это означает, что вы вычисляете метрики для каждого модуля в системе и смотрите, как конкретный модуль относится к своим братьям. Здесь обычно используются стандартные статистические методики.
Если вы обнаруживаете модуль, чья метрика значительно отличается от всех остальных, вам необходимо задать вопрос, приемлемо ли это. Для некоторых модулей "нарушение хода кривой" может быть вполне нормально. Но для тех, у которых нет хорошего оправдания, это может свидетельствовать о потенциальных проблемах.
Регрессионное тестированиеРегрессионное тестирование сравнивает выходные данные текущего теста с результатами (или известными значениями) предыдущих. Мы можем гарантировать, что дефекты, устраненные сегодня, не нарушат ничего из того, над чем мы работали вчера. Это важное средство страховки, и оно сокращает число неприятных сюрпризов.
Все тесты, о которых мы говорили до настоящего момента, могут запускаться как регрессионные тесты с гарантией, что мы не откатываемся назад, когда разрабатываем новую программу. Мы можем запускать регрессии для тестирования производительности, контрактов, достоверности и т. д.
Тестовые данныеГде мы достаем данные для запуска всех этих тестов? Существует только два типа данных: реальные и синтезированные данные. В действительности нам необходимо использовать оба типа, поскольку их различная природа будет способствовать выявлению разных дефектов в программном обеспечении.
Реальные данные исходят из некоего реального источника. Возможно, они были получены из существующей системы, конкурирующей системы или некоего прототипа. Они представляют типичные пользовательские данные. Большие сюрпризы возникают, как только вы открываете значение термина «типичный». При этом скорее всего являются дефекты и недоразумения в анализе требований.
Синтезированные данные генерируются искусственно, возможно, с определенными статистическими ограничениями. Вам могут понадобиться синтезированные данные по одной из следующих причин:
• Вам необходимо много данных, возможно, больше, чем содержится в любом из имеющихся образцов. Вы сможете использовать реальные данные в качестве «саженца» душ генерации большего набора данных и добиться уникальности определенных полей.
• Вам необходимы данные для того, чтобы выделить определенные граничные условия. Эти данные могут быть полностью синтезированными: поля, содержащие дату 29 февраля 1999 г., огромные размеры записей или адреса с иностранными почтовыми индексами.