Наша команда работает над «лицом» 2gis.ru — WebGL-библиотекой для визуализации картографических данных. В статье кратенько расскажем про WebGL (это будет важно для понимания особенностей его тестирования), про общий подход к тестированию и непосредственно про особенности тестирования приложения на WebGL [с которыми нам пришлось столкнуться].

Что вообще за WebGL
Примерно 30 лет назад, когда изобрели относительно мощные видеокарты, люди придумали, что часть вычислений можно выполнять непосредственно на них и не тратить время на передачу информации между основным и графическим процессором.
Довольно быстро стало понятно, что писать код для каждой конкретной видеокарты ужасно неудобно и нужен какой-то общий программный интерфейс. Так появился OpenGL (а также Metal, Vulkan, Direct3D), а потом и его реализация под веб — WebGL, которая уже лет десять как поддерживается всеми браузерами.
Чем хорош WebGL для карты
Каждый, кто хоть раз обращался к современным онлайн-картам, знает, что её (в отличие от аналоговой) можно приближать, отдалять, крутить, а ещё кликать на объекты, измерять расстояние между ними. Чтобы пользователь не возненавидел сайт в первую же минуту, всё это должно происходить незаметно для него, максимально быстро и плавно. Тут-то нам и пригождается WebGL.
Как и подобает низкоуровневому API, он умеет рисовать только очень простые двумерные фигуры (максимум — треугольники), но делает это невероятно быстро.
Следовательно, если мы научимся представлять все нужные нам объекты в виде [множества] треугольников, мы прямо в браузере получим возможность очень быстро рисовать и перерисовывать изображение. Чем и занимается наше приложение:
-
Учитывает положение и размер видимой области карты; наклон, поворот и зум карты + действия пользователя.
-
Загружает данные — что мы хотим нарисовать.
-
Загружает стиль — как мы хотим это нарисовать.
-
Преобразует всё это в формат, понятный WebGL, и запускает отрисовку.
-
[По необходимости] повторяет с пункта 1.
Успешность работы этого конвейера хотелось бы проверить.
Что нужно для тестирования
На входе есть набор переменных: источник данных для отрисовки, параметры стиля отрисовки, состояния карты или действия с картой в браузере. На выходе — нарисованный объект. Кажется, ничего сложного: комбинируем, создаём набор кейсов — готово?

Но главное — не торопиться и:
-
Понять, что будем проверять. Что является результатом работы нашего приложения? JSON с определенным содержимым? Docker-образ? Запись в базе данных? Исходя из этого можно придумать проверки и подобрать инструменты.
-
Подготовить приложение для тестирования. Как и где будет собираться актуальная версия приложения? Как тест будет получать к нему доступ, совершать действия? Без этого нечего и начинать писать автотесты.
-
Подобрать данные для тестирования. Как много данных нам нужно? Можем ли мы полностью управлять данными на своей стороне? Можем ли мы хранить их на своей стороне? Чем больше контроля и меньше вариативности, тем лучше.
-
Подобрать окружение для тестов. На каких платформах и браузерах предполагается использовать наше приложение? От каких параметров окружения зависит поведение приложения?
И тут с нашим приложением на WebGL мы начинаем спотыкаться буквально на каждом шагу.
Особенности тестирования приложения на WebGL
1. Локализация объектов
Раз мы визуализируем картографические объекты, результат работы приложения — это объекты. То есть мы будем проверять объекты? Поищем в DOM-дереве и убедимся, что объект с соответствующим айдишником создался, правильно? Нет.
Плохая новость в том, что никаких узлов в DOM под каждый объект не создаётся. Поэтому «нарисованный объект» существует в виде пикселей на экране, а в качестве узла в DOM — не существует.
Хорошая новость в том, что проверить «нарисованность» объекта визуально мы всё-таки можем. Для этого нам нужно уметь из теста делать скриншоты, сохранять их локально в виде артефактов (для дальнейших проверок или дебага), уметь сравнивать скриншоты попиксельно.
2. Завершение отрисовки
В тестировании веб-приложений частая боль — это ожидание загрузки каких-то компонентов, изменения состояния, ответа от сервера. Нас это тоже не обошло стороной. Например, мы не можем ретраить запрос (как можно было бы сделать с RESTful API на базе HTTP) или дожидаться появления целевого объекта в DOM’е (потому что WebGL вообще не создаёт для объектов DOM-узлы, см. пункт 1).
В итоге мы создали служебное событие, которое вызывается в приложении после завершения работы всех компонентов, влияющих на внешний вид карты. Дождавшись этого события, можно спокойно делать скриншот.
3. Interactive behaviour
Окей, с уже визуализированными объектами разобрались, но ведь визуализация не статичная! Одно дело — проверить результат взаимодействия («кликнули по объекту — объект поменял цвет»), другое — проверить само взаимодействие. Как, например, проверить, что при клике по объекту его цвет менялся плавно в течение 10ms? Или, что при увеличении зума здания плавно вырастают?

