- Проблемы с Axe, Jest и React Testing Library (RTL)
- Кастомизация
- Внедрение проверок доступности в сквозные тесты
- Отчеты о проблемах
- Настройка окружения и запуск тестов
- Триаж багов и владение тестами
- Аудиты
«У нас есть собственные стандарты доступности, которым следуют продуктовые команды, чтобы гарантировать соответствие фич требованиям Руководства по доступности веб-контента (WCAG). Наша специальная команда по обеспечению доступности поддерживает разработчиков в соблюдении этих рекомендаций на протяжении всего процесса разработки. Также мы привлекаем внешних ручных тестировщиков, которые специализируются на доступности.
В 2022 году мы начали дополнять свою стратегию по доступности, создавая автотесты доступности для десктопа, чтобы выявлять проблемы доступности в процессе разработки. Мы рассматриваем автоматизированное тестирование доступности как ценное дополнение к общей стратегии тестирования. Эта стратегия включает в себя привлечение людей с ограниченными возможностями на ранних этапах разработки, проведение анализа дизайна и прототипов с участием этих пользователей, а также ручное тестирование всех вспомогательных технологий. Автоматизированные инструменты могут упустить нюансы доступности, требующие человеческой оценки, например удобство программ чтения с экрана. Также эти инструменты могут подсвечивать проблемы с дизайном некоторых продуктов.
Несмотря на эти продвижения, мы стремились интегрировать инструменты проверки доступности в тестовые фреймворки как часть общей стратегии тестирования. В идеале мы надеялись добавить еще один уровень поддержки, интегрировав проверку доступности непосредственно в имеющиеся фреймворки, чтобы владельцы тестов могли удобнее добавлять свои проверки, а еще лучше — вообще не думать о добавлении проверок.
Первые проблемы
Axe, Jest и React Testing Library (RTL)
Мы выбрали Axe, популярный и легко настраиваемый инструмент тестирования доступности, благодаря его широким возможностям и совместимости с нашими фреймворками сквозного тестирования. Axe проверяет соответствие широкому спектру рекомендаций по доступности, большинство из которых соответствуют критериям из WCAG, и делает это таким образом, чтобы свести к минимуму количество ложных срабатываний.
Изначально мы изучали возможность встраивания проверок доступности Axe непосредственно в наш фреймворк React Testing Library (RTL). Обернув метод рендеринга RTL кастомной функцией рендеринга, включающей проверку в Axe, мы могли бы устранить множество сложностей в рабочем процессе разработчиков. Однако мы сразу же столкнулись с проблемой настройки Jest в Slack. Проверка доступности через отдельную конфигурацию Jest работала, но требовала от разработчиков писать тесты специально для доступности, чего мы хотели избежать. Переделка нашей кастомной настройки Jest была сочтена слишком сложной и не стоила затрат времени и ресурсов, поэтому мы сосредоточились на фреймворке Playwright.
Лучшее решение для Axe — Playwright
Поскольку Jest мы исключили из кандидатов для Axe, мы обратились к Playwright. Он поддерживает тестирование доступности в Axe с помощью пакета @axe-core/playwright. Axe Core предоставляет большую часть того, что вам понадобится для фильтрации и настройки проверок доступности. В нем из коробки предусмотрен метод исключения, позволяющий не анализировать определенные правила и селекторы. Также есть набор тегов доступности для дальнейшего указания типа проводимого анализа (‘wcag2a
‘, ‘wcag2aa
‘ и т. д.).
Нашей первоначальной целью было «заложить» проверки доступности непосредственно в методы взаимодействия Playwright, такие как клики и навигация, чтобы автоматически запускать Axe, не требуя от авторов тестов его явного вызова.
В процессе работы над этой целью мы обнаружили, что главная проблема такого подхода связана с объектом Locator в Playwright. Объект Locator предназначен для упрощения взаимодействия с элементами страницы путем управления автоматическим ожиданием, загрузкой и обеспечением полного взаимодействия с элементом перед выполнением любого действия. Это автоматическое поведение является неотъемлемой частью способности Playwright создавать стабильные тесты, но оно усложнило наши попытки встроить Axe в фреймворк.
Проверки доступности должны выполняться, когда вся страница или ключевые компоненты полностью отрисованы, но локатор Playwright проверяет готовность только отдельных элементов, но не всей страницы. Модификация локатора может привести к ненадежности, поскольку проблемы с доступностью могут остаться незамеченными, если проверки были запущены не в нужное время.
Другой вариант — использование устаревших методов, таких как waitForElement
, для управления запуском проверок доступности, также был проблематичным. Эти устаревшие методы не оптимизированы, что приводит к снижению производительности, потенциальному дублированию ошибок, и конфликтам с моделью абстракции, которой следует Playwright.
Поэтому, хотя встраивание проверок Axe в основные методы взаимодействия Playwright сначала казалось идеальным, сложность внутренних механизмов Playwright потребовала от нас поиска дополнительных решений.
Кастомизация
Чтобы обойти эти препятствия, мы решили пойти на некоторые компромиссы, сохранив при этом приоритет на упрощение задач разработчикам. Мы остановились на Playwright, потому что он предлагал гибкие способы выборочного пропуска или активации проверок доступности, позволяя легче управлять тем, когда и где эти проверки выполняются. Кроме того, в Axe Core реализованы замечательные функции кастомизации, такие как правила фильтрации и теги доступности.
Используя пакет @axe-core/playwright, мы можем описать процесс проверки доступности:
- Тест Playwright заходит на страницу
- Axe анализирует страницу
- Отфильтровываются предварительно прописанные исключения
- Найденные проблемы доступности и артефакты сохраняются в файл
Сначала мы создали главную функцию runAxeAndSaveViolations
и настроили область видимости, используя возможности класса AxeBuilder
.
- Мы хотели проверить соответствие требованиям WCAG 2.1, Уровни A и AA.
constructor(page: Page) { this.page = page; this.defaultTags = ['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa']; this.bodyText = ''; this.baseFileName = `${test.info().title}-violations`.replace(/\//g, '-'); A11y.filenameCounter = 0; }
- Мы составили список селекторов, которые нужно исключить из репорта о проблемах доступности. Они делятся на две основные категории:
- Известные проблемы с доступностью — проблемы, о которых мы знаем и которые уже были зарегистрированы.
- Правила, которые не применяются — правила Axe, выходящие за рамки подхода, принятого в Slack.
// Exclude selectors for known bugs and elements that we do not consider accessibility issues constants.ACCESSIBILITY.AXE_EXCLUDED_SELECTORS.forEach((excludedSelector) => { axe.exclude(excludedSelector); });
- Мы также хотели отфильтровать дубликаты и уровень серьезности. Мы создали методы для проверки уникальности каждого нарушения и отсеивания дубликатов. Мы решили репортить только нарушения, которые считаются
Critical
в соответствии с WCAG.Serious
,Moderate
иMild
— это другие возможные уровни серьезности, которые можно добавить в будущем.
/** * Filter violations based on criticality, then ensure we * are removing any duplicate violations within a single test file * Please note: this only removes duplicates on a single test, not the entire run */ private filterAndRemoveDuplicateViolations(violations: Violation[]) { return violations .filter((violation) => ['critical'].includes(violation.impact)) .map(this.mapViolation) .filter(this.isUniqueViolation.bind(this)); }
- Мы воспользовались моделью фикстур Playwright. Это способ создавать и уничтожать (teardown) состояние вне самого теста. В рамках нашего фреймворка мы создали пользовательскую фикстуру под названием
slack
, которая предоставляет доступ ко всем нашим API-вызовам, UI-представлениям (views), рабочим процессам (workflows) и утилитам, связанным со Slack. Используя такие фикстуры, мы получаем доступ ко всем этим ресурсам непосредственно в тестах, без необходимости каждый раз проходить весь процесс настройки. - Мы перенесли наш помощник доступности в уже существующую фикстуру
slack
. Это позволило вызывать его непосредственно в спецификации тестов, минимизируя операции для авторов тестов.
// Run accessibility checks and get the violations await slack.utils.a11y.runAxeAndSaveViolations();
- Также мы воспользовались возможностью кастомизации
test.step
в Playwright. Мы добавили кастомный тег «Выполнение проверок доступности вrunAxeAndSaveViolations
«, чтобы проще определять, где произошло нарушение доступности:
Test Steps - Before Hooks - apiResponse.json— ../support/api/api.ts:137 - browserContext.waitForEvent— ../support/workflows/login.workflow.ts:273 - Running accessibility checks in runAxeAndSaveViolations— ../support/utils/accessibility.ts:54
Внедрение проверок доступности в сквозные тесты
Чтобы запустить проект, мы создали набор, идентичный набору тестов критической функциональности Slack. Мы переименовали набор, чтобы было понятно, что он предназначен для тестов доступности, и настроили его на неблокирующий запуск. Это означало, что разработчики будут видеть результаты тестов, но неудача или нарушение доступности не помешают им слить свой код в продакшен. Этот первоначальный набор включал в себя в общей сложности 91 тест.
Стратегически мы продумали внедрение проверок доступности в этих критических тестах. В целом мы стремились добавлять проверку доступности для каждого нового представления, страницы или потока, рассматриваемого в тесте. В большинстве случаев это означало вставку проверки непосредственно после нажатия любой кнопки или ссылки, ведущей к навигации. В других сценариях проверку доступности нужно было вставлять после входа второго пользователя или после перенаправления.
Важно было убедиться, что одно и то же представление не анализируется дважды в одном тесте или дважды в нескольких тестах с одним и тем же UI-потоком. Подобное дублирование привело бы к появлению ненужных сообщений об ошибках и сохранению артефактов, а также замедлило бы тесты. Мы также старались размещать вызовы Axe только после полной загрузки страницы или представления, и рендеринга всего содержимого.
При таком подходе нам нужно было хорошо знать приложение и контекст каждого тест-кейса.
Отчеты о проблемах доступности
Мы потратили некоторое время на итерации по созданию отчета о проблемах доступности. Изначально мы создали простой текстовый файл для сохранения результатов локального запуска в папке с артефактами. Несколько разработчиков дали нам первые отзывы и попросили сделать скриншоты страниц, на которых были обнаружены нарушения доступности. Для этого мы интегрировали функцию скриншотов Playwright и стали сохранять эти скриншоты вместе с текстовым отчетом в папке с артефактами.
Чтобы сделать отчеты более логичными и читабельными, мы использовали Playwright HTML Reporter. Этот инструмент не только собирает результаты тестов, но и позволяет прикреплять к HTML-отчетам такие артефакты, как скриншоты и отчеты о проблемах доступности. Настроив HTML-отчет, мы смогли отображать все артефакты доступности, включая скриншоты и подробные отчеты доступности, в одном документе.
Наконец, мы хотели, чтобы сообщение об ошибке было полезным и простым для понимания, поэтому написали код для извлечения ключевых фрагментов информации о проблеме. Также мы настроили вывод сообщений в отчеты и в консоль, после парсинга и сокращения текста сообщений.
Error - [A11Y]: CRITICAL Description: Ensures an element's role supports its ARIA attributes Help: Elements must only use supported ARIA attributes Target selector: #add-channel-tab Fix all of the following: ARIA attribute is not allowed: aria-selected="false" HTML: <button class="c-button-unstyled addTab__brBMy c-tabs__tab js-tab" data-qa="unstyled-button"
Настройка окружения и запуск тестов
После интеграции проверок Axe и настройки тестового набора нам нужно было определить, как и когда разработчики должны их запускать. Чтобы упростить процесс для разработчиков, мы ввели флаг окружения A11Y_ENABLE
для управления активацией проверок доступности в нашем фреймворке. По умолчанию мы установили флаг на false
, чтобы предотвратить ненужные запуски.
Такая настройка позволила нам предложить разработчикам следующие варианты:
- Тестирование по требованию: Разработчики могут вручную включить флаг, когда им нужно запустить проверку доступности локально в своем отделе.
- Запуск по расписанию: Разработчики могут настроить периодические запуски в непиковые часы. В Buildkite настроен ежедневный прогон регрессии для передачи результатов тестирования доступности в Slack-канал с ежедневной периодичностью.
- Интеграция в CI: По желанию флаг может быть включен в пайплайны непрерывной интеграции для тщательного тестирования перед слиянием значительных изменений.
Триаж багов и владение тестами
Владение отдельными тестами и наборами часто становится горячей темой, когда речь заходит об сопровождении тестов. После того как мы добавили вызовы Axe в критические потоки в сквозных тестах Playwright, нам нужно было решить, кто будет отвечать за устранение проблем с доступностью, обнаруженных с помощью нашей автоматизации, и кто будет заниматься сопровождением существующих тестов.
Мы позволяем разработчикам самим создавать и поддерживать свои тесты. Чтобы помочь разработчикам лучше понять изменения во фреймворке и новую автоматизацию доступности, мы создали документацию и совместно с внутренней командой Slack по обеспечению доступности разработали комплексный процесс устранения проблем, который бы вписался в существующий рабочий процесс по устранению проблем с доступностью.
Внутренняя команда Slack по обеспечению доступности уже наладила процесс сортировки (триажа) и маркировки входящих проблем с доступностью, используя внутренние стандарты доступности Slack в качестве руководства. Чтобы усовершенствовать этот процесс, мы создали новый тег «автоматизированная доступность» для проблем, обнаруженных с помощью автоматизации.
Чтобы упростить каталогизацию этих проблем, мы настроили рабочий процесс Jira в нашем канале оповещений, который создавал тикет Jira с предварительно заполненным шаблоном. Тикет создается в рабочем процессе, автоматически помечается тегом automated accessibility
и помещается в эпик в Jira для сортировки.
A11Y Automation Bug Ticket Creator - Automatically create JIRA bug tickets for A11Y automation violations Hi there, Would you like to create a new JIRA defect? Button clicked. A new JIRA bug ticket, A11YAUTO-37, was created. What to do next: 1. Please fill out all of the necessary information listed here: https://jira.tinyspeck.com/browse/A11YAUTO-37. 2. Please add this locator to the list of known issues and include the new JIRA bug ticket in the comment.
Аудиты
Мы регулярно проводим аудит вызовов Playwright, чтобы проверить, не дублируются ли вызовы Axe, и обеспечить надлежащий охват проверок доступности.
Мы разработали скрипт и флаг окружения специально для облегчения процесса аудита. Аудит можно проводить как в тестовой песочнице (для аудита всего набора), так и локально (для отдельных тестов или подмножеств). При проведении аудита запуск скрипта позволяет сделать скриншот каждой страницы, на которой выполняется вызов Axe. Затем скриншоты сохраняются в папке, и их легко сравнить, чтобы обнаружить дубликаты.
Этот процесс является более ручным, чем нам хотелось бы, и мы ищем способы устранить этот шаг, возможно, прибегнув к помощи искусственного интеллекта, который будет выполнять аудит за нас — или например добавлять вызовы доступности на каждую новую страницу или представление, тем самым устраняя необходимость выполнять какой-либо аудит вообще.
Что в планах
Планируем продолжить сотрудничество с внутренней командой Slack по обеспечению доступности, чтобы разработать небольшой набор блокирующих тестов. Эти тесты будут сосредоточены на основных фичах Slack, с акцентом на навигацию по клавиатуре.
Мы также хотели бы изучить подходы к ИИ-постобработке результатов тестов, и рассмотреть возможность привлечения ИИ-помощников к аудиту наборов для уточнения точек проверки доступности, чтобы уменьшить нагрузку на разработчиков.
Размышления по итогам
В этом проекте нам пришлось пойти на неожиданные компромиссы, балансируя между ограничениями инструментов автоматизации тестирования и целью снизить нагрузку на разработчиков. Хотя мы не смогли полностью интегрировать проверки доступности в наши фронтенд-фреймворки, мы добились значительных успехов в достижении этой цели. Мы упростили для разработчиков процесс добавления проверок доступности, обеспечили простоту интерпретации результатов тестирования, предоставили понятную документацию и упростили процесс сортировки проблем в рабочих процессах Slack. В итоге мы смогли добавить тестовое покрытие доступности в наш продукт, обеспечив удобство некоторым нашим клиентам.
Автоматизированные проверки Axe снизили зависимость от ручного тестирования и теперь дополняют другие формы тестирования — ручное и исследования юзабилити. В настоящее время разработчикам все еще приходится вручную добавлять проверки доступности, но мы заложили основу для того, чтобы упростить этот процесс с помощью ИИ.
Такие препятствия, как сложности с фреймворком или конфигурациями, не должны отбить у вас желание автоматизировать тесты доступности. Даже если невозможно полностью спрятать автоматизированные проверки за кулисами фреймворка, есть способы сделать работу эффективной, сосредоточившись на удобстве разработчиков.»