dainiel

自动化你的无障碍测试

原文链接: 24ways.org

自动化你的无障碍测试

大家都希望把无障碍做得更好。这可以引出一系列的问题,像是:我们怎样才能让站点更好?怎么测试已经做好的工作?我们应该每天都花时间人工测试站点吗?或者只是期望团队的成员记得检查哪些改动是否无障碍化了?

这就是需要自动化无障碍测试的场景。我们可以着手于自动化测试,同时在任何人进行pull请求时,让其自动运行,哪怕是端对端测试也适用。

然而,自动化测试不能涵盖所有情况。只有20到50%的无障碍问题可以被自动检测到。例如,你还不能自动对比图片里的alt属性,还有一些需要手动处理的屏幕阅读器测试也是。为了确保我们的站点尽可能的无障碍化,我们依旧需要执行人工测试,这点稍后会提及。

首先,我将会说明我是如何在一个电子商务页面实行自动化测试的,同时会分享其中踩到的坑。

选取正确的工具

创建自动化无障碍测试,最难的一点,但也是最重要的部分,就是选择正确的工具。

我们通过研究aXe CLI开始,但是不久意识到它不能满足我们的需求。它不能检查需要用户登录的页面,因此当测试产品页面时,我们不能测试任何涉及用户登录的页面。取而代之,我们投奔了Pa11y阵营。它的beforeScript意味着我们可以登录页面,同时测试例如订单历史的页面。

下面的例子展示了如何在beforeScript这一步完成一个登录表单,然后在测试页面前等待登录完成:

beforeScript: function(page, options, next) {
  // An example function that can be used to make sure changes have been confirmed before continuing to run Pa11y
  //这个示例函数可以用来确定在继续运行Pa11y前,相关变化已经确保无误
  function waitUntil(condition, retries, waitOver) {
    page.evaluate(condition, function(err, result) {
      if (result || retries < 1) {
        // Once the changes have taken place continue with Pa11y testing
        waitOver();
      } else {
        retries -= 1;
        setTimeout(function() {
          waitUntil(condition, retries, waitOver);
        }, 200);
      }
    });
  }

  // The script to manipulate the page must be run with page.evaluate to be run within the context of the page
  // 处理页面的脚本必须和在页面上下文里的page.evaluate一起运行
  page.evaluate(function() {
    const user = document.querySelector('#login-form input[name="email"]');
    const password = document.querySelector('#login-form input[name="password"]');
    const submit = document.querySelector('#login-form input[name="submit"]');
    user.value = 'user@example.com';
    password.value = 'password';
    submit.click();
  }, function() {
    // Use the waitUntil function to set the condition, number of retries and the callback
    waitUntil(function() {
      return window.location.href === 'https://example.com';
    }, 20, next);
  });
}

waitUntil回调允许测试被延迟到我们的测试用户成功登录后再执行。

挑选工具时需要考虑另外件事是其产生的错误消息类型。aXe会把有相同错误的元素整合在一起,这样问题列表会易读很多,并且鉴别最普遍的问题也会容易得多。例如,这里是一些色彩对比度不足的元素。

8个违反“颜色对比度”的情况
确保前后色的颜色对比相符
WCAG 2 AA对比度入门。相关的无效元素:
  - #maincontent > .make_your_mark > div:nth-child(2) > p > span > span
  - #maincontent > .make_your_mark > div:nth-child(4) > p > span > span
  - #maincontent > .inform_your_decisions > div:nth-child(2) > p > span > span
  - #maincontent > .inform_your_decisions > div:nth-child(4) > p > span > span
  - #maincontent > .inform_your_decisions > div:nth-child(6) > p > span > span
  - #maincontent > .inform_your_decisions > div:nth-child(8) > p > span > span
  - #maincontent > .inform_your_decisions > div:nth-child(10) > p > span > span
  - #maincontent > .inform_your_decisions > div:nth-child(12) > p > span > span
欲知详情,请查看: https://dequeuniversity.com/rules/axe/2.5/color-contrast

aXe也提供链到它们页面的链接,在哪里可以讨论修复问题的最好方式。 对比而言,Pa11y列出了每个可以导致冗长列表的错误。然而,其确实提供了修复问题的有用建议,例如使用某种颜色的交替遮盖:


• 错误: 这个元素在一致性等级上没有足够的对比度。
  期望至少4.5:1的对比度,但是元素中的文本只有2.96:1的对比度。
  ⎣ WCAG2AA.Principle1.Guideline1_4.1_4_3.G18.Fail
  ⎣ #maincontent > div:nth-child(10) > div:nth-child(8) > p > span > span
  ⎣ <span style="color:#969696">Featured products:</span>

整合到我们的构建流里面

我们认为运行无障碍测试的最好时间是伴随着端对端测试。我们用一个Jenkins任务来检测预发布站点的变化,然后触发端对端测试,和我们的无障碍测试循环进行。我们的Jenkins任务会取回包含Pa11y脚本文件和npm包manifest的Github仓库内容。

一旦Jenkins克隆了仓库,其会安装依赖同时通过以下代码执行测试:

`npm install && npm test`

把要测试的URL打包进测试脚本意味着我们不需要命令行式的测试方法,这样我们只需要把要测试的URL列在Jenkins CLI里面就行了。这是有效但是也混乱的方式,它会让人搞不清楚哪些URL正在测试。

