Эта статья ещё не опубликована и не видна поисковым системам.
Визуальное тестирование и lazy loading: как тестировать страницы, которые строятся при скролле

Визуальное тестирование и lazy loading: как тестировать страницы, которые строятся при скролле

Lazy loading — это техника веб-оптимизации, откладывающая загрузку невидимых ресурсов — изображений, видео, компонентов, данных — до момента, когда пользователь прокрутит страницу к зоне их появления, тем самым снижая время начальной загрузки и потребление пропускной способности.

Вот парадокс, который мало какие команды хотят слышать: lazy loading отличен для ваших пользователей и ужасен для ваших визуальных тестов. Это технология, предназначенная для того, чтобы не загружать контент, пока он не станет видимым. Но инструмент визуального тестирования должен видеть контент, чтобы его тестировать. Эти две цели фундаментально противоречат друг другу.

Это противоречие — не причина выбирать одно в ущерб другому. Вашему сайту нужен lazy loading для производительности — данные Google однозначны: время загрузки является фактором ранжирования SEO и основным фактором показателя отказов. А вашему сайту нужны визуальные тесты для гарантии того, что lazy loading не вносит регрессий — placeholder, который никогда не исчезает, изображение, загружающееся с неправильными размерами, layout, который прыгает при появлении контента.

Эта статья объясняет, как примирить оба подхода.

Почему lazy loading усложняет визуальное тестирование

Невидимый контент нельзя тестировать

Фундаментальный принцип lazy loading заключается в том, что контент ниже первого экрана не загружается при начальной загрузке страницы. Скриншот, сделанный сразу после загрузки, показывает только контент выше первого экрана — всё остальное либо отсутствует, либо заменено placeholder'ами.

Это проблема покрытия. Если ваша страница имеет высоту 5 000 пикселей, а ваш viewport — 900 пикселей, начальный скриншот покрывает лишь 18% вашей страницы. Оставшиеся 82% не тестируются. На странице товара интернет-магазина это означает, что описание, отзывы клиентов, рекомендованные товары и подвал никогда не проверяются визуально.

Некоторые команды считают, что решают проблему, делая скриншот full-page. Но скриншот full-page не активирует lazy loading — он захватывает страницу в том виде, в каком она отрендерена в момент захвата, с placeholder'ами и незагруженными элементами. Вы получаете полное изображение неполной страницы.

Момент захвата: постоянная дилемма

Когда именно следует делать скриншот? Вопрос кажется простым. Но это не так.

Если сделать скриншот сразу после загрузки страницы, вы захватываете начальное состояние с placeholder'ами. Это быстро, но неполно. Если прокрутить до конца страницы перед захватом, вы активируете загрузку всего отложенного контента — но к моменту загрузки каждого ресурса контент в верхней части страницы может измениться (анимации, обновления в реальном времени, повторное отображение заголовка).

И кроме того, сам скролл меняет внешний вид страницы. Sticky header, появляющийся при скролле, кнопка «наверх», индикатор прогресса чтения, заполняющийся по мере прокрутки — все эти элементы меняются в зависимости от позиции скролла, и их состояние в момент захвата варьируется от одного прогона к другому.

Placeholders изображений и layout shift

Lazy loading изображений использует placeholder'ы для резервирования места в layout: серые прямоугольники, размытые изображения низкого качества (LQIP — Low Quality Image Placeholder), цветные SVG или просто ничего. Когда фактическое изображение загружается, оно заменяет placeholder.

Проблема возникает, когда замена placeholder'а на изображение меняет размеры элемента. Это печально известный Cumulative Layout Shift (CLS) — видимое смещение, сдвигающее окружающие элементы. CLS напрямую влияет на SEO и показатели Core Web Vitals. Если ваш скриншот сделан во время этого сдвига, вы захватываете переходное состояние, которое не является ни placeholder'ом, ни финальным состоянием.

