Модульное тестирование графического дизайна HTML&CSS

MVH

Новичок
При разработке системы динамической генерации баннеров столкнулся с необходимостью проверки соответствия генерируемого HTML и CSS эталонной картинке.

Система такая: пользователь задаёт текст, картинку, расположение картинки относительно текста и т.п. (подобных параметров и их комбинаций много). Затем PHP на основе этих данных генерирует соответствующий HTML и CSS и выводит результат.

Соответственно было бы очень удобно для каждой такой комбинации параметров написать тест, который бы проверял, соответствует ли итоговый результат (отображение в различных браузерах) ожидаемому (эталонной картинке), т.к. в данном случае важен именно графический вид и одной лишь проверкой генерируемого HTML и CSS не обойтись.

В моём представлении подобное тестирование может работать следующим образом:
— существует метода утверждения (например, в phpUnit), вроде
PHP:
assertImageEqualHtml('expected.png', '<div style="...">...</div>')
— данный метод генерирует картинку на основе HTML и CSS кода, используя движки различных браузеров (тупо загружая HTML код в браузер и делая скриншот);

— ну и затем происходит сравнение полученной в каждом браузере картинки с expected.pnd, с учётом допустимый расхождений: отличий в шрифтах и незначительных сдвигов (плюс/минус 1-2px) элементов.


Никто не встречал инструмент для подобного рода тестирований?
 

Mols

Новичок
Хрена се...
И как блин на скриншоте (он сам по себе картинка). Понять где в HTML была картинка, а где текст?
На вставленной картинке тоже может быть произвольный текст. И цвет фона может совпадать с фоном страницы указанным в стилях.
Так что врядли такой инструмент (за исключением специально обученных людей :) ) может существовать.
 

HraKK

Мудак
Команда форума
Нету, но написать можно и он реально будет прикольным.
 

fixxxer

К.О.
Партнер клуба
ну с картинкой это нереально :) рендеринг штука системнозависимая. разве что запариваться с нечеткой логикой, ну тут флаг в руки так сказать =)

а всякие edge cases типа оффсетов вполне можно проверить селениумом, только замучаешься правила писать
 

HraKK

Мудак
Команда форума
fixxxer
селениум тут мало поможет, а вот нейросеть - идеально. Но да, тут нетривиальная логика и я сомневаюсь что кто то такое сделает
 

MVH

Новичок
И как блин на скриншоте (он сам по себе картинка). Понять где в HTML была картинка, а где текст?
По идее, есть 2 варианта (оба исходят из того, что в браузере выравнивание задано по левому краю, но это тоже можно определять по идее первым методом):
1. Задать цвет фона и от правого нижнего угла начинать поиск пиксела, который отличается от фона. И изображением считать квадрат от левого верхнего угла до этой точки.
2. Взять за послулат, что выравнивание происходит по левому верхнему краю и обрезать квадрат от левого верхнего края, который по размеру равен expected.png. Можно в дополнение использовать первый метод, что бы определить, не вылазит ли ничего лишнего за этот квадрат.

На вставленной картинке тоже может быть произвольный текст.
Ну это не проблема. Для тестирования (собственно как и при любом тестировании) будут готовиться картинки с заранее определённым тестом и с таким же текстом будет генерироваться HTML.

И цвет фона может совпадать с фоном страницы указанным в стилях.
Это не существенное ограничение. Можно индивидуально подобрать цвет фона для тестирования такой, которого нет в expected.png.

Так что врядли такой инструмент (за исключением специально обученных людей :) ) может существовать.
Лично мне видится лишь проблема обработки различных отображений в браузерах (в основном насыщенности шрифтов). Но и тут можно подготовить картинки expected.png для всех браузеров индивидуально. По любому ручного труда будет меньше (точнее он будет происходить единожны, при дальнейшей модификации системы уже не надо будет вручную проверять ранее созданные картинки).
 

MVH

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

fixxxer

К.О.
Партнер клуба
ну разве что такое в голову приходит

