Pull to refresh

TDD for Responsive Design. Или как автоматизировать тестирование отображения сайта для разных устройств с помощью Galen Framework

Reading time11 min
Views19K
Трудно одним заголовком сформулировать, чем же является Galen Framework. Все началось с того, что у меня возникла потребность тестировать сайты в различных браузерах и проверять: не поехала ли разметка, например, в том же Internet Explore или Chrome. Затем возникла мода на Responsive Web-Design, и пришлось вручную менять ширину браузера и проверять, как отображаются сайты. И, хотя все это время были WebDriver и Selenium Grid под рукой, так и не получалось нормально тестировать верстку сайта в Java коде. Одна из идей была: делать скриншоты в разных браузерах в Selenium Grid и затем собирать их все в один большой отчет, по которому один из тестировщиков обязан пробежаться глазами и, в случае обнаружения несоответствий, рапортовать о дефекте. К сожалению, вся эта затея долго не продержалась. Тестировщикам стало лень листать огромный отчет и сравнивать скриншоты, и они все равно пропускали мелкие дефекты. А затем пошли требования внедрения во всех сайтах Responsive Design. И вот тут появился Galen Framework. Решение оказалось простым: проверять размер и расположение элементов относительно друг друга. Для этого понадобился специальный язык Galen Specs, который было бы легко читать и понимать.



Если коротко, Galen Framework — это специальный язык и инструмент для тестирования отображения сайта в браузере. Он позволяет тестировать адаптивный дизайн, а также проводить кросс-браузерное тестирование сайта.


Galen Framework (или просто Galen) использует Selenium для открытия странички в нужном браузере, изменения размера окна браузера и получения информации об элементах на веб-страничке (абсолютное положение и размер).

В качестве еще одной идеи Galen предлагает разрабатывать фронтенд с подходом TDD (Test Driven Development). Все просто: сначала пишите тест, используя синтаксис Galen, затем реализуете фронтенд, запускаете тесты и делаете рефакторинг. Вам не обязательно следовать этой методологии, пока это просто концепт. К сожалению, Galen Framework еще не был тщательно проверен в бою, и сейчас лишь только начинаются попытки внедрения его в нашей компании. Однако, я думаю, будет интересным взглянуть на саму идею разработки фронтенда с подходом TDD, используя Galen тесты. Итак, приступим. Представим, что мы обдумываем, каким же образом нам оптимизировать сайт под разные устройства.

Шаг 1. Сделаем заготовку сайта в обычном блокноте


Попытаемся сделать простой набросок для трех разных устройств:



Как видно по рисунку, мы определили 3 типа устройств: mobile, tablet, desktop. И, судя по нашему наброску, некоторые элементы сайта будут отображаться по-разному на разных устройствах.

Шаг 2. Пишем Galen Specs


Для простоты мы все будем делать в одном файле: homepage.spec
Определим имена всех элементов на страничке, с которыми мы будем работать. Синтаксис Galen я объясню позже, а сейчас постараюсь использовать максимально упрощенные конструкции тестов. В следующих постах, если хабрапользователи посчитают этот инструмент интересным, я постараюсь изложить более сложный подход к тестированию. Также вы можете посмотреть весь синтаксис и примеры на официальном сайте galenframework.com

Так как я заранее примерно представляю, каким образом у меня будет строится разметка в html, то я могу указать «локаторы» для тестовых элементов. Вообще, в Galen можно использовать три типа локаторов: id, css, xpath. Советую избегать xpath, использовать его только в редких случаях, когда id и css не позволяют выбрать нужный элемент со страницы.

===========================================
header               id   header
header-logo          css  #header .logo
header-caption       css  #header h1

menu                 id   menu
menu-item-*          css  #menu li a

content              id   content
side-panel           id   side-panel
side-panel-caption   css  #side-panel h2
side-panel-links-*   css  #side-panel li a

article              id   article
article-caption      css  #article h1
article-text         id   article-text

comments             id   comments

footer               id   footer
==========================================


Как видите, некоторые объекты имеют * в своем имени. Это нужно тогда, когда на странице много похожих элементов. Galen в таком случае сначала отыщет все элементы по заданому локатору, а затем создаст объекты с указанным именем, только вместо * он подставит порядковый номер, начиная с 1. Возьмем для примера menu-item-*. Если на нашем сайте будет 4 элемента меню, то Galen создаст соответственно объекты: menu-item-1, menu-item-2, menu-item-3, menu-item-4.