Лучшие веб-практики рекомендуют задавать явные размеры на изображениях (width и height в HTML), чтобы избежать layout shift. Но не все команды следуют этим практикам, а адаптивные изображения с переменными размерами усложняют ситуацию ещё больше.

Infinite scroll: страница без конца

Infinite scroll доводит проблему lazy loading до крайности. Вместо страницы фиксированного размера с отложенным контентом у вас есть страница, длина которой потенциально бесконечна. Каждый скролл вниз загружает новые элементы и расширяет страницу.

Как визуально тестировать страницу без конца? Невозможно сделать скриншот full-page — у страницы нет «полной» версии. Вы должны произвольно решить, когда прекратить скроллить, сколько элементов составляют достаточную выборку и как обращаться с тем, что контент, загружаемый infinite scroll, часто питается изменяющимися данными (новые статьи, новые посты, новые товары).

Infinite scroll также создаёт проблему памяти. Каждая порция загружаемого контента добавляет элементы в DOM. После достаточного количества скроллов браузер может замедлиться, рендеринг может стать менее плавным, а тайминги операций могут варьироваться — внося недетерминированность в ваши тесты.

Стратегии визуального тестирования lazy-loaded контента

Стратегия 1: инкрементальный скролл с множественными захватами

Вместо того чтобы искать единственный скриншот всей страницы, разделите страницу на сегменты и захватывайте каждый сегмент отдельно. Прокрутите на одну высоту viewport'а, подождите загрузки отложенного контента, сделайте скриншот, затем продолжайте.

Этот подход создаёт серию скриншотов — viewport 1, viewport 2, viewport 3 и т.д. — которые вы сравниваете индивидуально с их соответствующими baseline'ами. Каждый скриншот покрывает определённый сегмент страницы со всем загруженным контентом.

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

Для infinite scroll определите фиксированное количество скроллов (например 5 или 10) и тестируйте соответствующие сегменты. Вы не можете протестировать бесконечность, но можете протестировать репрезентативную выборку.

Стратегия 2: принудительная полная загрузка перед захватом

Некоторые инструменты позволяют отключить lazy loading в тестовой среде. HTML-атрибут loading="eager" принуждает немедленную загрузку всех изображений. Скрипты Intersection Observer можно пропатчить, чтобы считать все элементы немедленно видимыми. Фреймворки вроде React и Vue, реализующие lazy loading на уровне компонентов, можно настроить на загрузку всех компонентов в тестовом режиме.

Этот подход превращает вашу страницу с lazy loading в полностью загруженную страницу, и вы можете сделать классический скриншот full-page. Это просто, прямолинейно и решает проблему покрытия.

Но вы больше не тестируете сам lazy loading. Если в вашей реализации lazy loading есть баг — компонент, который никогда не загружается, placeholder, остающийся отображённым, переходная анимация, ломающая layout — вы не увидите этого в режиме «eager». Вы тестируете контент, а не механизм загрузки.

Это приемлемый компромисс, если ваша цель — исключительно обнаружение визуальных регрессий в дизайне. Если вы также хотите убедиться, что lazy loading работает корректно, вам нужна следующая стратегия.

Стратегия 3: тестирование переходных состояний

Вместо обхода lazy loading, тестируйте его явно. Делайте скриншоты на каждом этапе цикла загрузки: начальное состояние с placeholder'ами, состояние во время загрузки (переходное) и финальное состояние с полным контентом.

Каждое состояние имеет свой baseline. Тестирование начального состояния проверяет, что placeholder'ы правильно размерены и позиционированы. Тестирование финального состояния проверяет, что загруженный контент корректно заменяет placeholder'ы без нарушения layout. Тестирование перехода проверяет отсутствие чрезмерного layout shift.

Этот подход наиболее полный, но и наиболее тяжёлый в поддержании. Три baseline на каждый lazy-loaded компонент означают троекратное увеличение затрат на сопровождение при эволюции дизайна. Резервируйте его для критических компонентов, где поведение lazy loading существенно для пользовательского опыта.

