Пікселестабільні фіксації
Детерміноване рендерування з очікуванням шрифтів, зафіксованими анімаціями та маскуванням динамічного контенту — diff’и відображають справжні регресії, а не шум.
ScanU — платформа тестів візуальної регресії та cross-browser-скріншотів для професійних вебкоманд. Вона знімає точні по-пікселю рендери кожної важливої сторінки, у браузерах та viewport’ах, якими ваші користувачі справді користуються, і висвітлює зміни верстки, які юніт- та end-to-end-тести пропускають у тиші.
Що таке ScanU
ScanU перетворює останню милю якості релізу — саме те, що бачать ваші користувачі, — на сигнал, на який команда може реагувати. Платформа робить пікселестабільні скріншоти обраних вами сторінок, фіксує явний baseline, і кожний наступний запуск порівнюється з цим baseline — у браузерах і на пристроях, які мають значення.
Більшість команд уже мають лінтери, перевірки типів, юніт- тести та end-to-end-потоки. Усе це може лишатися зеленим, поки кнопка з’їжджає на дванадцять пікселів, у модалки зникає padding, меню ламається в Safari, а мобільний breakpoint тихо пересуває весь hero. Функціональні тести перевіряють поведінку; вони не перевіряють як виглядає сторінка. Саме для цього потрібен інструмент screenshot testing — і саме це ScanU і робить, без зайвих церемоній.
Під капотом ScanU керує справжніми рендер-рушіями — Chromium, Gecko та WebKit — проти URL або прев’ю компонентів, які ви вказуєте. Кожен запуск дає детерміновану фіксацію для кожної сконфігурованої пари (браузер, viewport). Перший прийнятий запуск стає baseline. Від цього моменту кожен pull request, кожен деплой, кожна запланована перевірка — це diff проти того baseline: будь-яка візуальна регресія показується як зміна, яку треба оглянути, так само як code review висвітлює змінений рядок.
Повний пайплайн порівняння дбає про деталі, які роблять diffing скріншотів реально придатним у продакшні: толерантність до anti-aliasing, стабілізація анімацій, завантаження шрифтів, маскування динамічного контенту, прокрутка під час захоплення та перцептивні пороги diff — щоб зміна хінтингу на суб-пікселі не забивала справжню регресію верстки.
ScanU створено для команд, що трактують UI як контракт зі своїми користувачами. Це інструмент тестів візуальної регресії, інструмент cross-browser-порівнянь скріншотів та поверхня огляду diff’ів — в одній платформі — між вашим build’ом і release gate.
Детерміноване рендерування з очікуванням шрифтів, зафіксованими анімаціями та маскуванням динамічного контенту — diff’и відображають справжні регресії, а не шум.
Chromium, Gecko і WebKit паралельно, у desktop-, tablet- і mobile-viewport’ах, якими ваші користувачі справді користуються.
Baseline, поточна фіксація і підсвічений diff поруч. Прийняти, відхилити або оновити baseline — завжди явною дією, ніколи в тиші.
Працює у вашому існуючому пайплайні. Status check’и, коментарі pull request і посилання на артефакти з’являються там, де ваші інженери вже роблять code review.
Наведіть ScanU на Storybook, sandbox компонентів або живі URL. Зміни токенів і рефакторинги компонентів отримують чесний візуальний аудит ще до релізу.
Скріншоти й метадані зберігаються на європейській інфраструктурі з обробкою даних відповідно до GDPR — придатно для команд із суворими вимогами до локалізації даних.
Чому це важливо
Вартість візуального бага рідко вимірюється в годинах розробки. Вона вимірюється в довірі користувача, який відкриває ваш продукт, бачить щось тонко не так і тихо вирішує, що ця команда не ставиться до деталей уважно. Відновити таку довіру складно — і майже завжди дешевше запобігти багові.
Функціональні тести добре відповідають на одне питання: «чи робить кнопка те, що треба, при кліку?». Вони мовчать про все, що відбувається до кліку — чи правильного кнопка кольору, правильного розміру, чи там, де має бути, чи читабельна на екрані 360 пікселів, чи взагалі видима після останнього рефакторингу CSS. Саме в цій прогалині живе більшість інцидентів дня релізу.
Реальні регресії, які ми бачимо і заради ловлі яких ScanU і створений, групуються навколо жменьки передбачуваних тригерів:
gap flex-контейнера на одному breakpoint. На desktop верстка виглядає ідентично; на планшеті 768 пікселів дві картки тепер накладаються.Жодна з цих змін не зробить асершен червоним. Усі вони ламають досвід користувача. Завдання ScanU — зробити цей другий клас поломок так само легким для помічання, огляду та блокування, як червоний юніт-тест. Коли diff з’являється на pull request, дизайнерка може висловитися так само, як reviewer висловлюється щодо сигнатури функції — до merge, а не після потрапляння у продакшн.
Цей перехід — від «сподіваємося, хтось помітить на staging» до «оглядаємо візуальну зміну так само, як оглядаємо зміну коду» — і є основною цінністю інструменту візуальної регресії у сучасному релізному пайплайні.
Тести cross-browser
Cross-browser-тестування — не ностальгійний податок часів IE6. Сучасні рушії — Chromium, Gecko та WebKit — досі розходяться в деталях, від яких тихо залежать ваші верстки, і вражаюча кількість продакшн-інцидентів зводиться до різниці в рендерингу, яку ніхто не перевірив.
Якщо регресія з’являється лише в одному рушії, це майже завжди означає одне з трьох: було використано фічу, яка в певних рушіях виходить пізніше, ніж в інших; верстка залежить від метрики, що відрізняється за платформою (ширина scrollbar, baseline шрифта, алгоритм згладжування); або polyfill, що спирається на user-agent, у полі поводиться трохи інакше, ніж на машині розробника. Усі три — невидимі для тестів, агностичних щодо рушія.
Типові приклади з cross-browser-аудитів:
date, datetime-local, select — рендеряться у WebKit з помітно іншим chrome, ніж у Chromium, інколи зсуваючи сусідні елементи на кілька пікселів.line-height, що тримається у Chromium, у Gecko може виштовхнути CTA під лінію згину.gap у flex-контейнерах, aspect-ratio та container queries прибували до рушіїв у трохи різні моменти. Якщо ваш build націлений на старішу baseline, fallback-шляхи можуть рендеритися інакше, ніж основний шлях.prefers-color-scheme, accent-color та forced-colors у Windows — потрапляють у DOM по-різному на різних платформах і легко випадають з уваги в локальному dev- середовищі.ScanU фіксує кожну сторінку в сконфігурованих рушіях та viewport’ах за один запуск, з ідентичними fixture і timing hook’ами, тому diff’и, які ви бачите, — це реальні відмінності верстки, а не побічний ефект того, що кожен браузер біжить в іншому harness. Повні можливості cross-browser описано на сторінці продукту: матриця, яку ви налаштовуєте, і є тією матрицею, що фіксується в кожному запуску.
Для команд, що випускають design system, і будь-якого продукту, чия візуальна ідентичність — частина бренду, ця матриця не є бонусом. Це єдиний спосіб знати, що те, що ваш клієнт бачить у Safari, відповідає тому, що ви затвердили у Chrome.
| Браузер | Viewport | Статус |
|---|---|---|
| Chromium 124 | 1440 × 900 | Відповідає baseline |
| Firefox 126 | 1440 × 900 | Відповідає baseline |
| WebKit (Safari 17) | 1440 × 900 | Візуальний diff · до огляду |
| Chromium 124 | 768 × 1024 | Відповідає baseline |
| WebKit (Safari 17) | 768 × 1024 | Виявлено зсув верстки |
| Chromium 124 | 390 × 844 | Нова baseline очікує |
Як працює порівняння
Інструмент візуального diff корисний настільки, наскільки високий співвідношення сигнал/шум у diff’ах, які він видає. Пайплайн фіксації ScanU зроблений так, щоб між двома запусками мінялося лише те, що ви справді змінили, — а не декорація навколо зі шрифтів, анімацій, таймстемпів чи рекламних слотів.
Кожен запуск — пайплайн із трьох кроків. Спочатку ScanU у кожному рушії переходить на сторінку або компонент під тестом, чекає на сконфігурований набір сигналів готовності — завантажені шрифти, декодовані зображення, тиха мережа, атрибут data-ready або користувацька JavaScript-проба — і пінить усі CSS-анімації на фінальному кадрі. Далі він фіксує сторінку на кожному сконфігурованому viewport у цьому ж запуску, зі scroll-stitching для довгих сторінок, щоб ви отримали повний артефакт, а не лише видиму частину. Нарешті порівнює фіксацію з прийнятим baseline і видає результат для кожної пари (браузер, viewport): ідентично, у межах толерантності або суттєво відмінно.
Саме порівняння — не наївний piksel-diff. ScanU застосовує перцептивну модель, що розуміє anti-aliasing, суб- пікселевий рендеринг і невеликі зсуви кольорового простору, щоб особливість кернінгу в WebKit не видавалася за баг. Також підтримуються явні маски для зон, про які ви знаєте, що вони змінюються при кожному завантаженні, — live-дані, відносні таймстемпи, випадковий контент, каруселі — так що ці ділянки додають нуль шуму до diff.
Коли з’являється справжня зміна, платформа показує три синхронізовані панелі: baseline, поточну фіксацію і diff- overlay, який точно підсвічує, що зрушило. Для кожної зміни записується одне оглядоване рішення — прийняти, відхилити або оновити baseline — і це рішення стає частиною історії проєкту. Жодного тихого дрейфу і жодного автоматичного прийняття: baseline рухається тільки тоді, коли авторизована людина прямо про це каже.
Той самий пайплайн можна запускати з трьох точок входу: проти живих URL (продакшн, staging, прев’ю PR), проти статичного сайту або зібраного бандла ассетів, або проти прев’ю компонентів у sandbox у стилі Storybook. Більшість команд користуються першим шляхом як release gate, другим — для артефактів деплоя, третім — для роботи над design system; усі три живлять те саме сховище baseline.
Останній прийнятий рендер для цієї сторінки, браузера та viewport. Заморожений, поки reviewer його явно не оновить.
Фіксація з цього запуску. Ті самі fixture, ті самі timing hook’и, той самий viewport — змінено лише код під тестом.
Бурштинові підсвічені ділянки показують, де поточний рендер відхиляється від baseline понад сконфігуровану толерантність.
Для кого ScanU
ScanU зроблений для команд, чию роботу оцінюють за тим, що бачить користувач. Це ширша група, ніж здається, — не лише дизайнерки й frontend-інженери, а будь-хто, чиї релізні рішення залежать від того, щоб UI був коректним у певному браузері, на певному viewport, у певний день.
Frontend- і full-stack-інженери використовують ScanU як останній етап пайплайну pull request: build зелений, юніт-тести проходять, end-to-end-набір задоволений — і візуальний diff або підтверджує, що зміна відповідає тому, що очікувала дизайнерка, або висвітлює регресію, яку ніхто не виловив би, читаючи патч. Результат: менше часу на гасіння пожеж після релізу і більше — на роботу, що реально рухає продукт.
QA-інженери отримують рівень тестів, що масштабується без переписування селекторів. Додати сторінку до візуального набору — це URL і baseline, а не тиждень крихкого XPath. Шар, який ловить UI-регресії, стає повноцінним членом піраміди тестів, а не post-factum- повідомленням у Slack від користувача.
Команди design system і платформні команди запускають ScanU проти кожного sandbox компонента своєї бібліотеки. Коли змінюється токен, кожен залежний компонент автоматично отримує візуальний аудит. Коли компонент рефакториться, нижні споживачі отримують diff, який можна оглянути ще до релізу нової версії. Саме так design system уникає накопичення тихих регресій роками.
Продуктові та інженерні керівники використовують поверхню огляду як доказ. Release notes можуть містити посилання на прийнятий візуальний diff для кожного релізу. Post-mortem можуть фіксувати, чи регресія була вловлена, пропущена чи явно прийнята. Згодом платформа перетворюється на літопис того, як UI еволюціонував і хто затверджував кожен крок.
Сценарії використання
Та сама платформа обслуговує дуже різні робочі процеси. Спільна нитка: кожна з цих команд випускає UI у ритмі, який важливий для їхніх клієнтів, і кожній потрібно знати — з одного погляду — чи UI виглядає так, як має.
Якою б не була форма команди, ScanU зазвичай впроваджують із однієї з п’яти причин: нещодавній продакшн-інцидент, який візуальна регресія вловила б; міграція design system, обсяг впливу якої неможливо оглянути вручну; CI/CD-процес, що потребує release gate, багатшого за «тести зелені»; клієнтський deliverable, що вимагає доказу «до/після»; або compliance-позиція, яка надає перевагу тестовому інструменту з хостингом у ЄС. За всіма п’ятьма стоїть спільна CI/CD-інтеграція — той самий пайплайн виконує роботу, чи тригером є PR, merge чи нічний розклад.
Щотижня передавайте клієнтам візуальну дельту за сайтом. Докази «до/після» кожного спринту, на кожному браузері з контракту — в одному звіті.
Додайте візуальний рівень до піраміди тестів. Нові сторінки потрапляють у набір через URL і baseline — без крихких селекторів і саморобних screenshot-скриптів для підтримки.
Diff’и скріншотів з’являються прямо на pull request. Регресії верстки ловляться в огляді, а не в продакшні й не у Slack-треді від клієнта.
Рухатися швидко, не ламаючи головну. Детерміністична страхувальна сітка, що тримає маркетинговий сайт пікселестабільним крізь редизайни, A/B-тести й міграції токенів.
Візуальне покриття на кожному sandbox компонента. Зміни токенів, заміни тем і рефакторинги компонентів автоматично отримують аудит ще до публікації бібліотеки.
Валідуйте breakpoint’и для mobile, tablet і desktop в одному запуску. Responsive-тестування перестає бути рутиною зі зняття скріншотів і стає етапом огляду.
CI/CD та впевненість у релізі
Впевненість у релізі — не відчуття. Це пайплайн, що каже правду про те, що зараз вирушає в продакшн, — включно з частинами, до яких у вашого test runner немає думки. ScanU підключається до цього пайплайну як status check, коментар PR і збережений артефакт, на який можна послатися з будь-якого post-mortem.
Модель інтеграції навмисно нудна: крок фіксації ScanU працює у тому самому job, що вже запускає ваші тести; він повідомляє pass, review-needed або fail на PR; і цей статус обробляється так само, як будь-який інший обов’язковий check. Команди й так уміють читати зелений, жовтий і червоний у пайплайні — check візуальної регресії, вплетений у цей ритм, додає новий вимір безпеки, не вимагаючи нової ментальної моделі.
Під капотом ScanU спроєктований під реалії сучасного CI/CD:
Покроковий гайд з інтеграції CI/CD описує конкретну обв’язку для GitHub Actions, GitLab CI, Bitbucket Pipelines та self-hosted runner’ів. Звичайний випадок — один додатковий job; складніший — матриця середовищ, що просуває baseline крізь поетапний реліз.
GDPR · Хостинг у ЄС · Конфіденційність
Тестові артефакти — це дані. Скріншоти можуть випадково зафіксувати персональні дані, які опинилися на сторінці, — ім’я в навігаційній панелі, e-mail у меню профілю, номер замовлення на екрані підтвердження. Відповідальна платформа візуальних тестів ставиться до цих артефактів з тією ж дбайливістю, що й до продакшн-даних, які вони відображають.
ScanU будується і хоститься в Європейському Союзі — зі зберіганням і обробкою на інфраструктурі, що оперується в ЄС. Для команд із зобов’язаннями щодо локалізації даних — регульованих галузей, державних замовників, чутливих до приватності B2B-клієнтів — це часто закупівельна вимога, а не уподобання. ScanU зроблений так, щоб задовольняти цю вимогу без компромісів у можливостях продукту.
Із цієї позиції випливає кілька свідомих рішень дизайну:
Повну позицію щодо приватності — суб-обробники, регіональний хостинг, DPA, вікна ретенції — описано у документації з GDPR і обробки даних. Для більшості команд важлива коротка версія: ваші скріншоти лишаються в ЄС, а платформа спроєктована так, щоб вони там і залишалися.
Відмінність
Visual testing — переповнена категорія. Значна частина того, чим ScanU вирізняється, — це речі, які він відмовляється робити: зрізи, які не дозволяє собі; шум, який не пропихає у вашу чергу огляду; і думки, що він має про те, як треба оглядати diff.
Універсальні screenshot-інструменти зазвичай постачають бібліотеку, яку ви приклеюєте до test runner, і далі вам доводиться боротися з timing, шрифтами, анімаціями та вічним питанням: зсув на один піксель — це справжній баг чи артефакт округлення. ScanU займає твердішу позицію: якщо платформа не може дати детерміновану фіксацію — це проблема платформи, а не ваша. Тому сигнали готовності, font loading, animation pinning, scroll stitching, перцептивний diffing і масковані зони вбудовані, а не доклеєні.
Ціноутворення слідує тій самій логіці. Для розумної команди — кілька десятків сторінок, три рушії, три viewport’и, один пайплайн — вартість візуального покриття не має бути рядком, який треба захищати на бюджетній зустрічі. Повна сторінка цін написана зрозумілими числами: що ви отримуєте на кожному тарифі, що рахується як run і де знаходиться стеля. Жодних персональних квот для команд, які просто хочуть випустити інтерфейс, який вони спроєктували.
Стабілізація, готовність шрифтів, animation pinning і scroll stitching — це функції платформи, а не сніпети, які ви підтримуєте у своєму репозиторії.
Двигун diff розуміє anti-aliasing і суб-пікселевий рендеринг — невидимі мікрозсуви не заглушують регресії, які справді мають значення.
Baseline рухається лише тоді, коли авторизована людина приймає зміну. Кожне оновлення піддається аудиту. Жодного тихого дрейфу.
Скріншоти, метадані й історія огляду живуть на інфраструктурі ЄС. Жодного opt-in для команд, що мусять триматися такої позиції.
Що ловить ScanU
Більшість багів, які ловить платформа візуальної регресії, не екзотичні. Це малі, недраматичні, легко не помічувані поломки, що прослизають повз reviewer’ів, бо жодна асершен туди не дивиться. Нижче — вибірка категорій, для висвітлення яких ScanU власне і збудований.
Візуальні баги збираються в жменьку повторюваних шаблонів. У відриві кожен здається тривіальним; кожен може долетіти до продакшну без жодного червоного тесту. Усі вони з’являються як diff у наступному запуску ScanU — ще до того, як PR помержать.
backdrop-filter. У Safari панель навігації раптом стає непрозорою там, де раніше робила blur.text-wrap: balance, виглядає чітко в Chrome, але лишається незбалансованим у рушіях, де ця фіча ще не вийшла. Без cross-browser- перевірки на машині розробника це невидимо.Огляд функцій детально описує примітиви виявлення — перцептивні толерантності, масковані зони, scroll-фіксацію, branching baseline — і показує, який примітив відповідає якій із категорій вище. Для більшості команд коротка версія така: якщо щось змінюється візуально, ScanU це помітить; якщо це очікувано — приймаєте одним кліком; якщо ні — ви вловили це раніше за всіх.
FAQ
Наступні кроки
Найшвидший спосіб зрозуміти, чи потрібні тести візуальної регресії у вашому пайплайні, — запустити їх один раз на проєкті, який ви вже випускаєте. ScanU можна почати безкоштовно, підключити до існуючого CI-job за кілька хвилин, а перший diff він видає на наступному коміті.
Більшість команд починають з однієї сторінки з високим трафіком на трьох браузерах і трьох viewport’ах. Цього досить, щоб побачити платформу в роботі, і цього досить, щоб вловити наступну справжню регресію, яку нинішній набір тестів пропустив би.
Звідти обсяг зростає з упевненістю команди: більше сторінок, більше breakpoint’ів, покриття на рівні компонентів для design system, обов’язковий status check на кожному pull request. Жодного дзвінка для знайомства, жодного індивідуального onboarding, жодних мінімальних зобов’язань.