Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Радости и гадости регрессионного тестирования вёрстки / Алексей Малейков (HTML Academy)

381 views

Published on

Совместно с университетом ИТМО мы запустили курс, посвященный основам HTML и CSS. Уже на момент регистрации на этот курс записалось более 12 тысяч студентов. Перед нами стояла задача разработать систему, которая будет автоматически проверять итоговые проекты на соответствие заранее подготовленному макету. В качестве основной техники для проверки было выбрано регрессионное тестирование.

В каждом проекте мы проверяли разметку, сетку и стилевое оформление не только страницы целиком, но и отдельных блоков. Одной из главных проблем был поиск этих самых блоков, так как о том, какой будет верстка студентов, мы не знали ничего — ни какие теги они использовали, ни какие классы и идентификаторы были задействованы. Имели только общее представление о структуре.

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

Published in: Engineering
  • Be the first to comment

  • Be the first to like this

Радости и гадости регрессионного тестирования вёрстки / Алексей Малейков (HTML Academy)

  1. 1. Радости и гадости регрессионного тестирования вёрстки
  2. 2. Задача • Курс по основам HTML и CSS
  3. 3. Задача • Курс по основам HTML и CSS • 12 000 пользователей записались на курс
  4. 4. Задача • Курс по основам HTML и CSS • 12 000 пользователей записались на курс • Автоматизация проверки
  5. 5. Найди отличия
  6. 6. Регрессионное тестирование
  7. 7. Регрессионное тестирование
  8. 8. Регрессионное тестирование
  9. 9. Проверка • JavaScript
  10. 10. Проверка • JavaScript • DOM
  11. 11. Проверка • JavaScript • DOM • Computed style
  12. 12. Серверная проверка • PhantomJS
  13. 13. Серверная проверка • PhantomJS • WebKit
  14. 14. Серверная проверка • PhantomJS • WebKit • JavaScript API
  15. 15. Серверная проверка • PhantomJS • WebKit • JavaScript API $ phantomjs /path/to/your/script.js params
  16. 16. var page = require('webpage').create(); page.open(url, function(status) { if (status === 'success') { … } }); Серверная проверка
  17. 17. var page = require('webpage').create(); page.open(url, function(status) { if (status === 'success') { var result = page.evaluate(function() { return HtmlacademyTask.runChecks(); }); console.log(result); } }); Серверная проверка
  18. 18. var page = require('webpage').create(); page.onConsoleMessage = function(msg) { console.log(msg); }; page.onAlert = function(msg) { console.log(msg); }; page.open(url, function(status) { … }); Серверная проверка
  19. 19. Испытания
  20. 20. var page = require('webpage').create(); page.viewportSize = { width: width, height: height }; page.open(url, function(status) { if (status === 'success') { page.render(output); } }); Проверка
  21. 21. ImageMagick
  22. 22. ImageMagick Cреднеквадратическое отклонение (RMSE)
  23. 23. ImageMagick Cреднеквадратическое отклонение (RMSE) $ compare -metric RMSE image1.png image2.png diff.png
  24. 24. ImageMagick Cреднеквадратическое отклонение (RMSE) $ compare -metric RMSE image1.png image2.png diff.png 13222.7 (0.201766)
  25. 25. ImageMagick Cреднеквадратическое отклонение (RMSE) $ compare -metric RMSE image1.png image2.png diff.png 13222.7 (0.201766) (1-0.201766) * 100 = ~79%
  26. 26. ImageMagick РезультатОбразец Сравнение Совпадение — 91%
  27. 27. ImageMagick Совпадение — 63% Образец СравнениеРезультат
  28. 28. ImageMagick Совпадение — 76% Образец СравнениеРезультат
  29. 29. ImageMagick Совпадение — 98% Образец СравнениеРезультат
  30. 30. Система проверки вёрстки
  31. 31. Принцип работы • Макет
  32. 32. Принцип работы • Макет • Образец вёрстки
  33. 33. Принцип работы • Макет • Образец вёрстки • Проверка: 1 2 3 4 5
  34. 34. Принцип работы • Макет • Образец вёрстки • Проверка: 1. Разметка 1 2 3 4 5
  35. 35. Принцип работы • Макет • Образец вёрстки • Проверка: 1. Разметка 2. Сетка 1 2 3 4 5
  36. 36. Принцип работы • Макет • Образец вёрстки • Проверка: 1. Разметка 2. Сетка 3. Оформление 1 2 3 4 5
  37. 37. Принцип работы • Макет • Образец вёрстки • Проверка • Скриншоты (PhantomJS) 1 2 3 4 5
  38. 38. Принцип работы • Макет • Образец вёрстки • Проверка • Скриншоты (PhantomJS) • Сравнение (ImageMagick) 1 2 3 4 5
  39. 39. Чужая вёрстка
  40. 40. Чужая вёрстка • Не знаем классов и идентификаторов
  41. 41. Чужая вёрстка • Не знаем классов и идентификаторов • Не знаем тегов
  42. 42. Чужая вёрстка • Не знаем классов и идентификаторов • Не знаем тегов • Знаем только общую структуру
  43. 43. Чужая вёрстка
  44. 44. Чужая вёрстка
  45. 45. Чужая вёрстка
  46. 46. body > *:nth-child(N) { … } Поиск нужных блоков
  47. 47. Поиск нужных блоков body > *:nth-child(2) { box-shadow: inset 0 0 0 6px #000000; }
  48. 48. Поиск нужных блоков body > *:nth-child(2) { box-shadow: inset 0 0 0 6px #000000; } body > *:not(:nth-child(2)) { visibility: hidden; }
  49. 49. Поиск нужных блоков body > *:nth-child(2) { box-shadow: inset 0 0 0 6px #000000; } body > *:not(:nth-child(2)) { display: none; }
  50. 50. var page = require('webpage').create(); page.open(url, function(status) { if (status === 'success') { page.evaluate(function() { … }); page.render(output); } }); Скриншоты блоков
  51. 51. 1. Разметка
  52. 52. var page = require('webpage').create(); page.onResourceRequested = function(data, request) { if ((/.+.css$/gi).test(data['url'])) { request.abort(); } }; page.open(url, function(status) { … }); Проверка разметки
  53. 53. page.evaluate(function() { var links = document.querySelectorAll('[rel=stylesheet]'); [].forEach.call(links, function(element) { element.parentNode.removeChild(element); }); }); Проверка разметки
  54. 54. 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); });
  55. 55. 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'); });
  56. 56. Проверка разметки
  57. 57. Проверка разметки
  58. 58. Особенности разметки
  59. 59. Особенности разметки
  60. 60. <table> <tr> <td>Название</td> <td>Длительность</td> <td>Описание</td> </tr> <tr> <td>Дневное обучение</td> <td>4 года</td> <td>Наиболее интенсивный вариант обучения, для тех, кто не терпит компромиссов ни в чем</td> </tr> </table> Особенности разметки
  61. 61. <table> <thead> <tr> <td>Название</td> <td>Длительность</td> <td>Описание</td> </tr> </thead> <tbody> <tr> <td>Дневное обучение</td> <td>4 года</td> <td>Наиболее интенсивный вариант обучения, для тех, кто не терпит компромиссов ни в чем</td> </tr> </tbody> </table> Особенности разметки
  62. 62. Особенности разметки
  63. 63. 2. Сетки
  64. 64. • Выделяем структурные блоки Поиск сеток
  65. 65. • Выделяем структурные блоки • Скрываем все декоративные элементы Поиск сеток
  66. 66. // первый уровень body > * { background: #333333; box-shadow: inset 0 0 0 4px #cccccc;
 } Поиск сеток
  67. 67. // первый уровень body > * { background: #333333; box-shadow: inset 0 0 0 4px #cccccc;
 } body > *::before, body > *::after { visibility: hidden; } Поиск сеток
  68. 68. // второй уровень body > * > * { background: #660000; box-shadow: inset 0 0 0 4px #ff9999;
 } Поиск сеток
  69. 69. // второй уровень body > * > * { background: #660000; box-shadow: inset 0 0 0 4px #ff9999;
 } body > * > *::before, body > * > *::after { visibility: hidden; } Поиск сеток
  70. 70. // третий уровень body > * > * > * { background: #000066; box-shadow: inset 0 0 0 4px #9999ff;
 } Поиск сеток
  71. 71. // третий уровень body > * > * > * { background: #000066; box-shadow: inset 0 0 0 4px #9999ff;
 } body > * > * > *::before, body > * > * > *::after { visibility: hidden; } Поиск сеток
  72. 72. // третий уровень body > * > * > * { background: #000066; box-shadow: inset 0 0 0 4px #9999ff;
 } body > * > * > *::before, body > * > * > *::after { visibility: hidden; } // все уровни глубже body > * > * > * > * { visibility: hidden; } Поиск сеток
  73. 73. // убираем весь текст body, body * { color: transparent; } Поиск сеток
  74. 74. Поиск сеток
  75. 75. Поиск сеток
  76. 76. Поиск сеток
  77. 77. Поиск сеток
  78. 78. 3. Оформление
  79. 79. Проверка оформления Оригинал
  80. 80. Проверка оформления Результат
  81. 81. Проверка оформления Уровень совпадения — 87%
  82. 82. Различия в цветах #6451d5 #7232d8
  83. 83. Шрифты
  84. 84. Шрифты
  85. 85. Шрифты Уровень совпадения — 87%
  86. 86. В поисках идеальной вёрстки
  87. 87. Выбор есть, даже когда нет выбора 1. Разметка
  88. 88. Выбор есть, даже когда нет выбора 2. Сетка
  89. 89. Выбор есть, даже когда нет выбора 3. Оформление
  90. 90. Наши требования • 15 из 17 проверок • 95% совпадения 1 2 3 4 5
  91. 91. Наши требования • 12 из 17 проверок • 90% совпадения 1 2 3 4 5
  92. 92. Результаты • 12 000 записались на курс • 5 700 начали проходить • 1 000 успешно прошли курс • 830 приступили к итоговому испытанию • 520 успешно прошли итоговое испытание • 10 итоговых испытаний на 100%
  93. 93. Регрессионное тестирование • SlimerJS
 slimerjs.org
  94. 94. Регрессионное тестирование • SlimerJS
 slimerjs.org • GraphicsMagick
 graphicsmagick.org
  95. 95. Регрессионное тестирование • CasperJS
 casperjs.org
  96. 96. Регрессионное тестирование • CasperJS
 casperjs.org • PhantomCSS
 github.com/Huddle/PhantomCSS
  97. 97. Регрессионное тестирование • CasperJS
 casperjs.org • PhantomCSS
 github.com/Huddle/PhantomCSS • BackstopJS
 garris.github.io/BackstopJS/
  98. 98. Регрессионное тестирование • CasperJS
 casperjs.org • PhantomCSS
 github.com/Huddle/PhantomCSS • BackstopJS
 garris.github.io/BackstopJS/ • Gemini
 gemini-testing.github.io/gemini/
  99. 99. Вопросы?
  100. 100. htmlacademy.ruhtmlacademy htmlacademy_ru

×