Добавить в цитаты Настройки чтения

Страница 12 из 16

Вся платформа Google построена на простоте и единообразии: одинаковые сборки Linux для компьютеров инженеров и машин с боевой средой, общие базовые библиотеки под централизованным управлением, общая инфраструктура хранения исходного кода, сборки и тестирования, один компилятор для каждого из языков программирования, общая спецификация сборки для всех языков. И самое важное, культура, которая уважает и поощряет поддержку этих общих ресурсов.

Тему единообразия платформ и единства репозитория продолжает единая система сборки, не зависящая от языка, на котором написан проект. Не важно, на каком языке работает команда (C++, Python или Java), она все равно будет использовать общие «файлы сборки».

Чтобы сборка состоялась, нужно указать «цель сборки». Это может быть библиотека, бинарный файл или набор тестов, который состоит из некоторого количества исходных файлов.

Последовательность шагов следующая.

1. Напишите класс или набор функций в одном или нескольких исходных файлах. Убедитесь, что весь код компилируется.

2. Укажите цель сборки (например, определенную библиотеку) для новой сборки.

3. Напишите юнит-тесты, которые импортируют библиотеку, имитируют нетривиальные зависимости и выполняют интересующие нас пути в коде для самых актуальных входных данных.

4. Создайте тестовую сборку для юнит-тестов.

5. Соберите и запустите сборку с тестами. Изменяйте код до тех пор, пока все тесты не будут проходить.

6. Запустите все обязательные инструменты статического анализа, которые проверяют соответствие кода гайдлайнам и выявляют стандартные баги.

7. Отправьте итоговый код на код-ревью (подробнее о код-ревью мы расскажем позже), внесите изменения и повторите все юнит-тесты.

В результате мы создаем две сборки: собственно библиотеку, представляющую новый сервис, и сборку тестов для этого сервиса. Учтите, что многие разработчики в Google применяют методологию TDD (Test-Driven Development, или разработка через тестирование), при которой шаг 3 предшествует шагам 1 и 2.

Если разработчик конструирует более крупный сервис, то он продолжает писать код, связывая постоянно увеличивающиеся сборки библиотек. Сборка бинарника создается из основного файла, который ссылается на нужные библиотеки. Так появляется продукт Google, у которого есть:

— хорошо протестированный автономный бинарный файл;

— легкочитаемая и приспособленная для повторного использования библиотека (с набором вспомогательных библиотек, которые можно использовать для создания других сервисов);





— набор юнит-тестов, покрывающих нужные аспекты всех сборок.

Типичный продукт Google — это набор нескольких сервисов. В любой команде мы стараемся добиться соотношения 1:1 между разработчиками и сервисами. Это означает, что сервисы собираются и тестируются параллельно, а затем интегрируются в итоговой сборке. Чтобы связанные сервисы могли создаваться одновременно, их интерфейсы взаимодействия согласовываются в начале проекта. Тогда разработчики могут реализовывать зависимости через такие интерфейсы, а не через библиотеки. В начале работы разработчики создают имитации таких интерфейсов, чтобы начать писать тесты на уровне всего сервиса.

Разработчики в тестировании вовлечены в создание большинства тестовых сборок и определяют, где нужно писать малые тесты. По мере того как маленькие сборки собираются в целое приложение, задачи растут, и уже нужно проводить более крупные интеграционные тесты. Если для сборки одной библиотеки достаточно выполнения малых тестов, написанных самим разработчиком, то с увеличением объема сборок разработчики в тестировании вовлекаются во все большей степени и пишут уже средние и большие тесты.

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

Разработчики в тестировании — центр всей этой деятельности. Они помогают разработчикам решить, какие юнит-тесты написать. Они создают подставные объекты и имитации. Они пишут средние и большие интеграционные тесты. Именно об этих задачах разработчиков в тестировании мы собираемся сейчас рассказать.

Кто такие разработчики в тестировании на самом деле?

Разработчики в тестировании — это инженеры, которые помогают тестировать на всех уровнях процесса разработки Google. Но все же в первую очередь они именно разработчики. Во всех наших руководствах по найму и внутренних документах написано, что их работа на 100% связана с программированием. Этот специфический, можно даже сказать гибридный, подход к тестированию позволяет нам рано привлекать тестировщиков к проектам. Причем они занимаются не составлением абстрактных тест-планов или моделей качества, а сразу погружаются в проектирование и написание кода. Это ставит на одну чашу весов и программистов, и тестировщиков. Это повышает производительность команды и создает доверие ко всем видам тестирования, включая ручное и исследовательское, которое потом проведут уже другие инженеры.

Тест — это еще одна фича приложения, и за нее отвечают разработчики в тестировании.

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

На собеседовании разработчики в тестировании должны продемонстрировать такие же знания по программированию, как и разработчики. Даже больше — они должны уметь тестировать код, который написали. Проще говоря, разработчик в тестировании должен ответить на те же вопросы по программированию, что и разработчик, а потом еще решить задачки по тестированию.

Как вы уже догадались, специалистов на эту роль найти непросто. Скорее всего, это и есть причина относительно малого количества разработчиков в тестировании в Google. А вовсе не то, что мы нашли волшебную формулу производительности. Скорее, мы смирились с реальностью и адаптировали нашу работу, зная, что такое сочетание навыков встречается редко. Однако сходство ролей разработчика и разработчика в тестировании дало приятный побочный эффект: люди могут переходить из одной группы в другую. Google как раз старается поддерживать переходы между ролями. Представьте компанию, в которой все разработчики умеют тестировать, а все тестировщики умеют программировать. Нам далеко до этого, и, наверное, мы никогда такими не станем, но эти группы все-таки пересекаются. Мы находим разработчиков в тестировании со склонностью к разработке и разработчиков со склонностью к тестированию. Такие ребята становятся нашими лучшими инженерами и образуют самые эффективные команды разработки.

Ранняя стадия проекта

В Google нет правила, когда именно разработчики в тестировании должны присоединиться к проекту. Так же как нигде не прописано, когда именно проект становится «реальным». Типичный сценарий создания нового проекта такой: эксперимент, над которым работали в «двадцатипроцентное» время, набирается сил и становится самостоятельным продуктом Google. Именно так развивались Gmail и Chrome OS. Эти проекты начинались с неформальных идей, а со временем выросли в полноценные продукты со своими командами разработчиков и тестировщиков. Наш друг Альберто Савоя (написавший введение к этой книге) любит повторять, что «качество не имеет значения, пока ваш продукт не имеет значения».