Стратегия 4: структурное сравнение, безразличное к пиксельному содержимому

Структурный подход элегантно решает несколько проблем lazy loading одновременно. Вместо сравнения пикселей placeholder'а с пикселями финального изображения он сравнивает структуру элемента: его позицию в DOM, вычисленные размеры, CSS-свойства и видимость.

Правильно размеренный placeholder занимает то же пространство, что и финальное изображение — структура идентична, даже если пиксели полностью разные. Lazy-loaded компонент, загружающийся корректно, сохраняет ту же позицию и размеры, что и его placeholder. Структурный подход проверяет эту эквивалентность, не заботясь о пиксельном содержимом изображений.

Именно этот подход Delta-QA использует нативно. Когда placeholder размером 400x300 пикселей заменяется изображением 400x300 пикселей, структура не меняется — нет алерта. Когда placeholder 400x300 заменяется изображением 400x200 (баг пропорций), структура меняется — закономерный алерт.

Специфические проблемы infinite scroll

Infinite scroll заслуживает особого внимания, потому что он сочетает проблемы lazy loading с уникальными для себя вызовами.

Проблема повторяемости

Infinite scroll обычно загружает пагинированный контент из API. Контент страницы 2 зависит от того, что на странице 1. Если набор данных меняется между двумя прогонами тестов (опубликована новая статья, удалён товар), страницы не имеют одинакового контента, и сравнение не проходит.

Для получения повторяемых результатов необходимо заморозить базовые данные. Используйте замоканную API, которая всегда возвращает одни и те же данные в одном и том же порядке, или тестируйте против staging-окружения с фиксированным набором данных.

Проблема заголовков группировки по времени

Списки infinite scroll часто отображают контент с заголовками группировки — «Сегодня», «Вчера», «На прошлой неделе». Эти заголовки зависят от текущей даты и меняются ото дня ко дню. Статья, опубликованная «сегодня», завтра окажется под заголовком «Вчера».

Решение то же, что и для любого временного контента: зафиксируйте системную дату в тестовой среде.

Проблема деградации производительности

После 20–30 последовательных скроллов производительность браузера может снизиться из-за количества элементов в DOM. Эта деградация влияет на тайминги рендеринга и может вносить недетерминированность в ваши скриншоты.

Хорошо спроектированные приложения реализуют виртуализацию — они хранят в DOM только текущие видимые элементы, перерабатывая DOM-узлы по мере скролла пользователя. Если ваше приложение виртуализирует DOM, количество элементов остаётся постоянным независимо от числа скроллов, и производительность стабильна.

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

Практические рекомендации по интеграции lazy loading в стратегию визуального тестирования

