«С самого начала работы над проектом Selenium мы знали, что наши разработчики любят писать на многих языках. Кто-то предпочитает JS, кто-то Ruby, а кто-то C# или Java.
Сложность в том, что в Selenium весьма разнообразный код и много языковых связок. Например «атомы» — многократно используемые фрагменты на Javascript, выполняющие стандартные функции типа «isDisplayed» и «getAttribute», которые должны работать независимо от языка теста. Также поддержка CDP, это “общие” файлы, описывающие все доступные вызываемые функции, и Selenium Manager, который написан на Rust, но с языковыми связками.
Преобразование исходного кода и других артефактов (например “атомов”) в распространяемые нами артефакты (например Selenium Server или связки) называется «сборкой». Существует множество инструментов для сборки. Если вы Java-разработчик, вы, вероятно, знаете о Maven или Gradle. Если вы JS-хакер, то возможно вы знаете что-то о npm или yarn. Если вы разработчик на C (а таких еще много!), то вы, скорее всего, используете make или CMake.
Проблема многих инструментов сборки в том, что они ориентированы на один язык. npm — это здорово, но ужасный выбор для Java-проекта. Gradle ок, но если вы пишете на Ruby…
Почему это проблема: потому что в кодовой базе Selenium мы хотим поддерживать множество языков и сохранять возможность «сшивать» их в единое целое. Например, jar’ы Selenium содержат довольно большое количество JS. Гемы Ruby тоже.
И поэтому нужен инструмент для сборки, способный работать с множеством разных языков, чтобы мы могли соединить наш билд в нечто целое одним инструментом.
Это Bazel, инструмент для сборки, изначально разработанный в Google, но сейчас с открытым кодом и довольно широко используемый. Сам по себе этот инструмент относительно ограничен в возможностях, но его легко расширить с помощью «наборов правил», которые позволяют поддерживать все, что нам нужно.
Bazel относится к новому поколению инструментов сборки, он показывает, как интересующий процесс сборки связан с другими процессами. Это можно представить себе в виде диаграммы, на которой каждая сущность, которую нам нужно скомпилировать (например Selenium Manager, или “атомы”, или jar-файл), соединена линиями с другими сущностями, от которых она зависит. В Computer Science такая диаграмма называется графом, а так как каждая линия имеет направление («эта сущность зависит от той»), мы называем ее направленным графом. Поскольку мы не можем зависеть от чего-то, что зависит от самого себя, мы можем ввести «цикл». Bazel — это инструмент для сборки, предназначенный для работы с такими «направленными ациклическими графами».
Одна из приятных особенностей этих графов заключается в том, что существуют известные способы выяснить, какие части сборки могут выполняться параллельно. Современный компьютер имеет процессор с большим количеством (4, 8, 16) ядер, много памяти и быстрые SSD-накопители: на нем комфортно выполнять множество задач одновременно. Bazel использует это преимущество, запуская как можно больше частей билда одновременно. Это делает наши процессы значительно быстрее.
Еще лучше то, что Bazel заставляет перечислять все, от чего зависит каждая часть билда. Не только исходный код, но и используемые в данном случае версии инструментов. Это значительно облегчает работу новичкам: им нужно просто клонировать наше репо, убедиться, что у них установлен Bazel, и процесс сборки позаботится о том, чтобы у них было все необходимое (хотя первая сборка может быть очень медленной, поскольку все нужное будет загружаться по сети). Это приятно и для новичков, и для сеньоров. Им уже не нужно уточнять, как устанавливать и настраивать цепочки инструментов, с которыми они могут быть не знакомы — они просто запускают сборку.
Используя «граф сборки», Bazel самостоятельно определяет, какие части кода в исходном коде Selenium зависят от других частей. Это означает, что, хотя мы можем дать указание Bazel «запустить все тесты», когда мы вносим изменения, он достаточно умен чтобы понять, что ему нужно запустить только те тесты, на которые действительно влияет это изменение. Можете посмотреть на этот процесс на видео, и поверьте, что это экономит нам огромное количество времени. Мы также можем попросить Bazel повторно запустить упавшие тесты.
Есть и другое преимущество. Поскольку мы описали все, что нам нужно для Bazel, и как все части связаны друг с другом, нет необходимости запускать сборку на наших собственных машинах. Мы работаем с EngFlow, используя их сетку для сборки. Мы не запускаем небольшое количество сущностей одновременно на своих машинах, вместо этого запускаем во много раз больше в чужой сетке. Поэтому наши сборки невероятно быстры.
Вот почему мы используем Bazel в проекте Selenium: он поддерживает все языки в одном инструменте, позволяя не думать о том, как настраивать наши машины разработчиков, и невероятно быстро выполняет сборки.»