Одиннадцатикласница або тестуємо баги верстки



У сучасному вебі несправедливо мало уваги приділяється хоч скільки-небудь автоматизованого тестування UI. Особливо це стосується статичної верстки. На проекті 2ГІС Онлайн ми спробували частково заповнити цей пробіл. Які корисні практики ми придбали, і про якихось хороших бібліотеках ми дізналися, розповімо далі.

Верстка

Розглянемо історію однієї вигаданої кнопочки:



Квадратна кнопка з піктограмою. Все просто. Розміри можна хардкодить в пікселях — адже яка різниця?

Практично відразу кнопка починає еволюціонувати. Користувачі рідко натискають на кнопку. Що ж робити? Як варіант — додати пояснює напис. Залишилося лише трохи збільшити ширину, щоб напис входила:



А як же напис російською мовою? Та й оригінальний текст може змінитися. Так що хардкодить ширину не можна, доведеться робити довільну:



Тексту може бути так багато, що в один рядок він не читається. Потрібно обмежити максимальну ширину і розв'язати висоту:



Кнопкою і раніше, мало користуються! Можна зробити допоміжне багаторядковий опис. Для цього потрібно додати span-чик з відповідними стилями:



Здається, вже все враховано, і ніхто не в силах зламати цю верстку. Ніхто крім одинадцятикласниці — довгого слова, не поміщається в максимальну ширину. Просто робимо перенесення по буквах:



Користувачі почали скаржитися на нав'язливу велику кнопку, тому було прийнято рішення зробити хрестик, що закриває кнопку без фактичного натискання. Трохи стилів для хрестика, трішки відступу для заголовка щоб він не потрапляв під цей хрестик — і все готово:



Не забуваємо, що основного тексту може і не бути, правимо відступи:



Здається тепер ми маємо багатофункціональну кнопку на всі випадки життя, з поправленными багами, правда? Давайте ще раз подивимося всі кейси, тільки тепер одночасно:



Що ж ми бачимо? Замість повнофункціональної кнопочки ми бачимо велику кількість регресійних багів: іконка вивалилася з кнопки, поламалося вертикальне вирівнювання, з'явився зайвий відступ для хрестика… Іншими словами, хотіли як краще, вийшло як завжди.

А тепер уявіть, що мова не про неї, а про великий, який постійно розвивається проекті з багатомільйонною аудиторією. Підтримка перетворюється в пекло, в якому, на жаль, живуть багато верстальники.

Є безліч технік і методологій, які допомагають підтримувати верстку складних проектів. Наприклад, широко відомий всім БЕМ, який ми теж використовуємо. Але сама по собі методологія БЕМ не вирішує, а тільки локалізує регресійні баги верстки. Як же позбутися від них в принципі? Насправді дуже просто (і для цього вам не знадобиться вивчати API десятки нових js-бібліотек!) — потрібно створити одну тестову html-сторінку з усіма станами кнопки. Давайте дружно, прям зараз, створимо її, це не займе більше 10 секунд. Ось вам навіть розмітка:

<!doctype html>
<html>
<head>
<meta charset="utf-8" />

<!-- Стильовий файл проекту -->
<link rel="stylesheet" href="/style.css">

<title>Test page</title>
</head>

<body>

<!-- Тут буде перше стан -->

</body>
</html>

Ніякого js, npm-залежностей, express-серверів… Просто html-файлик, відкритий у браузері.

На кожну еволюційну ітерацію потрібно заводити одну або кілька нових станів (тобто варіантів html-коду досліджуваного елемента, включаючи контент), але не видаляти старі. Перегляд всіх старих станів можна назвати напівавтоматичного регресією.

Ми навмисно не будемо радити будь-яких засобів автоматизації цієї роботи, з двох причин: по-перше, для більшості випадків створити самостійно таку сторінку може (і повинен) кожен фронтэндер; по-друге, для складних випадків та випадків pixel-perfect, ми пишемо власне рішення, яке поки не готові анонсувати.

Одинадцятикласниця

Більше половини багів верстки пов'язані з дуже простим прорахунком: фронтэндер не враховує, що в текстові ноди його макета може потрапити, взагалі кажучи, будь-який текст. Він може бути багаторядковий, складатися з довгих слів, або може бути порожнім рядком.

Візьміть пару будь-яких своїх макетів — готовий посперечатися на російський рубль, що їх зможе зламати навіть одна одинадцятикласниця. Вставити кілька одиннадцатиклассниц в кожне поле — поломка верстки гарантована!

Пропоную відкрити будь-який популярний сайт і в налагоджувач виконати наступний код

