Тестирование CSS-регрессий с Сергей Татаринцев, Яндекс BEMup в Москве, 17 мая 2014
Обо мне sevinf@yandex-team.ru @SevInf github.com/SevInf Старший разработчик в группе разработки интерфейсов bit.ly/bemup-msk-gemini
Обеспечение качества кода Стиль кода: jscs Статический анализ: JSHint Регрессии в JS: юнит-тесты Регрессии в CSS: ???
Зачем автоматизировать? Это быстрее Это надежнее
Чего хочется Тестировать в разных браузерах Скриншоты в разных состояних Сравнивать фрагменты страницы Эталонные скриншоты в репозитории JavaScript
DPXDT https://github.com/bslatkin/dpxdt Не нужен код тестов Нужен эталонный URL Скриншоты всей страницы
casper.js + phantom.css https://github.com/Huddle/ PhantomCSS Снимает фрагменты Тестирование различных состояний Только в phantom.js
Huxley https://github.com/facebook/huxley Не нужен код тестов Тестирование различных состояний Скриншот всей страницы Один бразуер
Сравнение dpxdt phantom.css Huxley Разные браузеры ✘ ✘ ✘ Сравнение фрагментов ✘ ✘ Скриншоты в репозитории ✘ Различные состояния ✘ JavaScript ✘ ✘
gemini
Схема работы Тестовый набор Состояние 1 Действия Состояние 2 Действия Состояние N Действия
Кнопка из bem-components
Кнопка plain hover Навести курсор pressed Нажать левую кнопку clicked Отпустить кнопку
Создание набора var gemini = require('gemini'); ! gemini.suite('button', function(suite) { });
Задание URL ! suite.setUrl('/some/url'); !
Область захвата ! suite.setCaptureElements('.button');
Захват начального состояния suite.capture('plain'); !
Состояние с действиями ! suite.capture('hovered', function(actions) { }); !
Передвижение курсора ! suite.capture('hovered', function(actions) { actions.mouseMove('.button'); }); !
Нажатая кнопка ! suite.capture('pressed', function(actions, find) { actions.mouseDown(find('.button')); }); !
Кнопка в фокусе ! suite.capture('clicked', function(actions, find) { actions.mouseUp(find('.button')); }); !
before ! suite.before(function(actions, find) { this.button = find('.button'); }); !
Финальный вариант var gemini = require('gemini'); ! gemini.suite('button', function() { suite.setUrl('/some/url') .setCaptureElements('.button') .before(function(actions, find) { this.button = find('.button'); }) .capture('plain') .capture('hovered', function(actions, find) { actions.mouseMove(this.button); }) .capture('pressed', function(actions, find) { actions.mouseDown(this.button); }) .capture('clicked', function(actions, find) { actions.mouseUp(this.button); }); });
.gemini.yml rootUrl: http://example.com gridUrl: http://localhost:4444/wd/hub browsers: - {name: chrome, version: '33.0'} - {name: opera, version: '12.16'} - {name: firefox, version: '25.0'} - {name: ie, version: '10.0'}
Демо
Полезные советы Скриншоты - не замена юнит-тестам Использовать статические данные
https://saucelabs.com/
Переменные среды SAUCE_USERNAME=<USERNAME> SAUCE_ACCESS_KEY=<ACCESS KEY>
.gemini.yml gridUrl: http://ondemand.saucelabs.com/wd/hub
SauceConnect https://saucelabs.com/docs/connect <SAUCE CONNECT DIR>/bin/sc
https://travis-ci.org/
Интеграция с TravisCI before_install: - sudo apt-get update -qq - sudo apt-get install -qq -y graphicsmagick .travis.yml
Интеграция с TravisCI "scripts": { "test": "gemini test" } package.json
SauceLabs + TravisCI https://saucelabs.com/opensource/travis ! Пример: http://bit.ly/bc-gemini
Где взять? ru.bem.info/tools/testing/gemini/ ! github.com/bem/gemini
sevinf@yandex-team.ru @SevInf SevInf Сергей Татаринцев! Яндекс Ваш звонок очень важен для нас: http://bit.ly/msk-bemup-feedback

Сергей Татаринцев — Тестирование CSS-регрессий с Gemini