在办公室中间我们有一台展示Jenkins面板的显示器,通过它我们可以看到无障碍测试是通过还是失败。团队里的每个人有查看Jenkins log的权限,每当构建失败时他们都可以看到原因同时修复问题。

修复问题

正如前面提到的一样,Pa11y可以生成需要修改区域的长列表,这个列表可能会冗长且十分震撼。我建议仔细检查下列表,看看哪些问题出现最频繁然后先修复这些。例如,我们首先有一堆颜色对比度相关的错误,特别是一个灰色的阴影。通过把这个颜色弄得更深,错误数有所降低,这样我们可以集中精力处理剩余的问题。

我喜欢做的另外一件事是进行快速修复,例如给图片添加alt文本。这些小事可以让我们直接产生效果,给我们时间处理一些例如修复tabindex的细节问题,或者和我们的设计师讨论改变站点元素对比度的问题。

人工测试

给我们的网站添加自动化测试以检查无障碍支持情况是很棒的,但是就如我前面所提到的一样,这种方式只能覆盖20-50%的潜在问题。为了提升这点,我们也需要手动测试,要么靠我们自己要么咨询下其他人。

测试站点的方法是放弃鼠标或者触控板,只使用键盘来和站点交互。这就可以让我们检查例如tab次序的项目,确保彩蛋项、按钮等等都可以在没有鼠标的情况下使用。不同的操作系统命令也会有所不同,不过线上会有一些进一步学习相关知识的教程。

添加altaria-label来移除错误是蛮好的,但如果这些没有什么意义,那它们到底有什么用?我们可以使用屏幕阅读器检查alt是否准确的表达出图片。有一些检查项也是很好的途径: ARIA role是否有效,其是否正确表意元素,以及如何与其交互。当使用屏幕阅读器测试站点时,需要特别记住不是所有的屏幕阅读器都是一样的,有些阅读器与站点的交互方式与其他的会有所不同。

可以直接去找那些有些不同需求和能力缺陷的人来测试你的站点。大家在体验站点时会出于不同目的:有的是永久的、有的是临时的、有的甚至是场景式的。他们可能用你从未想过的方式和站点交互,因为扩广你的知识和认知也是个好办法。

建议和技巧

还有一个使用Pa11y会导致的问题就是我们可能会发现那些无力解决的难题。最好的例证就是Facebook插入到我们页面里的1像素图片。因此,我们写了一个小函数来检查这样的错误,忽略掉哪些我们不能修复的。

const test = pa11y({
  ....
  hideElements: '#ratings, #js-bigsearch',
  ...
});

const ignoreErrors: string[] = [
  '<img src="https://books.google.com/intl/en/googlebooks/images/gbs_preview_button1.gif" border="0" style="cursor: pointer;" class="lightbox-is-image">',
  '<script type="text/javascript" id="">var USI_orderID=google_tag_mana...</script>',
  '<img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=123456789012345&ev=PageView&noscript=1">'
  ];
const filterResult = result => {
    if (ignoreErrors.indexOf(result.context) > -1) {
      return false;
    }
    return true;
};

首先我们需要关注的是修复主要问题,因此我们添加了忽略提示和警告的规则。这可以让列表或者错误更少,以让我们把精力花在修复例如颜色对比度和alt丢失等主要问题上。忽略掉的提示和警告可以在这些大的问题解决后添加回来。

const test = pa11y({
  ignore: [
    'notice',
    'warning'
  ],
...
});

Jenkins注意事项

使用Jenkins时我们遇到了一些问题。有时Jenkins会显示构建通过了但实际失败了。这是因为PhantomJS抛出错误,或者测试没有通过第一个URL导致的Pa11y超时引起的。Pa11y最近发布了使用headless Chrome替代PhantomJS的新beta版本,因此希望这些问题会尽量少的发生。

我们试了一些方法来解决这些问题。首先我们添加了错误处理机制:迭代测试URL数组以便如果意想不到的错误发生,我们可以在捕获的同时带着任务失败的错误信息退出进程(使用process.exit(1))。

for (const url of urls) {
  try {
    console.log(url);
    let urlResult = await run(url);
    urlResult = urlResult.filter(filterResult);
    urlResult.forEach(result =&gt; console.log(result));
  }
  catch (e) {
    console.log('Error:', e);
    process.exit(1);
  }
}

我们也会遇到session断开或者类似错误引起的未处理拒绝。为了避免Jenkins显示构建通过了但实际没有执行任何测试的情况,当未处理拒绝或者未捕获异常发生时,我们会让Jenkins把任务处理为失败状态:

process.on('unhandledRejection', (reason, p) =&gt; {
  console.log('Unhandled Rejection at:', p, 'reason:', reason);
  process.exit(1);
});
process.on('uncaughtException', (err) =&gt; {
  console.log('Caught exception: ${err}n');
  process.exit(1);
});

Now it’s your turn

现在轮到你了

就是这样!这就是我们在实践中自动化无障碍测试的方案,这样我们提升了站点同时对每个人都更加无障碍化。我希望我们的经验可以帮助你自动化无障碍测试,同时让所有站点的无障碍化都能更上一层楼。