Download - Регрессионное тестирование верстки
Алексей МалейковРазработчик в HTML Academy
2016
Радости и гадости регрессионного
тестирования вёрстки
Задача
• Курс по основам HTML и CSS
Задача
• Курс по основам HTML и CSS
• 12 000 пользователей записались на курс
Задача
• Курс по основам HTML и CSS
• 12 000 пользователей записались на курс
• Автоматизация проверки
Найди отличия
Регрессионное тестирование
Регрессионное тестирование
Регрессионное тестирование
Интерактивные задания на сайте
Проверка
• JavaScript
Проверка
• JavaScript
• DOM
Проверка
• JavaScript
• DOM
• Computed style
Серверная проверка
• PhantomJS
Серверная проверка
• PhantomJS
• WebKit
Серверная проверка
• PhantomJS
• WebKit
• JavaScript API
Серверная проверка
• PhantomJS
• WebKit
• JavaScript API
$ phantomjs /path/to/your/script.js params
var page = require('webpage').create();
page.open(url, function(status) { if (status === 'success') { … } });
Серверная проверка
var page = require('webpage').create();
page.open(url, function(status) { if (status === 'success') {
var result = page.evaluate(function() {
return HtmlacademyTask.runChecks(); });
console.log(result); } });
Серверная проверка
var page = require('webpage').create();
page.onConsoleMessage = function(msg) { console.log(msg); };
page.onAlert = function(msg) { console.log(msg); };
page.open(url, function(status) { … });
Серверная проверка
Испытания
Испытания
var page = require('webpage').create();
page.viewportSize = { width: width, height: height };
page.open(url, function(status) { if (status === 'success') {
page.render(output); } });
Проверка
ImageMagick
ImageMagick
Cреднеквадратическое отклонение (RMSE)
ImageMagick
Cреднеквадратическое отклонение (RMSE)
$ compare -metric RMSE image1.png image2.png diff.png
ImageMagick
Cреднеквадратическое отклонение (RMSE)
$ compare -metric RMSE image1.png image2.png diff.png
13222.7 (0.201766)
ImageMagick
Cреднеквадратическое отклонение (RMSE)
$ compare -metric RMSE image1.png image2.png diff.png
13222.7 (0.201766)
(1-0.201766) * 100 = ~79%
Система проверки вёрстки
Принцип работы
• Макет
Принцип работы
• Макет
• Образец вёрстки
Принцип работы
• Макет
• Образец вёрстки
• Проверка пяти блоков
1
2
3
4
5
Принцип работы
• Макет
• Образец вёрстки
• Проверка пяти блоков
1. Разметка
1
2
3
4
5
Принцип работы
• Макет
• Образец вёрстки
• Проверка пяти блоков
1. Разметка
2. Сетка
1
2
3
4
5
Принцип работы
• Макет
• Образец вёрстки
• Проверка пяти блоков
1. Разметка
2. Сетка
3. Оформление
1
2
3
4
5
Принцип работы
• Макет
• Образец вёрстки
• Проверка пяти блоков
1. Разметка
2. Сетка
3. Оформление
• Проверка страницы целиком
1
2
3
4
5
Принцип работы
• Макет
• Образец вёрстки
• Проверка пяти блоков
1. Разметка
2. Сетка
3. Оформление
• Проверка страницы целиком
• Скриншоты (PhantomJS)
1
2
3
4
5
Принцип работы
• Макет
• Образец вёрстки
• Проверка пяти блоков
1. Разметка
2. Сетка
3. Оформление
• Проверка страницы целиком
• Скриншоты (PhantomJS)
• Сравнение (ImageMagick)
1
2
3
4
5
Работа с архивами
– project.zip — img/ — css/ — index.html
Работа с архивами
– project.zip — img/ — css/ — index.html
– Мой Проект.rar — Мой проект/
— img/ — css/
— стили.css — project_index.html
Работа с архивами
– project.zip — img/ — css/ — index.html
– Мой Проект.rar — Мой проект/
— img/ — css/
— стили.css — project_index.html
• To zip or not to zip
Работа с архивами
– project.zip — img/ — css/ — index.html
– Мой Проект.rar — Мой проект/
— img/ — css/
— стили.css — project_index.html
• To zip or not to zip
• Поиск index.html
Чужая вёрстка
Чужая вёрстка
• Не знаем классов и идентификаторов
Чужая вёрстка
• Не знаем классов и идентификаторов
• Не знаем тегов
Чужая вёрстка
• Не знаем классов и идентификаторов
• Не знаем тегов
• Знаем только общую структуру
Чужая вёрстка
Чужая вёрстка
Чужая вёрстка
body > *:nth-child(N) {
… }
Поиск нужных блоков
Поиск нужных блоков
body > *:nth-child(2) {
box-shadow: inset 0 0 0 6px #000000; }
Поиск нужных блоков
body > *:nth-child(2) {
box-shadow: inset 0 0 0 6px #000000; }
body > *:not(:nth-child(2)) {
visibility: hidden; }
Поиск нужных блоков
body > *:nth-child(2) {
box-shadow: inset 0 0 0 6px #000000; }
body > *:not(:nth-child(2)) {
display: none; }
var page = require('webpage').create();
page.open(url, function(status) { if (status === 'success') {
page.evaluate(function() { … });
page.render(output); } });
Скриншоты блоков
1. Разметка
Проверка разметки
• Получаем чистый HTML
Проверка разметки
• Получаем чистый HTML
• Вырезаем все стили
Проверка разметки
• Получаем чистый HTML
• Вырезаем все стили
• Частично проверяем семантику
var page = require('webpage').create();
page.onResourceRequested = function(data, request) { if ((/.+\.css$/gi).test(data['url'])) { request.abort(); } };
page.open(url, function(status) { … });
Проверка разметки
page.evaluate(function() {
var links = document.querySelectorAll('[rel=stylesheet]'); [].forEach.call(links, function(element) { element.parentNode.removeChild(element); });
});
Проверка разметки
page.evaluate(function() {
var links = document.querySelectorAll('[rel=stylesheet]'); [].forEach.call(links, function(element) { element.parentNode.removeChild(element); });
});
Проверка разметки
var styles = document.querySelectorAll('style'); [].forEach.call(styles, function(element) { element.parentNode.removeChild(element); });
page.evaluate(function() {
var links = document.querySelectorAll('[rel=stylesheet]'); [].forEach.call(links, function(element) { element.parentNode.removeChild(element); });
});
Проверка разметки
var styles = document.querySelectorAll('style'); [].forEach.call(styles, function(element) { element.parentNode.removeChild(element); });
var attrs = document.querySelectorAll('[style]'); [].forEach.call(attrs, function(element) { element.removeAttribute('style'); });
Проверка разметки
Проверка разметки
Особенности разметки
Особенности разметки
<table> <tr> <td>Название</td> <td>Длительность</td> <td>Описание</td> </tr> <tr> <td>Дневное обучение</td> <td>4 года</td> <td>Наиболее интенсивный вариант обучения, для тех, кто не терпит компромиссов ни в чем</td> </tr> </table>
Особенности разметки
<table>
<thead> <tr> <td>Название</td> <td>Длительность</td> <td>Описание</td> </tr>
</thead>
<tbody> <tr> <td>Дневное обучение</td> <td>4 года</td> <td>Наиболее интенсивный вариант обучения, для тех, кто не терпит компромиссов ни в чем</td> </tr>
</tbody> </table>
Особенности разметки
Особенности разметки
2. Сетки
Поиск сеток
• Выделяем структурные блоки
Поиск сеток
• Выделяем структурные блоки
• Скрываем все декоративные элементы
// первый уровень body > * { background: #333333; box-shadow: inset 0 0 0 4px #cccccc;}
Поиск сеток
// первый уровень body > * { background: #333333; box-shadow: inset 0 0 0 4px #cccccc; }
body > *::before, body > *::after { visibility: hidden; }
Поиск сеток
Поиск сеток
// второй уровень body > * > * { background: #660000; box-shadow: inset 0 0 0 4px #ff9999; }
Поиск сеток
// второй уровень body > * > * { background: #660000; box-shadow: inset 0 0 0 4px #ff9999; }
body > * > *::before, body > * > *::after { visibility: hidden; }
Поиск сеток
// третий уровень body > * > * > * { background: #000066; box-shadow: inset 0 0 0 4px #9999ff;}
Поиск сеток
// третий уровень body > * > * > * { background: #000066; box-shadow: inset 0 0 0 4px #9999ff; }
body > * > * > *::before, body > * > * > *::after { visibility: hidden; }
Поиск сеток
// третий уровень body > * > * > * { background: #000066; box-shadow: inset 0 0 0 4px #9999ff; }
body > * > * > *::before, body > * > * > *::after { visibility: hidden; }
// все уровни глубже body > * > * > * > * { visibility: hidden; }
// убираем весь текст body, body * { color: transparent; }
Поиск сеток
Поиск сеток
Поиск сеток
Поиск сеток
Поиск сеток
3. Оформление
Проверка оформления
Оригинал
Проверка оформления
Результат
Проверка оформления
Уровень совпадения — 87%
Различия в цветах
#6451d5 #7232d8
Шрифты
В поисках идеала
Выбор есть, даже когда нет выбора
1. Разметка
Выбор есть, даже когда нет выбора
2. Сетка
Выбор есть, даже когда нет выбора
3. Оформление
Наши требования
• 15 из 17 проверок
• 95% совпадения1
2
3
4
5
Наши требования
• 12 из 17 проверок
• 90% совпадения1
2
3
4
5
Результаты
• 12 000 записались на курс
• 5 700 начали проходить
• 1 000 успешно прошли курс
• 830 приступили к итоговому испытанию
• 520 успешно прошли итоговое испытание
• 10 итоговых испытаний на 100%
Регрессионное тестирование
• SlimerJSslimerjs.org
Регрессионное тестирование
• SlimerJSslimerjs.org
• CasperJScasperjs.org
Регрессионное тестирование
• SlimerJSslimerjs.org
• CasperJScasperjs.org
• PhantomCSSgithub.com/Huddle/PhantomCSS
Регрессионное тестирование
• SlimerJSslimerjs.org
• CasperJScasperjs.org
• PhantomCSSgithub.com/Huddle/PhantomCSS
• BackstopJSgarris.github.io/BackstopJS/
Регрессионное тестирование
• SlimerJSslimerjs.org
• CasperJScasperjs.org
• PhantomCSSgithub.com/Huddle/PhantomCSS
• BackstopJSgarris.github.io/BackstopJS/
• Gemini gemini-testing.github.io/gemini/
Вопросы?