var a,w=document.createTreeWalker(document,NodeFilter.SHOW_TEXT);while(a=w.nextNode()){a.textContent='Одинадцятикласниця пішла подивитися на пам'ятку, вона йшла довго, кілька рядків, поки не прийшла'}

Перший десяток сайтів, який прийшов на розум (виключаючи 2ГІС Онлайн, звичайно), був зламаний до такої міри, що користуватися ними стало абсолютно неможливо.

Звичайно, це не означає, що одинадцятикласниця кожен день ходить по всім текстовим нодам інтернету і ламає верстку (з тим же успіхом сайт можна захищати від эболавируса), але ви повинні враховувати наступні фактори:

  1. Якщо ваш проект існує на декількох мовах, то на іншій мові може бути більш довга фраза (російська довше англійської, іспанська довше російської і т. д.)
  2. У користувача не може бути основного шрифту, а fallback виявиться більшим
  3. може бути кастомный зум чи інший механізм рендеринга шрифтів
  4. Текст може бути змінений в процесі підтримки, у тому числі контент-менеджерами, які верстку перевіряти вже точно не будуть
  5. У полі може прилетіти неправильний текст просто з-за бага в js-коді
  6. Баг у верстці іншого блоку може стиснути ваш блок
  7. Хто-небудь прочитає цю статтю і виконає наведений код в налагоджувач :)
Ми щиро віримо, що в будь-якому з цих випадків весь текст повинен бути видний користувачеві, і він повинен бути читабельним. Він може некритично змінювати розмір блоку, йти в фейд обриватися або трьома крапками; але він не повинен перетворюватися в атакуючого сусідні ноди монстра, выжигающего очі користувача; тобто він як мінімум не повинен налізати на інший текст.

Автоматизація

Все, про що ми писали вище, назвати автоматичним тестуванням не можна, тому що вимагає очей людини. Якщо ви не хочете напружувати свої очі зовсім, вам допоможуть тести, які ми називаємо dom-тестами.

Dom-тест — це js-код, що виконується у браузері, який перевіряє в ізольованій частині додатка, або у всьому додатку. Перевірятися може що завгодно: від наявності класу і атрибуту в html, до аргументів, з якими була викликана якась функція, в тому числі асинхронна.

Тут вам допоможуть такі чудові бібліотеки як:

mocha. Фреймворк для тестування. Дозволяє створювати тести і групи тестів, включаючи асинхронні; виконувати якийсь код перед тестом або групою тестів, і після нього.

chai. Бібліотека для assert-ів принципі можна використовувати нативний assert node.js, але у «чаю» є плюшки, наприклад красивий diff deepEqual.

sinon. Бібліотека, що дозволяє робити дві важливі речі:

  • Стежити за функціями. Ви будете знати, скільки разів і з якими аргументами була викликана функція, за якої ви стежите.
  • FakeTimers. Дозволяє підміняти setTimeout і setInterval і, таким чином, «керувати» часом. Тобто, після підміни ви може викликати sinon.tick(20) — і миттєво пройде 20 мілісекунд часу, при цьому виконуються всі таймаут, зареєстровані на виконання в цьому періоді.
Комбінуючи все це можна писати тести як на всі програма, так і на його ізольовані частини. У цих тестах можна робити буквально все: заповнювати форму і кликати кнопки; змінювати dom-дерево; робити ajax-запити… По суті, всередині таких тестів ви знаходитесь всередині налагоджувальної консолі браузера, а в руках у вас будь-які js-бібліотеки для тестування, які вам подобаються.

Перевага таких тестів — вони виконуються у браузері, а значить, можуть бути запущені в будь-якому браузері за нульовою витратою ресурсів на адаптацію (чого не скажеш про драйвери selenium, особливо в комбінації, припустимо, з ie8 або android 4.0). Крім того, такі тести можна запускати в повністю автоматичному режимі на phantomJS, наприклад на git-push hooks.

На всяк випадок варто відзначити, що dom-тести не є альтернативою регрессионному тестування верстки; це просто ще один підхід захисту коду, зі своєю специфікою і областю застосування.

Висновки

Заведіть html-сторінку для регресії верстки, пустіть у неї одинадцятикласницю, і ваша верстка стане в 10 разів якісніше. Захищайте свій код js-тестами, і ви зможете відмовитися від послуг тестувальників (яким доведеться перекваліфікуватися в автоматизаторів і допомагати вам писати тести). На проекті 2ГІС Онлайн 90% завдань потрапляють на бій без ручного тестування, і це багато в чому стало можливим завдяки названим вище підходам тестування.

Не чекайте, коли одинадцятикласниця прийде до вас сама!

Більше інформації можна почерпнути з презентації на Web Standards Days.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.