Регулярное тестирование сборок программной системы является основой современных практик разработки ПО. Широкое распространение получила технология непрерывной интеграции, которая предполагает тестирование каждой правки исходного кода, в дополнение к традиционному тестированию ночных сборок. Развитием данной идеи является использование набора тестов, запускаемого перед отправкой изменений в основную ветвь разработки, при этом 100% прохождение данных тестов является необходимым условием для попадания правок разработчика в репозиторий исходного кода. Такой подход позволяет избегать ситуаций, когда серьезная ошибка, допущенная одним из разработчиков блокирует работу целой команды.
Для сложных программных систем, состоящих из множества взаимодействующих компонент, характерно использование объемного предварительного тестирования, в связи с необходимостью проверки работоспособности каждой из составляющих частей системы. Ручное определение состава тестирования не всегда надежно, так как правки в одной из компонент могут отразиться на работе системы совершенно неожиданным для разработчика образом. На практике это приводит к существенному замедлению процесса разработки, так длительность предварительного тестирования является одним из факторов, ограничивающих скорость работы над проектом.
Подходы к сокращению объемов тестирования, основанные на сопоставлении изменений в исходном коде с данными о тестовом покрытии, описаны в литературе и хорошо изучены с теоретической стороны. Их основная идея состоит в исключении из тестового прогона тестов, не покрывающих изменившиеся части программы. Внедрение подобных методик в процесс разработки больших программных систем сталкивается с рядом трудностей, которые во многом определены объемами данных о тестовом покрытии. Наибольшую проблему представляет поддержание этих данных в актуальном состоянии, так как тестирование инструментированных сборок идет в несколько раз (как правило в 3-5 раз) дольше обычных тестирований. Таким образом, возрастающая нагрузка на тестирующую систему может свести на нет выигрыш, достигнутый сокращением объемов тестирования. Передача, хранение и оперативный анализ данных о тестовом покрытии также вызывает затруднения, так как их объем может достигать сотен гигабайт.
В данном докладе будет рассказано об опыте внедрения этой технологии в процесс разработки существующего программного продукта. Описанные выше проблемы были решены при помощи снижения детализации данных о тестовом покрытии. Вместо традиционного покрытия базовых блоков используется покрытие процедур (модулей, классов либо других крупных частей программы). Данный подход позволяет инструментировать только точки входа в процедуры, что существенно (до 80%) сокращает стоимость обновления данных о покрытии. Вместо отдельных тестов рассматриваются логические группы тестов (в предположении, что тестовая база имеет некоторую структуру), что сокращает объемы данных и повышает прозрачность работы алгоритма. Общее снижение детализации данных о тестовом покрытии влечет их меньшую изменчивость, что позволяет обновлять эти данные не для каждой правки в исходном коде, а на периодической основе. Также в докладе будут освещены другие вопросы, связанные с практическим внедрением данной методики, такие как разработка алгоритма анализа изменений в исходном коде и проверка семантической корректности программы для фиксированных входных данных.