1) делаем скриншот правильной верстки (именно скриншот, потому что макет это макет и там всегда немножко не так - хотя любители верстки пиксель-в-пиксель могут и с макетом попробовать)
2) на скриншоте помещаем специальные уникальные позиционные маркеры по углам
3) их же вставляем в тестируемую верстку
4) зная примерный размер, подгоняем размер окна по оффсетам в рамках +- 10 пикселей (точно все равно не получится заранее сделать)
5) делаем скриншот того что есть
6) вычисляем difference, совмещая картинки по маркерам (тут еще можно прогнать фильтром, чтобы убрать "артефакты" антиалиасинга)
7) считаем в диффе "ненулевые" пиксели, если их больше заданного threshold тест не пройден
 

MVH

Новичок
6) вычисляем difference, совмещая картинки по маркерам (тут еще можно прогнать фильтром, чтобы убрать "артефакты" антиалиасинга)
Вот это самое проблемное место. В идеале хотелось бы добиться того, что бы порог (threshold) распространялся только на текст, а не на картинки (что бы можно было не обращать внимания на антиалиасинг браузеров, но в то же время отловить небольшой сдвиг картинки, т.к. дизайн может требовать попиксельной состыковки (например, состыковка линий, отклонение которой на 1 px будет очень заметна)). Но Ваша идея с маркерами как раз кстатии, только с помощью них мы будет отмечать не квадрат области скриншота, а текстовые области. Т.е. подготавливаем картинку, затем на ней (или на другой картинке, которые будут совмещаться, либо сделать спрайт, либо вообще в текстовом файле координаты прописать) специальным цветом обводим текстовые области, на которые и будет распространяться threshold.

Всё сейчас упирается в простом способе получения скриншотов в браузерах. Надо будет поискать готовое решение. Может кто знает такое?
 

fixxxer

К.О.
Партнер клуба
Для фаерфокса точно есть плагины, там сорцы можно посмотреть. Для ие что-то вроде тоже было но не факт что ими получится управлять программно
 

whirlwind

TDD infected, paranoid
Всё сейчас упирается в простом способе получения скриншотов в браузерах. Надо будет поискать готовое решение. Может кто знает такое?
winapi: GetDC(NULL), BitBlt()


PS. тока по моему бредовая это затея. Мало того, чтонужно формализовать постановку теста, так еще надо формализовать результат. Что касается анализа образов, я думаю тут как unit-е не выйдет - фреймворки для модульного тестирования разговаривают с программистом и кодом на одном языке. Здесь же и постановку и результат нужно выводить используя графику. Иначе для дизайнера/версталы будет ад постановки/интерпретации.
 

MVH

Новичок
PS. тока по моему бредовая это затея. Мало того, чтонужно формализовать постановку теста, так еще надо формализовать результат. Что касается анализа образов, я думаю тут как unit-е не выйдет - фреймворки для модульного тестирования разговаривают с программистом и кодом на одном языке. Здесь же и постановку и результат нужно выводить используя графику. Иначе для дизайнера/версталы будет ад постановки/интерпретации.
Мне сейчас это представляется уже по другому:
Тесты создаются и обрабатываются вообще сторонними программами (не имеющими никакого отношения к PHP) и имеют следующую файловую структуру:
Код:
tests/
	test1.png
	test1.xml

	test2.xml
Настройки тестов храняться в XML файлах (по сути, каждый XML файл аналог тестового метода в PHPUnit)
Пример test1.xml:
Код:
<test>
	<expectedURL type="image">test1.png</actualURL>
	<actualURL>http://localhost/test1.html</actualURL>
	<areas>
		<area type="text" form="rect" coords="10,10,60,60" />
		<area type="exclude" form="rect" coords="0,0,10,10" />
	</areas>
</test>
Пример test2.xml:
Код:
<test>
	<expectedURL type="html" browser="c:/firefox.exe">http://localhost/test1.html</actualURL>
	<actualURL>http://localhost/test1.html</actualURL>
	<areas>...</areas>