Советую пока не писать тесты для элементов меню. Лучше начать с простого: тестирование каркаса нашего сайта. Попробуем объяснить Galen, каким образом он должен тестировать наши объекты, в зависимости от размера браузера. Будем использовать четыре тега: mobile, tablet, desktop, all. Последний мы введем для собственного удобства, чтобы не пришлось перечислять все устройства для обычных тестов.

Следующий кусок кода мы добавим в наш файл homepage.spec после объявления объектов, хотя, на самом деле, не важно, в каком месте мы пишем сами проверки.

@ all
------------------------------------
header
    width: 100% of screen/width
    height: 100px
    above: menu 0px

menu
    width: 100% of screen/width
    below: header 0px
    above: content 0px

footer
    width: 100% of screen/width
    height: > 100px

content
    inside: screen 0px left
    below: menu 0px


@ desktop, tablet
-----------------------------------
side-panel
    width: 300px
    below: menu 0px
    inside: screen 0px right
    near: content 0px right

menu
    height: 50px

footer
    below: content 0px


@ mobile
-----------------------------------
side-panel
    width: 100% of screen/width
    below: content 5px

content
    width: 100% of screen/width
    above: side-panel 5px

footer
    below: side-panel 0px


Как видите, для desktop и tablet тегов объект content — единственный, у которого не определена ширина. Это потому, что в Galen пока еще нет возможности употреблять арифметические операции (например, 100% of screen/width — 300px). Но, с другой стороны, это бы являлось излишним. В нашем тесте есть проверка side-panel на то, что она располагается рядом с объектом content с левой стороны. Также указано, что content прикреплен к левой стороне экрана, а side-panel — к правой. Таким образом, если ширина content будет слишком маленькой или слишком большой, это отобразится в нарушении при проверке «near: content 0px right», и мы в любом случае не пропустим этот дефект.

Код выше можно оптимизировать, но я этого не делаю для большей наглядности. Пока этого достаточно для того, чтобы приступить к верстке нашего каркаса. Вот каким образом его можно было бы оптимизировать:

Показать оптимизированный код
Мы можем убрать излишние проверки above и below. Если мы проверяем, что menu располагается над main на расстоянии 10 пикселей, то уже нет смысла проверять, что main располагается под menu на том же расстоянии. Также мы можем объединить все объекты, которые должны растягиваться по ширине экрана в одну проверку.
@ all
------------------------------------

header, menu, footer
    width: 100% of screen/width

header
    height: 100px
    above: menu 0px

menu
    height: 50px
    above: content 0px

footer
    height: > 100px

content
    inside: screen 0px left



@ desktop, tablet
-----------------------------------

side-panel
    width: 300px
    below: menu 0px
    inside: screen 0px right
    near: content 10px right

@ mobile
-----------------------------------
side-panel, content
    width: 100% of screen/width

side-panel
    below: content 5px




Шаг 3. Пишем Html/CSS


Давайте теперь напишем нашу главную страничку. Тут я набросал простейшую страничку, на которой можно будет протестировать наши проверки samples.galenframework.com/tutorial1/tutorial1.html

Шаг 4. Запускаем тесты в Galen


Наша главная страничка готова. Мы можем запустить тесты в galen для разных устройств. По умолчанию будет использоваться Firefox браузер.

Внимание! Т.к. Galen использует Selenium, то высока вероятность, что последний Firefox браузер не будет поддерживаться. Это одна из основных головных болей в мире Selenium, и я пока не придумал, как ее решить для Galen. Все, на что я способен — обновлять версию Selenium в Galen до последней и надеяться, что со следующим выходом Firefox ребята из Mozilla перестанут вносить серьезные изменения в API и ломать зависимость селениума. Как вариант, можно было бы разработать свой браузер, основанный на WebKit, специально для Galen, но мне кажется, что это будет пустая трата времени.


Запустим из командной строки три команды для отдельной проверки в десктопе, планшете и мобильной версии.

galen check homepage.spec --url "http://samples.galenframework.com/tutorial1/tutorial1.html" --size 1024x768 --include "all,desktop" --htmlreport desktop-reports

galen check homepage.spec --url "http://samples.galenframework.com/tutorial1/tutorial1.html" --size 600x800 --include "all,tablet"   --htmlreport tablet-reports

galen check homepage.spec --url "http://samples.galenframework.com/tutorial1/tutorial1.html" --size 400x600 --include "all,mobile"   --htmlreport mobile-reports


