Много лет назад я отправился на поиски.
Покрытие казалось для меня важным словом в тестировании, но в какой-то момент я поймал себя на мысли, что не обладаю достаточно четким представлением об этом. Я чувствовал, что в этом не одинок.
Я хотел знать, что люди имеют в виду под «покрытием». И я хотел знать, что имею в виду я сам.
В учебных материалах класса «Быстрое тестирование ПО» Джеймс Бах описал покрытие как «протестированную пропорцию продукта». Я не понял смысла сказанного.
Можем ли мы думать о продукте в рамках таких понятий? «Продукт» может для разных людей означать разное. Мы можем смотреть на продукт как на набор байтов на жестком диске, но это не особенно поможет. Продукт — это набор файлов и модулей, содержащие код, который инстанцирует значения объектам, данным и функциям. Продукт содержит взаимодействия между железом и софтом, некоторые из которых созданы нами, а некоторые — другими людьми. Продукт предлагает людям (предположительно ценные) функции и фичи. У продукта есть интерфейсы, с которыми люди и другие программы могут взаимодействовать, передавать ему данные, исследовать его содержимое, производить вывод.
Программный продукт — это не статичная материальная вещь, а набор связей. Как будет выглядеть продукт, представляющий набор связей на 100%? Это важный вопрос, потому что если мы не знаем, как выглядит 100%, идея «пропорции» не имеет большого смысла.
Так, мы с Джеймсом поспорили на эту тему.
Я пошел искать информацию в книгах по тестированию. Если в них и упоминалось про покрытие, то в большинстве случаев это было просто описание того, что это такое. В книгах, в которых было представлено описание покрытия, о нем говорилось с точки зрения покрытия кода — строк кода, ветвлений… В книге «Тестирование программного обеспечения» (Testing Computer Software. Cem Kaner, Hung Q Nguyen, Jack Falk) приводится цитата Бориса Бейзера: «Тестирование до достижения уровня полного покрытия приведет к обнаружению, в лучшем случае, половины количества багов.» Хм, и как такое может быть?
В один прекрасный день я нашел копию «Software Testing Techniques» Бейзера, которая содержала такую интригующую подсказку в указателе: «Любая метрика полноты по отношению к критерию выбора теста». Хотя в книге говорилось о покрытии кода, речь также шла о функциональных потоках в программе.
Джеймс утверждал, что «любая метрика полноты по отношению к критерию выбора теста» также не очень полезна. По его словам, «критерии отбора тестов» всегда основываются на какой-то модели продукта.
Модель — это некая идея, действие или объект (например, идея в вашем уме, диаграмма, список слов, электронная таблица, человек, игрушка, уравнение, демонстрация или программа…), который представляет (буквально выражаясь, ре-презентует) нечто сложное простыми терминами. Путем понимания чего-то о простых вещах, хорошая модель может помочь нам понять более сложные вещи.
Существует столько же способов смоделировать программный продукт, сколько и представить его, или его части, или то, к чему он относится. Для примера: мы можем смоделировать продукт путем репрезентации его компонентов на диаграмме. Мы можем смоделировать продукт, описав его в документе с требованиями, который и сам по себе является моделью требований продукта. Мы можем представить информацию, хранящуюся в продукте, в виде схемы базы данных.
Мы можем моделировать продукт, имея в виду его интерфейсы — API, GUI, командную строку. Мы можем представить взаимодействие пользователей с продуктом с помощью блок-схем, пользовательских историй, руководств и списков задач. И, конечно, мы всегда моделируем продукт неявно, имея набор идей в голове. Мы можем презентовать их самыми разными способами.
Код — не продукт. Продукт — это набор связей между софтом, железом, людьми, их потребностями и желаниями; индивидуально и в социальных группах. Код для продукта сам по себе является моделью продукта. Покрытие кода — это один из способов описать, как мы покрыли продукт тестированием.
И где-то во всех этих наших с Джеймсом дискуссиях начало зарождаться зерно понимания.
В Rapid Software Testing, где мы обсуждали покрытие в целом,
Покрытие — это то, насколько тщательно мы изучили продукт по отношению к какой-то модели.
Когда мы говорим о каком-либо покрытии, мы имеем в виду определенную модель.
Функциональное покрытие — это то, насколько тщательно мы изучили продукт в отношении какой-то модели функций в продукте.
Покрытие требований — это то, насколько тщательно мы исследовали продукт в отношении какой-то модели требований.
Покрытие производительности — это то, насколько тщательно мы исследовали продукт в отношении какой-то модели производительности.
Покрытие риска — это то, насколько тщательно мы изучили продукт в отношении какой-то модели риска.
Покрытие кода — это то, насколько тщательно мы изучили продукт в отношении какой-то модели кода.
Должно быть понятно, что покрытие кода — это не то же самое, что и покрытие риска; что покрытие кода не покрывает все возможные риски, которые могут быть связаны с продуктом. Также должно быть ясно, что покрытие риска (то, как тщательно мы изучили продукт в отношении какой-то модели риска) не обязательно покрывает весь код.
Это приводит нас к следующему интересному разделу: что мы понимаем под глубоким и поверхностным тестированием.
Всех желающих приглашаем на открытый урок, на котором познакомимся с тем, как очень быстро запустить автоматизацию API на проекте, а также запустим CI/CD для наших автотестов с отчетом в telegram.