20 мая 2018 г.

"Тестирование конфигурации для java-разработчиков" (Гейзенбаг 2018, Петербург)


Меж тем я тут немного погрузился в тестирование — вплоть до того, что выступал на питерском Гейзенбаге с докладом про тестирование конфигурации. Только вчера вернулся, а сегодня на сайте конференции уже выложили слайды.

Тезисно: я рассказывал о том, что конфигурация это важная часть приложения — такая же важная, как код. Ошибки в конфигурации приводят к некорректной работе сервисов, и/или отказам в обслуживании — ровно так же, как и ошибки в коде.

Но код приложения проходит множество проверок — начиная от компилятора (если вы, конечно, пишете на нормальных языках, а не на JavaScript), и кончая многими уровнями тестов. Конфигурация же, чаще всего, это просто какие-то текстовые файлы (properties, xml, yaml, json...), с очень вольным форматом, практически без валидации. Никаких автоматизированных тестов для нее, как правило, нет.

К валидации конфигурационных параметров в самом приложении программисты тоже обычно относятся наплевательски — в большинстве приложений валидации либо нет, либо она довольно дырявая.

UAT/staging проблемы не решает: конфигурация, как правило, различается для разных environment, поэтому протестировав сервисы в UAT/staging вы протестируете конфигурацию UAT/staging, но не PROD.

Проверить конфигурацию методом пристального взгляда (code review) не очень реально: в более-менее крупном проекте объем конфигурации измеряется сотнями и тысячами строк, и мало кто знает смысл и ограничения всех существующих параметров, и как они взаимодействуют с другими параметрами.

Из всего вышесказанного очевидно: потребность в тестировании конфигурации столь же сильная, что и потребность в тестировании кода.


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

По моему опыту, самый существенный барьер не технический, а психологический. Выглядят-то тесты конфигурации как юнит-тесты, но фактически лазают по файловой системе, какие-то файлики там читают… Т.е. как юнит-тесты они выглядят странновато и кривовато. Да и вообще сама идея что конфигурацию нужно тестировать так же, как код — требует времени, чтобы к ней привыкнуть. Но это вопрос привычки: вспомните, сколько времени разработчики привыкали к идее, что нужно тестировать код.

А еще конфигурация не заканчивается на .properties/.xml: можно тестировать crontabs, sql, shell-scripts — все то, что важно для работы сервисов, и не проверяется другими способами. Не всегда можно протестировать во всей полноте, но почти всегда можно написать тест, закрывающий путь конкретному классу ошибок, которые больше всего портят жизнь.


Мы пишем тесты конфигурации уже года 3 (спасибо Андрею Сатарину, который принес эту идею — его собственный рассказ про тестирование конфигурации был на московском Гейзенбаге 2017). И за 3 года написания и поддержки мы набрели на несколько удачных решений.

Например, для тестирования взаимозависимостей между параметрами разных сервисов полезно построить модель предметной области — т.е. модель деплоймента приложения. Формализовать в виде программных объектов environments, сервера, сервисы, конфигурационные файлы, и как это все между собой связано в вашем случае. Тогда тесты будут выглядеть не как “пойди в ту папочку, возьми такой файлик…”, а как “для каждого environment-а в конфигурации сервиса ХХХ на primary-сервере те же самые порты, что и в конфигурации того же сервиса ХХХ на backup-сервере того же environment-а". Такая модель полезна сама по себе — в ходе ее создания проясняется много всякого неявного знания о деплойменте.

А еще для тестирования конфигурацию удобно представлять не как Properties, а как Stream из кортежей типа [environment, server, service, configFile, propertyName, propertyValue]. Тесты в таком виде выглядят более единообразно, кроме того если тест падает, то в сообщении об ошибке автоматом будет весь адрес злокозненного свойства.


Ну и на закуску был case-study: тестирование конфигурации как поддержка для рефакторинга конфигурации. Есть сложная и запутанная система конфигурации, доставшаяся в наследство, которую нужно упростить и преобразовать в понятный вид. Как построить достаточно плотную сеть тестов, которая позволит удостоверить, что преобразованная конфигурация по-прежнему корректна?

Комментариев нет:

Отправить комментарий