Для изображений с lazy loading, минимум — тестировать финальное состояние, то есть состояние, в котором все изображения, видимые в viewport'е, загружены. Используйте инкрементальный скролл для активации загрузки, дождитесь стабилизации и сделайте захват. Установите чёткие ожидания: все изображения в viewport'е должны быть загружены (без видимых placeholder'ов), и layout shift не должен происходить после загрузки.

Для lazy-loaded компонентов (code splitting, динамические импорты), тестируйте в двух режимах: режим «всё загружено» для проверки рендеринга компонентов и режим «естественная загрузка» для проверки переходных состояний и fallback'ов.

Для infinite scroll, определите реалистичный объём тестирования. Тестируйте первые 3–5 загрузок (скроллов), что покрывает начальное поведение, логику пагинации и переходы между порциями. Не пытайтесь протестировать весь поток — это ни практично, ни необходимо.

Для placeholder'ов, тестируйте их явно. Placeholder'ы — часть пользовательского опыта — плохо размеренный placeholder вызывает layout shift, отсутствующий placeholder оставляет белый пробел на странице. Сделайте скриншот начального состояния (до скролла) и проверьте, что placeholder'ы правильно размерены и позиционированы.

Для таймингов, предпочтите условные ожидания фиксированным задержкам. Ждите загрузки изображений (через событие load на элементах img), а не ждите произвольное количество секунд. Фиксированные задержки ненадёжны — 2 секунд может хватить локально и не хватить в CI под нагрузкой.

Lazy loading — союзник, а не враг

Lazy loading оптимизирует производительность вашего сайта. Он снижает время начальной загрузки, потребление пропускной способности и использование ресурсов на стороне клиента. Это реальные и измеримые преимущества для ваших пользователей.

Тот факт, что он усложняет визуальное тестирование — не причина отказываться от него, а причина адаптировать вашу стратегию тестирования. И современные инструменты визуального тестирования, в первую очередь Delta-QA, спроектированы для обработки этой сложности, не заставляя вас выбирать между производительностью и тестируемостью.

Lazy loading — не препятствие для визуального тестирования. Это техническое ограничение с техническими решениями. Реализуйте их, и вы получите лучшее из обоих миров: быстрые страницы и надёжные тесты.

FAQ

Делает ли lazy loading визуальное тестирование full-page невозможным?

Нет, но он требует другого подхода по сравнению с классическим скриншотом full-page. Либо вы принуждаете полную загрузку (loading="eager") перед захватом, либо скроллите прогрессивно, захватывая каждый сегмент отдельно. Оба подхода обеспечивают полное покрытие — первый проще, второй более точно отражает фактическое поведение страницы.

Как визуально тестировать страницу с infinite scroll?

Определите реалистичный объём тестирования: 3–5 скроллов покрывают начальное поведение, логику пагинации и переходы между порциями. Используйте замоканные данные для гарантии повторяемости. Захватывайте каждый сегмент как независимый скриншот со своим baseline. Не пытайтесь протестировать бесконечность — тестируйте репрезентативную и надёжную выборку.

Нужно ли отключать lazy loading в тестовой среде?

Это зависит от вашей цели. Если вы тестируете контент (обнаружение визуальных регрессий в дизайне), отключите lazy loading для упрощения захватов. Если вы тестируете механизм загрузки (проверка того, что placeholder'ы, переходы и отложенная загрузка работают), оставьте lazy loading включённым и явно тестируйте различные состояния.

Как справиться с layout shift, вызванным отложенной загрузкой изображений?

Всегда задавайте явные размеры (width и height) на ваших изображениях для резервирования места в layout. Используйте placeholder'ы того же размера, что и финальное изображение (LQIP или цветные прямоугольники). Визуально тестируйте начальное состояние (с placeholder'ами) и финальное состояние (с изображениями), чтобы убедиться, что размеры не меняются и сдвиг не происходит.

Визуальные тесты с lazy loading медленнее классических?

Да, неизбежно. Инкрементальный скролл с ожиданием загрузки на каждом шаге занимает больше времени, чем мгновенный захват полностью загруженной страницы. Это цена полного покрытия. Оптимизируйте за счёт параллелизации тестов, ограничения количества скроллов до строгого минимума и использования условных ожиданий вместо фиксированных задержек для минимизации времени ожидания.

Справляется ли Delta-QA с lazy loading и infinite scroll?

Да. Структурный подход Delta-QA особенно хорошо подходит для lazy loading, потому что он сравнивает структуру, а не пиксели. Правильно размеренный placeholder и финальное изображение имеют одинаковую структуру — нет ложного срабатывания. Инструмент обрабатывает инкрементальный скролл, ожидание загрузки и сравнение сегментов — всё без написания единой строки кода.


Для углубления


Lazy loading оптимизирует производительность вашего сайта. Delta-QA гарантирует, что он не вносит визуальных регрессий. Два подхода не противоречат друг другу — они дополняют друг друга. Тестируйте ваши динамические страницы с той же строгостью, что и статические.

Попробовать Delta-QA бесплатно →