</test>
Существует несколько программных модулей (по видимому, которые лучше будет написать на Java):
1. Программа для получения скриншотов в браузере (BrowserSnapshot)
2. Интерфейс для создания тестов (TestCreator)
3. Программа для исполнения теста (TestExecuter)
4. Программа для запуска тестов (TestRunner)

--BrowserSnapshot
На вход получает путь к браузеру (к исполняемому файлу) и URL адрес для загрузки. Программа открывает указанный браузер, загружает в него указанный URL и делает скриншот (который и возвращает вызывающей программе).

--TestCreator
Интерфейс для создания тестов (с помощью него формируются XML файлы). Форма интерфейса содержит элементы для обеспечения следующего функционала:
1. добавление картинки-образца (загрузка с локального компьютера или автоматическое получение прямо перед тестированием скриншота указанной страницы из браузера посредством BrowserSnapshot). Значение этого элемента хранится в XML файле в теге <expectedURL>.
2. нанесение на картинку прямоугольных областей двух типов (значение этого элемента хранится в XML файле в теге <areas>):
a) область исключения (сравнение этих областей не производится при тестировании)
b) область текста (сравнение этих областей происходит с использованием не строгого сравнения, этот тип, видимо, не обязательный, см. конец поста)

3. actualURL - URL адрес страницы, с которой надо будет сравнение производить, хранится в <actualURL>


--TestExecuter
На вход получает:
1. expectedImage (картинка-образец, берётся из <expectedURL>)
2. expectedImageMarking (разметка картинки, где отмечены области исключения и текстовые области, берётся из тега <areas>)
2. actualURL (адрес для загрузки в браузер, содержаний HTML код для сравнения с expectedImage)
3. browsersList (список браузеров, в которых следует выполнять тесты)

При запуске программа циклично запускает по очереди все указанные браузеры, выполняя для каждого следующие действия:
1. загружает страницу actualURL
2. получает скриншот страницы
3. производит анализ (сравнение) полученного скриншота с expectedImage, используя expectedImageMarking
4. Возвращает результат сравнения: thresholdOverload (превышение допустимого порога расхождений в процентах) и diffAreas (список областей (координаты квадратов), в которых произошло расхождение)


--TestRunner
Считывает все тесты из папки tests и для каждого выполняет алгоритм, описанный в TestExecuter.
Результат отображается следующим образом: если thresholdOverload превышает установленное значение, то выводится сообщение о том, что тест в таком то браузере не прошёл и показывается скриншот страницы actualURL, где красными прямоугольниками выделяются области diffAreas - что бы пользователь понял где то не так.


