Я большой поклонник автоматизированных тестов и достаточно дисциплинированный их автор. Проектирование ПО крайне сложно реализовать функционально корректно и ещё сложнее избежать регрессии в дальнейшем. Как сказал Майкл Фезерс, «легаси-код — это весь код, у которого нет тестов».
Некоторые вещи, например, конечные точки серверов, схемы баз данных и компоненты библиотек UI тестировать очень просто.
Другие вещи тестировать сложнее, например, конечные точки, вызывающие сторонние API, веб-страницы на React со сложными состояниями и асинхронные задачи, требующие детализированных записей баз данных. В Airbnb мне было сложно тестировать письма со сбросом паролей, потому что отправка электронной почты выполнялась через аутсорсный сервис.
Но такая функциональность всё равно заслуживает тестов, и на то есть две причины. Во-первых, всё равно важно, чтобы она не регрессировала — из-за их сложности вероятность регрессии велика. Во-вторых, тестирование сложных фич часто заставляет инженеров проектировать фичу таким образом, чтобы её можно было тестировать. Если вводить тесты ещё на ранних этапах разработки, это может мотивировать к проектированию более узких интерфейсов и снижению связанности, а значит, в долговременной перспективе приводит к повышению качества кодовой базы.
Тестировать или не тестировать?
Мир неидеален — иногда у нас есть время на написание фичи, но не хватает времени на создание автоматизированных тестов этой фичи. Почему так происходит? По аналогии с обратной задачей P=NP, многие фичи гораздо проще создать, чем тестировать. Возьмём для примера приложение на React для создания списка дел с функцией удаления свайпом. На разработку приложения может понадобится полчаса, но для создания автоматизированных тестов UI, проверяющих функцию удаления свайпом, можно потратить несколько часов или даже дней. Такой дисбаланс, а также поспешность, которая всегда необходима бизнесу, приводят к тому, что команды разработчиков вынуждены писать фичи, но игнорировать добавление трудозатратных тестов.
Насколько плоха ситуация? Если вы прагматичны, то не особо — иногда стоит увеличить технический долг, создавая функциональность без тестов. Выигрыш от нетестируемой фичи может быть высок, затраты на тестирование тоже высоки, а ваши ресурсы ограничены. Возможно, в вашей команде не хватает людей или это сторонний хобби-проект. Если вы заставляете себя добавить автоматизированные юнит-тесты для своего приложения со списками дел, то можете и никогда не выпустить его для первых десяти пользователей. (Однако если вы всё ещё не тестируете функцию удаления свайпом, даже набрав миллион пользователей, то напрашиваетесь на проблемы.)
Откладывание автоматизированных тестов на потом — скользкая дорожка, но создание продукта требует применения искусства стратегического пользования техническим долгом. «Кредит» позволяет командам разработчиков быстро проверять правильность, а обнаруженную ценность фичи можно в дальнейшем потратить на выплату технического долга (с процентами). Это справедливо для стартапов, а также для команд, создающих MVP. Если сначала потратить слишком много времени на создание трудозатратных тестов, то вам может не хватить времени на выпуск, анализ и дальнейшее развитие.
Творческий подход
Помните, что отсутствие автоматизированных тестов не означает полного отсутствия тестирования. По умолчанию отсутствие тестов означает, что вы втихомолку заставляете пользователей искать баги за вас. Трафик продакшена и тщательный алертинг могут служить слабой заменой автоматизированного тестирования, но лучше настроить быстрые откаты или флаги, не теряя при этом бдительности. Разочарованных пользователей вы надолго не удержите.
Вместо трафика продакшена лучше использовать подмножество трафика продакшена — часто чтобы найти регрессию, на баг достаточно наткнуться не всем пользователям, а только небольшой их части. Здесь могут пригодиться канареечные релизы и бета-когорты. Но всё равно существует проблема столкновения реальных пользователей с реальной регрессией, и чтобы понять, когда пользователи испытывают трудности, необходим качественный мониторинг.
Вместо бета-когорт лучше использовать догфудинг. Отправлять реальным пользователям фичу, которую вы не хотите тестировать автоматически, но пусть эти пользователи будут вами. Вы не можете просто перестать пользоваться собственным продуктом, а ваши глаза — прекрасная динамическая система алертов (только не забывайте каждую ночь закрывать их на восемь часов).
Проблемы с онбордингом
Итак, у вас есть спектр тестирования фич — автоматизированные тесты, канареечные релизы, бета-когорты и догфудинг. Наша команда разработки использует все эти методики, но в функциональности всё равно остаются слепые пятна.
Одно из самых сложных в тестировании слепых пятен для нас — это онбординг продукта. Это замороченный процесс с участием цикла OAuth и асинхронной загрузки метаданных репозитория с GitHub, запросов к нашим базам данных и уникальных элементов UI, не используемых ни в каких других частях приложения. Несмотря на эти трудности, онбординг крайне важен и нам нужно его как-то тестировать.
Классические синтетические тесты оказываются нестабильными из-за распознавания ботов при логине в GitHub. Тестирование канареечного трафика не особо помогает, потому что продакшен-пользователи, которым не удалось пройти онбординг, редко сообщают об этом; к тому же иногда в логах они отображаются как нерешительные, а не как пользователи, у которых возникли проблемы. Бета-когорты редко что-то отлавливают, потому что проходят онбординг только один раз; то же самое справедливо и для традиционного догфудинга.
Вращаем рулетку
Мы придумали следующее решение: скрипт-рулетка, ежедневно в 9 часов утра случайным образом удаляющий одну из учётных записей наших инженеров. Мы не просто сбрасываем онбординг, но и удаляем аккаунты, токены, настроенные фильтры, загруженные gif и так далее.
Раздражает ли это? Конечно. Наши коллеги приходят на работу, чтобы кодить новые фичи, но выясняют, что выполнен выход из системы и необходимо создавать аккаунты с нуля. Поначалу при проверке этой методики мы были осторожны, но сразу увидели все её преимущества. Примечание: это только аккаунт нашего продукта; у разработчиков сохраняется доступ к GitHub и другим аккаунтам компании.
Как и большинство компаний, мы стремимся создать быстрый и беспроблемный онбординг. Лучший способ добиться этого — заставить разработчиков ежедневно страдать, проходя процесс онбординга. Во всей команде технического проектирования продукта аккаунт каждого из сотрудников в среднем удаляется раз в месяц. Но возникновение проблем у одного коллеги за день оказалось достаточной ценой, мотивирующей находить и устранять проблемы.
Удаление аккаунтов сотрудников обеспечило догфудинг одной из самых критичных и сложных в тестировании поверхностей. Мы отловили кучу багов и развили в себе сочувствие к пользователю в одном из самых традиционных слепых пятен. Я крайне рекомендую другим продуктовым командам рассмотреть возможность удаления аккаунтов сотрудников для достижения тех же целей.
Ограничения
Идеально ли это решение? Нет. Удалённые сотрудники воссоздают аккаунты в уже существующей организации. Из-за этого они могут пропускать некоторые аспекты онбординга, с которыми сталкиваются пользователи. когда впервые настраивают продукт в новой организации, например, проблему долгой первоначальной синхронизации. В будущем мне бы хотелось изучить возможность удаления раз в месяц аккаунта всей компании, чтобы повысить степень догфудинга, хоть меня и беспокоит то, насколько сильно это помешает внесению утренних изменений в код.
Может ли любой продукт позволить себе такое частое удаление аккаунтов сотрудников, как у нас? Вероятно, нет — в некоторых аккаунтах накапливается не только конфигурация, но и множество полезного создаваемого пользователями контента. Например, Instagram и Google Docs, возможно, не смогут воспользоваться таким подходом. Но для многих сервисов, особенно для тех, в которых создаваемые пользователями данные могут выжить после удаления отдельного аккаунта, это пойдёт на пользу. Такие продукты, как Datadog, Vercel, Hex и Superhuman могут позволить себе удалять аккаунты сотрудников раз в месяц. Да, людям придётся восстанавливать личные дэшборды и фильтры, но ведь в этом и смысл.
Работа на будущее
Продолжим ли мы постоянно удалять аккаунты сотрудников? Подозреваю, что да. Однако онбординг с догфудингом не лучше, чем автоматизированное тестирование: мы постоянно вкладываем большие средства в создание реальных сквозных и юнит-тестов. Но догфудинг достаточно сильно отличается от автоматизированного тестирования, и они дополняют друг друга. Догфудинг отлавливает неизвестные неизвестные так, как с этим не справляются автоматизированные тесты. Он вырабатывает в разработчиках сочувствие к пользователям, а также создаёт глубокое видение продукта, которое сотрудники могут использовать в будущих обновлениях. Если разработчику не так легко восстановить аккаунт, то будет ли новому пользователю просто создать его?