Средства проверки статического анализа, инструменты непрерывной интеграции, модульные тесты и многое другое
По мере того, как все больше и больше компаний сосредотачиваются на том, чтобы сделать свои приложения доступными, часто возникает вопрос: «Как нам убедиться, что мы ничего не упускаем из виду?» Мы проделали всю эту работу, чтобы исправить наше приложение, но как нам убедиться, что через шесть месяцев мы снова не закопаемся в яму и не окажемся в той же ситуации, в которой находимся сейчас? Как мы делаем вещи доступными?
Есть несколько решений. Во-первых, это образование и обучение. Каждый в компании должен быть сторонником доступности и понимать передовой опыт в области доступности. Второе — это более совершенные организационные процессы. Компании должны включать аудит доступности в естественные контрольные точки на протяжении всего жизненного цикла разработки программного обеспечения, например, когда UX предоставляет макеты дизайна команде инженеров или когда команда инженеров завершает код для новой функции. Третье — автоматизированное тестирование, и именно на нем я хотел бы сегодня остановиться.
Отказ от ответственности
В качестве краткого заявления об отказе от ответственности, прежде чем мы начнем, я хочу подчеркнуть, что когда речь идет о специальных возможностях, нет адекватной альтернативы хорошему ручному тестированию с помощью мыши, клавиатуры и программы чтения с экрана. Спросите любого консультанта по доступности, и он скажет вам то же самое.
Проблема в том, что инженеры часто недовольны этим ответом. Инженеры любят все автоматизировать. Ручное тестирование звучит утомительно, и оно не масштабируется.
И, вы были бы правы. Это справедливые опасения. Итак, давайте взглянем на некоторые из имеющихся у нас автоматических инструментов и рассмотрим их преимущества и недостатки.
Автоматизированные инструменты специальных возможностей
Есть несколько хороших инструментов, которые могут помочь нам в наших усилиях по обеспечению доступности. Некоторые из распространенных инструментов, которые я использовал, — это плагины ESLint, такие как eslint-plugin-jsx-a11y, инструменты от Deque, такие как расширение axe DevTools Chrome или веб-краулер axe Monitor, и инструменты CI, такие как Google Lighthouse или GitLab CI/CD с Pa11y.
Что нужно знать обо всех этих инструментах, так это то, что все они являются средствами проверки статического анализа.
Средства проверки статического анализа проверяют код, будь то исходный код JavaScript или встроенный HTML-код на веб-странице, а затем сообщают о возможных нарушениях на основе набора правил.
И вот в чем фишка: эти средства проверки статического анализа могут выявить только около 10–30% проблем с доступностью в вашем приложении.
Да, вы правильно прочитали это число. 10–30%. Почему это число такое низкое? Чтобы лучше понять, почему, мы должны рассмотреть, что эти инструменты хорошо определяют, а что плохо.
Какие средства проверки статического анализа хорошо определяют
Средства проверки статического анализа хорошо выявляют недопустимое использование HTML. Например, они поймают, когда вы используете тег привязки (<a>
) без атрибута href
. Возможно, вы поместили обработчик кликов на тег привязки, чтобы он функционировал как кнопка, что было бы недопустимо. Средство проверки статического анализа сообщит о нарушении и сообщит вам, что вы должны либо использовать элемент <button>
с обработчиком кликов, либо предоставить действительный атрибут href
для вашего элемента <a>
, если вы действительно хотели, чтобы он был ссылкой.
В качестве другого примера, средства проверки статического анализа могут определить, когда вы использовали элементы заголовков (от <h1>
до <h6>)
в неправильном порядке. Правило состоит в том, что уровни заголовков могут увеличиваться только на один, поэтому вы не можете иметь элемент <h1>
, за которым следует <h4>
. Если чекер статического анализа увидит это в вашем приложении, он сообщит о нарушении.
В качестве третьего примера, средство проверки статического анализа также может определять, неправильно ли вы вкладываете элементы в список. Прямые потомки элементов <ul>
или <ol>
должны быть элементами <li>
, поэтому, если у вас есть что-то вроде <div>
в качестве дочернего элемента контейнера списка <ul>
или <ol>
, средство проверки статического анализа будет жаловаться.
Средства проверки статического анализа также хорошо выявляют плохое использование ролей и обработчиков взаимодействия. Распространенная ошибка, которую я часто вижу, заключается в том, что кто-то использует элемент <div>
с обработчиком кликов, а не элемент <button>
. Проблема только с этим подходом заключается в том, что вы теряете большую часть функциональности, которую семантический элемент <button>
предоставляет вам из коробки. Например, элемент <button>
реагирует на клики, а также на нажатия клавиш Enter и пробела, и правильно сообщает свою роль («кнопку») средствам чтения с экрана. Средство проверки статического анализа, просматривающее ваш исходный код (например, eslint-plugin-jsx-a11y
), сообщит об этих нарушениях и сообщит вам, что если у вас есть обработчик кликов, вам также потребуется сопутствующий обработчик взаимодействия с клавиатурой, а также соответствующая роль для вашего элемента.
Наконец, средства проверки статического анализа, которые запускаются в вашем браузере для визуализированного приложения, также прекрасно обнаруживают проблемы цветового контраста, когда коэффициент цветового контраста для любой заданной комбинации переднего плана и фона падает ниже требуемого порога.
В качестве краткого обзора, вот некоторые из основных вещей, которые средства проверки статического анализа хорошо определяют:
- Недопустимое использование HTML
- Плохое использование ролей и обработчиков взаимодействия
- Проблемы с цветовым контрастом
Какие средства проверки статического анализа плохо определяют
Теперь поговорим о том, что плохо определяют чекеры статического анализа. Короткий ответ заключается в том, что они будут плохо идентифицировать вещи, которые имеют технически правильный исходный код, но создают плохой пользовательский опыт для людей.
Например, рассмотрим порядок табуляции на странице. Для большинства западных языков, которые читаются слева направо, порядок табуляции на странице обычно будет идти слева направо и сверху вниз. У вас может быть макет столбца на вашей странице, и в этом случае порядок вкладок будет опускаться на один столбец, прежде чем переходить к следующему столбцу. При переходе по странице вы можете иногда столкнуться с тем, что фокус табуляции перемещается на элемент, которого вы не ожидали, возможно, пропуская несколько других кнопок или просто переходя куда-то совершенно не связанное. Это дезориентирует человека, но это не то, что может уловить программа проверки статического анализа. Только человек может сказать, какой порядок табуляции имеет смысл, а какой нет.
Другим примером могут быть бесполезные арии-метки. Средство проверки статического анализа хорошо подскажет вам, когда отсутствует метка, например, для кнопки, состоящей только из значков, но без метки aria. Но средство проверки статического анализа не сможет сказать вам, полезна ли метка aria или имеет ли она смысл. Вы можете ввести какие-то бессмысленные символы в качестве значения aria-label, чтобы пройти проверку статического анализа, но это не поможет вашим пользователям.
В-третьих, средства проверки статического анализа не могут идентифицировать клавиатурные ловушки. Это непреднамеренные ловушки фокусировки, из которых пользователь, пользующийся только клавиатурой, не может выйти, не используя мышь. Вы можете столкнуться с ловушкой клавиатуры при взаимодействии с всплывающим содержимым, таким как модальное окно, всплывающая подсказка или раскрывающееся меню. Пользователь, использующий только клавиатуру, должен иметь возможность попасть в ловушки клавиатуры и выйти из них, поэтому, если они не могут убежать, это проблема.
В-четвертых, средства проверки статического анализа не могут определить, когда на странице отсутствуют альтернативные функции для размещения всех пользователей. Возьмем, к примеру, поведение перетаскивания. Функциональность перетаскивания по своей сути недоступна, поскольку для перемещения указателя мыши из одной конкретной позиции в другую требуется использование мыши и управление мелкой моторикой. Это не проблема сама по себе, но вам необходимо предоставить альтернативные методы для выполнения той же задачи. Таким образом, для чего-то вроде использования функции перетаскивания для изменения порядка элементов в списке вы также можете предоставить элементы управления с клавиатуры, чтобы пользователи, использующие только клавиатуру, могли нажимать клавишу Enter, чтобы активировать «режим изменения порядка», а затем использовать клавиши со стрелками для перемещения элементов. вверх или вниз по списку. Программы проверки статического анализа не могут знать, когда у вас есть достаточно альтернативных методов для выполнения той или иной задачи.
В-пятых, средства проверки статического анализа не могут определить области, в которых использование семантического HTML может быть улучшено. Например, возможно, вы построили таблицу из <div>
элементов. Визуально это выглядит как таблица, но у нее не будет такого же поведения при навигации для пользователей программ чтения с экрана, и она не будет отображаться как таблица для пользователей программ чтения с экрана. Программы проверки статического анализа не будут жаловаться, потому что реальный HTML-код, который вы написали, является технически правильным и не содержит недопустимого синтаксиса. Средство проверки статического анализа не знает, что вы предназначали это для представления таблицы.
Точно так же у вас может быть список элементов на странице, построенный с использованием элементов абзаца (<p>
), а не элементов <ul>
/<ol>
и <li>
. Или, может быть, у вас есть диалоговое модальное окно, но в нем отсутствует вся необходимая сопутствующая модальная разметка, такая как aria-modal="true"
, role="dialog"
и метка aria, обеспечивающая заголовок для модального окна. Программы чтения с экрана увидят технически правильный HTML, но не узнают ваших намерений относительно типа виджетов или информации, которую вы пытаетесь передать.
Опять же, в качестве краткого обзора, вот некоторые из основных вещей, которые плохо определяют средства проверки статического анализа:
- Запутанный порядок табуляции
- Бесполезные арии-лейблы
- Клавиатурные ловушки
- Отсутствует альтернативный функционал
- Области, в которых можно улучшить семантический HTML
Люди против компьютеров
Итак, перед нами дилемма. Как инженеры, мы хотим иметь возможность автоматизировать тестирование доступности. Но инструментов, которые есть в нашем распоряжении, самих по себе недостаточно, чтобы вселить в нас уверенность в том, что наше приложение действительно доступно. Что нам с этим делать?
Ключевым моментом здесь является понимание того, что компьютеры хороши в чем-то, а люди хороши в чем-то.
Компьютеры работают быстро, не нуждаются в отдыхе и могут безупречно выполнять инструкции (даже когда мы, люди, даем им неправильные инструкции!).
С другой стороны, люди лучше мыслят и рассуждают на более высоком уровне. Когда дело доходит до аудита доступности нашего приложения, мы можем сделать шаг назад и спросить: «Имеет ли это смысл? Могу ли я использовать это? Обеспечивает ли то, что мы создали, хороший пользовательский опыт?»
Итак, вместо того, чтобы конкурировать, почему бы не позволить людям и компьютерам работать вместе, чтобы обеспечить лучшее из обоих миров?
Как люди, мы можем решить, какие критерии важны, что стоит проверить и каким должно быть ожидаемое поведение. Мы можем кодифицировать эти требования как автоматизированные тесты. Затем компьютеры могут запускать наши тесты, и мы можем включать эти тесты в конвейер непрерывной интеграции (CI), чтобы предотвратить ухудшение доступности в нашем приложении.
Давайте посмотрим на пару примеров.
Пример 1: модальный
Для нашего первого примера давайте представим, что мы создаем модальное окно. Мы можем найти руководство по созданию доступных модальных окон в Руководстве по доступности веб-контента (WCAG), а также в документах WAI-ARIA Authoring Practices.
Наши модальные критерии будут выглядеть так:
- Модальное окно открывается при нажатии триггерной кнопки
- Модальное окно имеет соответствующую разметку aria (
aria-modal="true"
,role="dialog"
, aria-label) - Фокус отправляется на первый фокусируемый элемент внутри модального окна, когда оно открывается
- Фокус застрял внутри модального окна
- Модальное окно закрывается при нажатии кнопки «Закрыть», и фокус возвращается на кнопку-триггер
- Модальное окно закрывается при нажатии клавиши Escape, и фокус возвращается на кнопку триггера
- Модальное окно закрывается при нажатии в любом месте за пределами модального окна, и фокус возвращается на кнопку триггера
Наши следующие вопросы, естественно, будут такими: на каком уровне мы должны тестировать эти критерии и как мы можем написать эти тесты?
При написании тестов доступности правильным уровнем для их тестирования почти всегда будет модульное тестирование. Вам не нужно писать сквозной тест, чтобы убедиться, что ваше модальное окно имеет правильную разметку aria. Юнит-тестов будет достаточно.
Итак, как мы можем написать модульные тесты для этих критериев? Используя те же инструменты, которые вы уже используете для других модульных тестов. В основном я работаю в React, поэтому мои инструменты выбора — Jest в качестве моей тестовой среды с React Testing Library и User Event в качестве моих тестовых библиотек.
Библиотека тестирования React отлично подходит для рендеринга и взаимодействия с компонентами. User Event — это сопутствующая библиотека, которая помогает еще больше упростить тестирование взаимодействия с пользователем. Это отлично подходит для тестирования таких вещей, как поведение вкладок или запуск событий, которые прослушивает document
.
Пример 2: кликабельная кнопка Div
Рассмотрим другой пример. Ранее в этой статье мы обсуждали интерактивные элементы <div>
и некоторые функции, которые вам придется повторно реализовать самостоятельно, если вы решите использовать элемент, отличный от семантического элемента <button>
.
Наши критерии приемлемости для этой кнопки будут выглядеть так:
- Обработчик кликов вызывается при клике
- Обработчик кликов вызывается при нажатии клавиши Enter
- Обработчик кликов вызывается при нажатии пробела
- Обработчик кликов не вызывается при любом другом нажатии клавиши
- Элемент имеет атрибут
role="button"
Итак, где и как мы можем проверить эти критерии? Ваш ответ должен быть таким же, как и в прошлый раз. Мы можем написать модульные тесты для этого, используя наш тестовый фреймворк и выбранные библиотеки.
Ключевые выводы
Сегодня мы рассмотрели здесь много информации. Если вы что-то помните из этой статьи, я надеюсь, что это будут следующие пункты:
- Проверки статического анализа сами по себе не являются достаточными инструментами для обеспечения доступности вашего приложения.
- Важно провести предварительное тестирование вручную, чтобы убедиться, что люди действительно могут использовать ваше приложение с мышью, клавиатурой и/или программой чтения с экрана.
- Мы можем взять эти результаты из нашего ручного тестирования, исправить ошибки и написать автоматические тесты для предотвращения регрессии.
Спасибо, что прочитали, и спасибо за то, что вы выступаете за доступность.