Т.е. подобная тестовая среда будет самостоятельная (не будет завязана на PHPUnit). А что бы это дело связать с PHP достаточно будет создать PHP страницу, которая будет генерировать нужный HTML для тестов по запросу (и эти URL'ы и надо будет прописать в XML файлах).

А если реализовать автоматическое определение областей текста, то можно будет подобную систему натравить на сайт (указав в качестве образца нужный браузер) и получить результат сравнение всех страниц в различных браузерах. Т.е. можно будет в одном браузере проверить визуальный вид сайта в ручную, а в остальных браузерах выполнить проверку автоматически.

Автоматическую определение текста, кстатии, можно довольно легко будет реализовать: достаточно в CSS задать для текста цвет-образец через !important и весь тест на сайте будет одного цвета. Таким образом можно будет отделить текст от остальной части картинки. Притом перед выбором цвета образца можно сделать скриншот сайта и выбрать в качестве цвета образца тот, который не присутствует на скриншоте. Можно так же несколько раз с различными цветами прогнать.

P.S.: мне всё это нужно как человеку, которого ужасно утомляет каждый раз после вёрстки вручную проверять результат как минимум в 8 браузерах (к тому же небольшое изменение может затронуть множество комбинаций результатов, как в моём примере с баннерной системой). Плюс, на мой взгляд, было бы просто здорово так же проверить сайт во всех минорных версиях браузеров (ff3.3, ff3.4, ff 3.5 и т.п.) в различных ОС.
 

whirlwind

TDD infected, paranoid
MVH не, ну идея то здравая. Тока ты учти один момент который есть при любом тестировании. Это необходимость поддерживать тесты в актуальном состоянии. Будет ли оно оправдано, сидеть втыкать в разработку тестов, что бы один раз проверить верстку отдельной страницы? Это же не код, тут связанности компонентов вроде нету.
 

MVH

Новичок
whirlwind. Мне видится две стороны такой системы:
1. Использование её в качестве модульного тестирования (например, для моего случая - тестирования баннеров).
2. Использовать её для сравнения визуального представление страниц сайта в разных браузерах с одним браузером. Вот тут как раз и никаких тестов вообще писать не придётся. Просто выбирается основной браузер, в котором в ручную тестируется визуальный вид сайта, а затем на автомате прогоняется сравнение скриншотов всех страниц сайта в этом браузере со скриншотами соответствующих страниц в других браузерах. Вот этот функционал меня больше всего и привлекает. Представьте только, вместо того, что бы тестировать сайт вручную во всех (как минимум в 6) браузерах, надо будет протестировать только в одном.
 

whirlwind

TDD infected, paranoid
Ну вот насчет 2 пункта в топике пока не вижу даже приблизительной формулировки теста. С нейросетью хороший фариант, но он тут только на этапе идеи.
 

MVH

Новичок
whirlwind, по поводу связи с тестами: возможно, что бы производить сравнение скриншотов потребуется настроить тестовое окружение. Ведь некоторые страницы сайта могут динамически генерировать содержимое и тогда скриншот, сделанный в одном браузере в один момент времени будет отличаться от скриншота, сделанного в другом браузере в другой момент времени. Соответственно моет понадобиться вызывать такие страницы со спец. параметрами, отменяющими случайную генерацию контента. Т.е. тесты подобные будут выглядеть примерно так:
Код:
<test>
	<expectedURL type="HTML">http://localhost/test1.html?no_dynamic</actualURL>
	<actualURL>http://localhost/test1.html?no_dynamic</actualURL>
</test>
Т.е. как бы тестовые случаи будут автоматом генерироваться. Т.е. можно это назвать автоматическими тестами.
 

MVH

Новичок
По поводу нейронной сети: Вы, как я понимаю, предлагаете применять её для определения несоответствий текста? Думаю, даже если ограничиться простым исключением сравнения текстовых областей, уже будет толк от такой системы.
 

tz-lom

Продвинутый новичок
whirlwind
я далеко не спец по нейросетям,но сможет ли она вносить некоторые поправки в процедуру сравнения?
допустим 4 блока друг под другом и в "друге всех верстальщиков" они на пиксель выше
первый так и будет на своём месте,второй съехал на пиксель вниз(пускай допустимая погрешность) ,чётвёртый съехал уже на 3 пикселя и это плохо,хотя на самом деле считаем что вроде как всё хорошо
вопрос в том можно ли такое на нейросетях сделать (нужно ли - другой вопрос и его я не задаю)?
MVH
подумайте над следующими моментами:
1-иногда стоит требование "вот эта хрень - напротив этой"
2-возможно следует снапшотить не саму страницу,а допустим выкрашивать блоки в свои цвета и сравнивать уже картинки с цветными прямоугольниками?
 

whirlwind

TDD infected, paranoid
tz-lom как раз нейросеть и подойдет для распознования образов. А что там текст или блоки, уже вопрос реализации.
 

MVH

Новичок
Мне кажется, что если привести сайт перед тестированием в однообразное состояние (касается элементов форм и line-height), то можно обойтись без сложных алгоритмов анализа на основе нейронных сетей. Сейчас я как раз провожу анализ таких отличий.
 
Сверху