В итоге Galen создаст html отчет, в котором можно найти все совершенные проверки, а также увидеть сообщения об ошибках.



Если нажать на подсвеченную красным проверку, то получим скриншот с выделенными блоками, которые нарушили эту самую проверку.



Как видите, в сообщении говорится «side-panel» is 0px below «content» instead of 5px. Т.е. в нашей версии сайта нет указаного отступа в 5 пикселей между объектами «content» и «side-panel» для мобильной версии. Надо что-то с этим делать. Если это баг, то будем чинить нашу верстку и добавлять этот отступ. Если же нам все равно какого размера отступ, то мы можем указать, что он должен быть в пределах разумного таким образом: below: content 0 to 10 px. Т.е. отступ может быть любой в диапазоне от 0 до 10.

После того, как мы подправим нашу верстку или исправим проверки, можно еще раз запустить тесты. Только способ запуска какой-то не очень удобный. Приходится запускать разные команды отдельно и читать отчеты в разных папках. Давайте воспользуемся еще одной особенностью Galen — так называемыми Galen Test Suites. Создадим файл galen-tutorial.test, напишем в нем следующее:

@@ Parameterized
   | device   | size       | tags        |
   | desktop  | 1024x768   | all,desktop |
   | tablet   | 600x800    | all,tablet  |
   | mobile   | 400x600    | all,mobile  |
Tutorial 1 Home page in ${device} device
    http://samples.galenframework.com/tutorial1/tutorial1.html  ${size}
        check homepage.spec --include "${tags}"


Готово. Теперь мы можем запустить наши тесты и объединить все отчеты в один.

galen test galen-tutorial.test --htmlreport reports


Получившийся отчет можете посмотреть по этой ссылке: samples.galenframework.com/tutorial1/reports/report.html

Более сложные и детальные проверки



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

@ all
-----------------------------------
header-logo
    inside: header 10px left
    centered vertically inside: header
    height: 60px


header-caption
    inside: header 10 to 20px top left
    near: header-logo ~ 10 px
    text is: My Awesome Website!


Как видите, появились новые проверки: «centered vertically inside» и «text is». Первая проверяет, что наш логотип расположен вертикально посередине и внутри объекта header, а вторая просто проверяет текст.
Еще вы, наверное, заметили новый символ "~", который означает, что мы хотим производить приблизительное сравнение в пределах 2 пикселей погрешности (в Galen можно настроить погрешность для приблизительных сравнений).

Теперь еще более сложная проверка. Давайте проверим, что на десктопе и планшете меню выложено горизонтально, а на мобильной версии таблицей в две колонки, как мы, собственно, и задумывали в нашем наброске в начале статьи. Постараюсь объяснить синтаксис каждой проверки в комментариях кода. Если вы помните, то вверху мы определили объекты меню следующим образом «menu-item-* css #menu li a». Т.е. Galen найдет все элементы меню, а т.к. у нас их только 4, то мы получим в итоге объекты menu-item-1, menu-item-2, menu-item-3, menu-item-4.

@ all
--------------------------------------

# Проверяем, что все элементы меню находятся в самом меню и не выступают за края
menu
    contains: menu-item-*

# Все элементы меню должны иметь высоту 50 пикселей
menu-item-*
    height: 50px


@ desktop, tablet
--------------------------------------

# Проверяем, что каждый элемент меню расположен слева от следующего элемента без отступа (0px)
[ 1 - 3 ]
menu-item-@
    near: menu-item-@{+1} 0px left
    aligned horizontally: menu-item-@{+1}


@ mobile
--------------------------------------
# Каждый элемент меню должен быть примерно в половину ширины самого меню
menu-item-*
    width: 45 to 50 % of menu/width


# Проверяем, что первый столбец меню (табличное отображение)
# расположен слева от второго без какого-либо отступа
# И также проверяем, что оба элемента выравнены горизонтально по верхнему и нижнему краям
[ 1, 3 ]
menu-item-@
    near: menu-item-@{+1} 0px left
    aligned horizontally: menu-item-@{+1}

# Проверяем, что первая строка меню (табличное отображение)
# расположена сверху над вторым без какого-либо отступа
[1, 2]
menu-item-@
    above: menu-item-@{+2} 0px
    aligned vertically: menu-item-@{+2}