Можно попробовать делать серии скриншотов и сравнивать их, но стабильность такой проверки вызывает сомнения.
4. Отсутствие окружения
Наше приложение — js-библиотека, предоставляющая API для создания в браузере карты, а не полноценный сайт (за это отвечают конечные продуктовые команды).
Если мы собрались тестировать, как карта рисуется на странице браузера, придётся такую страницу создать! То есть нужно захостить html с подключенным кодом нашей библиотеки — по этому адресу тест сможет открыть страницу в браузере и выполнить код (создать карту уже наконец).
5. Зоопарк окружений
Отрисовка происходит на видеокарте устройства, на котором запущен браузер. Новое устройство — потенциально новые особенности отрисовки (или её отсутствие). Скриншот карты, сделанный в Chrome на Linux, может не совпадать со скриншотом на mac. Не говоря уже о том, как сложно будет дебажить локально тест, упавший в CI.
Можно гонять тесты в одном популярном окружении и пропустить баг в менее популярном. Или запихать тесты в docker и игнорировать все особенности операционных систем. Или гонять тесты в нескольких окружениях и поддерживать набор эталонных скриншотов, кратный количеству этих окружений. В итоге нам нужно как минимум выбрать для тестов фреймворк, позволяющий выполнять один и тот же тест в разных браузерах. А в идеале сразу смотреть в сторону инструментов типа browserstack, позволяющих запустить приложение одновременно и в разных браузерах и на разных операционных системах.
6. Слишком актуальные данные
Дефолтный источник данных, на основе которых мы рисуем почти все объекты в карте, — векторные тайлы. Это специальным образом запакованная информация об объектах на конкретном квадрате земли на определенном масштабе. Мы не должны проверять данные, их точностью и корректностью занимаются другие команды. Но мы должны проверять, что на основе одних и тех же данных приложение рисует одну и ту же картинку. Где же нам взять эти данные?
На продакшне данные обновляются минимум раз в день: то появится какой-нибудь новый объект, то пропадёт, то подвинется, то обновится кусочек его геометрии. Все эти изменения совершенно непредсказуемы и тестировать на них с пиксельной точностью было бы сущим адом.
Ещё можно замокать данные. Но мы рисуем на карте так много различных типов объектов, что для них потребуется создать и поддерживать собственный тайловый сервер.
А ещё можно сделать копию определённого сегмента продакшн-данных. Но если всё-таки возникнет потребность обновить эти данные, это будет новая копия. То есть обновятся все данные, и придётся вручную актуализировать все ранее созданные скриншоты.
Что в итоге
Понятно, что без решения половины этих проблем и тестировать нечего. К сожалению, без решения других проблем можно жить довольно долго! Мы, например, спроектировали тесты без учёта кроссбраузерного запуска и гоняли полную регрессию только на одном окружении. И при переходе на WebGL 2.0 пропустили, что его поддержка в Safari до 15 версии (сентябрь 2021) была экспериментальной и включалась отдельным флагом (то есть по умолчанию фичи WebGL 2.0 просто не работали) ?. И это мы ещё не добрались до тестирования перфоманса! Про него должна быть отдельная история.
Если хочется больше технических подробностей и примеров, вы всегда можете обратиться к webglfundamentals.org или, например, к нашему старому туториалу по основам WebGL для разработчиков. Узнать больше про WebGL для визуализации картографических данных можно тут и тут.
И если всё это вам по душе, приходите к нам! Нам очень нужны специалисты, играючи справляющиеся с техническими задачами, будем вас любить и ценить по достоинству.
ссылка на оригинал статьи https://habr.com/ru/articles/721452/
Добавить комментарий