Diff результатов

В библиотеке Axe-core механизм сравнения результатов доступности играет ключевую роль при автоматизации тестирования интерфейсов. В большинстве случаев требуется не просто запуск аудита и получение отчёта, но и выявление изменений между двумя состояниями приложения. Для этого используется концепция diff результатов, которая позволяет детектировать новые, исправленные или оставшиеся ошибки доступности.


Основные понятия

Результат аудита в Axe-core представляет собой объект, содержащий массивы violations, incomplete, passes и inapplicable. Каждый элемент массива содержит уникальный id правила, описание, рекомендации по исправлению, селекторы элементов и дополнительные метаданные.

Diff — это сравнение двух таких объектов: предыдущего состояния (baseline) и текущего состояния (actual). Цель сравнения — определить:

  • New violations — ошибки, появившиеся после изменений в DOM или логике приложения.
  • Resolved violations — ошибки, которые были устранены с момента последнего аудита.
  • Persistent violations — ошибки, которые остались без изменений.

Подход к реализации diff

Для корректного определения различий между результатами необходимо учитывать несколько факторов:

  1. Уникальность ошибки определяется по сочетанию id правила и target элементов, на которых ошибка проявляется.
  2. Контекст DOM может изменяться, поэтому селекторы элементов должны быть максимально стабильными (например, использование data-testid вместо сложных CSS-путей).
  3. Дополнительные свойства, такие как helpUrl и tags, позволяют классифицировать ошибки и фильтровать их при сравнении.

Простейший алгоритм diff:

function diffAxeResults(previous, current) {
  const prevMap = new Map();
  previous.violations.forEach(v => {
    v.nodes.forEach(node => {
      prevMap.set(`${v.id}-${node.target.join(',')}`, v);
    });
  });

  const newViolations = [];
  const resolvedViolations = [];
  const persistentViolations = [];

  current.violations.forEach(v => {
    v.nodes.forEach(node => {
      const key = `${v.id}-${node.target.join(',')}`;
      if (prevMap.has(key)) {
        persistentViolations.push({ ...v, node });
        prevMap.delete(key);
      } else {
        newViolations.push({ ...v, node });
      }
    });
  });

  prevMap.forEach((v, key) => {
    resolvedViolations.push(v);
  });

  return { newViolations, resolvedViolations, persistentViolations };
}

Особенности анализа

  • Группировка по правилам: После получения diff полезно агрегировать результаты по id правил. Это позволяет видеть, какие категории нарушений чаще всего появляются или исчезают.
  • Учёт динамического контента: Для приложений с часто меняющимся DOM следует сохранять baseline на стабильных страницах или компонентах, иначе diff может генерировать большое количество ложных “новых” ошибок.
  • Сравнение по хешу: Для ускорения сравнения и минимизации ошибок рекомендуется генерировать хеш для каждого node и использовать его при определении уникальности. Например, можно хешировать сочетание id, html, target.

Интеграция с CI/CD

Diff результатов особенно полезен при автоматизированном тестировании:

  • GitHub Actions, GitLab CI: Сравнение результатов на этапе pull request позволяет выявлять регрессии доступности.
  • Файл baseline: Сохраняется как JSON, который загружается на следующей итерации теста для сравнения.
  • Автоматическая отчетность: Система может уведомлять команду о новых нарушениях через email, Slack или генерацию HTML-отчета.

Пример использования в пайплайне:

const previousResults = require('./baseline.json');
const currentResults = await axe.run(document);

const { newViolations, resolvedViolations } = diffAxeResults(previousResults, currentResults);

if (newViolations.length > 0) {
  console.warn('Обнаружены новые ошибки доступности:', newViolations);
}

// Сохраняем текущий результат для следующего сравнения
fs.writeFileSync('./baseline.json', JSON.stringify(currentResults, null, 2));

Визуализация изменений

Для облегчения анализа изменений рекомендуется строить таблицы diff с указанием:

  • Названия правила (id)
  • Селектора элемента (target)
  • Описание нарушения (help)
  • Статуса (new, resolved, persistent)

Можно использовать генерацию HTML-таблиц с цветовой маркировкой:

  • Красный — новые ошибки
  • Зеленый — исправленные
  • Жёлтый — оставшиеся

Это помогает сразу видеть динамику изменений доступности на страницах.


Практические советы

  • Всегда фильтруйте результаты по уровню критичности (impact) — иногда low-приоритетные ошибки можно игнорировать на стадии diff, чтобы сосредоточиться на критических нарушениях.
  • Сохраняйте baseline после релиза стабильной версии, чтобы сравнение отражало реальные изменения.
  • При работе с фреймворками (React, Angular, Vue) важно учитывать, что виртуальный DOM может изменять селекторы, поэтому стоит использовать стабильные идентификаторы или атрибуты.

Дифф результатов в Axe-core превращает обычный аудит в инструмент контроля качества, позволяя не только обнаруживать нарушения, но и отслеживать их эволюцию во времени, интегрируя результаты в процессы разработки и поддержки веб-приложений.