Конструкция [1 — 9] дает указание Galen параметризировать следующий объект со всеми его проверками и везде, где встречается символ "@", подставлять текущее значение параметра. Можно указать диапазон, а можно указать конкретные значения через запятую [1, 3, 6, 10]. Также, как видно в верхнем примере, мы использовали конструкцию @{+1}. Это простейшие арифметические операции, которые позволяют нам указать на следующий объект по списку.

И так можно продолжать до бесконечности. Как видите, проверить можно практически любое расположение элементов на странице. Главное, только правильно выбрать способ проверок, чтобы потом не создать себе проблем с поддержкой тестов.
Если вам интересно узнать, какие еще есть возможности в Galen Framework, можете посетить официальный сайт galenframework.com. Позже постараюсь выложить еще несколько статей (например, о том, как автоматизировать тестирование в разных браузерах используя Selenium Grid или о том, как правильно использовать компонентное тестирование).

Вкратце перечислю достоинства и недостатки (недоработки) Galen.

Что может Galen:
  • Проверять расположение блоков относительно друг друга
  • Проверять видимый текст
  • Работать с Selenium Grid
  • Запускать пользовательский javascript на тестовой странице (если, например, нужно открыть выпадающее меню и проверить его элементы)
  • Взаимодействовать с браузером через Selenium, для того, чтобы добраться до нужного места на сайте, если нельзя его вызвать через прямую ссылку
  • Компонентное тестирование. Galen может запускать отдельные файлы проверок для указанных объектов. Таким образом, можно реализовать проверки повторяющихся сложных элементов на странице (например, результаты поиска, комментарии и т.д.)
  • Делать корректировки размеров и положения объектов. Это может быть полезно в двух случаях: либо Selenium дает некорректную информацию о расположении объекта, либо нам нужны так называемые «guides» (или виртуальные объекты привязки), к которым мы будем относить другие объекты на странице
  • Блоки условий. Могут оказаться полезными, когда невозможно узнать, какой именно элемент будет отображен на странице (напр. баннеры)
  • Параметризация тестов в тест-сьютах. Можно, кстати, пойти дальше и использовать параметризацию параметризации (редкий случай, но можно, например, запустить один и тот же тест для разных размеров да еще и для разных браузеров)


Что пока еще не может Galen:
  • Проверять расположение видимого текста, а не всего блока (например h1 теги). В планах реализовать определение текста на скриншоте, но это будет работать только в Firefox (у Selenium проблемы с скриншотами в Chrome и IE)
  • Запускаться в реальных мобильных браузерах. Это проблема Selenium, т.к. он не позволяет получать информацию о расположении элементов на странице в Android браузере. Решением может стать разработка собственного инструмента, основаного на javascript (например как BusterJS или как Selenium 1.0). В таком случае, можно работать вообще с любым браузером. Либо можно написать свой собственный браузер для iOS и Android, который бы поддерживал коммуникацию с Galen. Но это будет слишком сложно для одного человека, поэтому я пока что отложу эту идею
  • Проверять цвет и сравнивать участки изображения на скриншотах. В планах разработать простейшее сравнение цветовой гаммы по гистограммам (например, color scheme is: 80 to 85 % black, ~10% white или color scheme like: image-samples/menu.png). Galen будет брать скриншот, выделять область указаного элемента и сверять его цветовую гамму. Также можно добавить простейшее сравнения изображений, однако, мне кажется это избыточным.
  • Выполнять сложные арифметические операции в параметризированых проверках. Пока можно делать только так: @{+1}, @{*2}, @{-1}, @{/10}. Но в планах сделать полноценные арифметические выражения с использованием скобок
  • Выполнять арифметические операции в обычных проверках. Например было бы неплохо сделать что-то наподобие width: 100% of screen/width - 10px - 100% of comments/width + 10% of somethingelse/width
  • Нет вменяемого установщика. На машине должна быть Java 1.6+, к сожалению я не имею опыта в создании установщиков, но в скором времени надеюсь что-нибудь придумать


Проект выложен на GitHub github.com/ishubin/galen и распространяется под лицензией Apache License, Version 2.0.

Galen поддерживается только одним человеком и нигде еще не распространен. Мы пытаемся внедрить его в нашей компании, но пока о каких-либо успехах говорить еще рано. Если вас заинтересовал проект, буду рад любым отзывам, особенно конструктивной критике т.к. проект находится в стадии бета и нуждается в тестировании. Дефекты можете направлять сюда github.com/ishubin/galen/issues. Скачать проект можно по этой ссылке galenframework.com/download
Tags:
Hubs:
+26
Comments8

Articles

Change theme settings