Background
Automated tools have advanced a lot over the last few years, and we should be able to add accessibility testing either within our CI/CD process. At the very least, we should be able to evaluate a daily snapshot, which would allow us to test various components of Core with an automated tool. Automated testing will never catch 100% of WCAG 2.1 issues, but it will catch the easiest to catch barriers.
What most developers have focused on recently is Deque's axe core. This is both open source, and built to avoid false positives. Deque's rule-set and accompanying resource library helps developers understand and resolve issues when they arise. A Deque study suggests that up to 57% of accessibility issues can be identified through axe, which is much higher than previous estimates.
Axe is incorporated into the base of many tools like Google Lighthouse, Accessibility Insights, Pa11y and many others. There is even a Drupal module (Accessibility Scanner) that uses axe to scan the site.
This is in some ways getting back to this Green by 2014 initiative, to build in more automated testings, including an accessibility Test Swarm. Much of this was discussed at DrupalCon Portland in 2014.
Proposal
Maintaining Drupal's accessibility will be easier if we are able to easily and regularly evaluate key functionality.
We need to be able to define the key functionality that we would want to test, would likely need to use a module like Realistic Dummy Content, to ensure that there is more there than just Core, but might also want to use Umami.
It would then be possible to either crawl the dummy site, or hit a set number of URLs. The advantage with the latter is that it would be easier to control, and thus understand if there is an increase or decrease over time. Perfection is not the goal, the goal is to be more inclusive today than you were yesterday.
Build on our work
The CivicActions Drupal team discussed this briefly earlier in the week. Would be terrific to be able to build on some of the existing initiatives within the Drupal community.
Nightwatch is already built in, and so it would be trivial to add in nightwatch-axe-core to make accessibility testing easier. Some folks use Cypress & Cypress-axe, but best to build on what we have.
If we are moving to GitLab CI/CD, then there is support for pa11y already. We'd need to make sure that axe-core is included. Always great when others have paved the way. We should be able to publish Accessibility Reports with GitLab as well.
The Pa11y Dashboard might be the easiest way to provide a historical view.
Pages to scan - Phase 1
This isn't intended to be a complete list. This could all be done with Pa11y & axe-core.
- Home page
- Search
- List View
- Table View
- Sample article content type
- Sample blog content type
- 404 page
- Log in
- Create new account
- Reset your password
- Admin - Content
- Admin - Content: Add Article
- Admin - Content: Add Blog
- Admin - Structure
- Admin - Structure: Block layout
- Admin - Structure: Create Content type
- Admin - Structure: Create Taxonomy
- Admin - Structure: Create View
- Admin - Appearance
- Admin - Appearance: Configure Olivero
- Admin - Extend
- Admin - Configuration
- Admin - Configuration: Basic site settings
- Admin - People
- Admin - People: Add user
- Admin - People: Permissions
- Admin - Reports
- Admin - Reports: Status report
- Admin - Help
- Admin - Help: Text editor
Functions to test - Phase 2
We would likely need to use start writing Nightwatch-axe-core tests to evaluate the interactive functionality.
- Search
- Login
- Admin - Content: Add Article
- Admin - Structure: Create Content type
- Admin - Structure: Create View
---
We should keep things like https://github.com/tenon-io/tenon-drupal and https://github.com/Asqatasun/Asqatasun on our radar as a potential way to add accessibility checking in an automated fashion.
- https://github.com/dequelabs/axe-core
- https://github.com/crawlkit
- http://pa11y.org/
- https://github.com/Asqatasun/Asqatasun
- https://github.com/Tanaguru/Tanaguru
- https://tenon.io/
- https://github.com/tenon-io/tenon-drupal
- https://www.drupal.org/project/siteimprove
- https://www.drupal.org/project/accessibility_scanner
Earlier efforts to build a JavaScript test swarm: https://groups.drupal.org/node/366873
Comments
Comment #2
mgiffordAlso worth looking at https://www.axe-core.org/ & https://github.com/pa11y
Would be excellent to have this as part of the patch review process. There was a TestSwarm project that was used early on on D8 using QuailJS [@1844046] but that project has died.
Some other links.
https://www.drupal.org/sandbox/kevee/2026475
https://dev.acquia.com/podcast/98-accessibility-testing-tools-and-quail-...
Comment #3
mgiffordMarking this as part of #1299710: [meta] Automate the coding-standards part of patch review
Comment #4
kreynen commentedFor what it's worth, we've been evaluating Tenon.io at CU. Their API is really straightforward (Send url... get back JSON). It has been easy to integrate with both our UI for users to check content as well as with our CI, but we found that a number of the tests either weren't running or didn't catch an issue we thought would be easy to detect like https://www.colorado.edu/tenon-tests/content/114-select-element-less-5-o...
When we met with the vendor, they quickly acknowledged the issues and committed to having fixes pushed before the CSUN Assistive Technology Conference on 3/22.
At the enterprise level, a managed version of Tenon can be brought "in-house". At that point, you aren't limited by the number of api calls but only by the speed of running the tests on the backlog of requests.
Comment #5
mgifford@kreynen want to give a +1 on tenon.io
Karl's been a great advocate in the web accessibility community. He's actively investing in his platform.
Also: "We offer special discounts for open source projects, local governments, public school systems (primary/ secondary), community colleges, 501C(3) non-profits, web developer training schools/ bootcamps." - https://tenon.io/pricing.php
And they made sure there was a Drupal module built under the GPL - https://www.drupal.org/project/tenon_io
It's just not open source which is why I didn't list it here. Not as easy to integrate and propagate.
Comment #6
kreynen commentedBut easier to maintain :)
Comment #7
mgiffordAdding related links to refer to.
Comment #8
mgiffordComment #9
mgiffordThis is a good review from WordPress https://humanmade.com/2018/05/17/automated-accessibility-testing-during-...
Comment #10
andrewmacpherson commentedLots of stuff discussed in the #accessibility Slack channel today, with @modulist and myself. Here's a recap:
As for the how/what/when to test, I think a couple of approaches together:
Aside: a couple of years back, at a conference, I heard someone from a big a11y consultancy (not saying which....) describe a similar approach. It was to do with all these drive-by a11y lawsuits proliferating in the US. Turns out a lot if these came from a law office that was using the WAVE API to spider sites, then send them a lawsuit. So armed with the knowledge that WAVE reports were the risk for their clients, they made a custom assertion for Behat tests called "wave reports no errors" and did that at the start and end of every Behat test. This is about as black-hat as a11y gets (WAVE was the one generating the lawsuits, so that's the one we satisfy). But in a CI context it makes some sense I think.
An interesting point about putting generic a11y rulesets into CI, is how do we act on the results?
Can you refine rulesets specifically for Drupal though?
An interesting thing to do would be to set up a way to view the report for the current state of head, and maybe set some alert if we try to tag a new stable 8.x release candidate which has more warnings than the current supported release
You’d have to re-set your test every time Tenon and aXe do an update, like when 2.1 guidelines were added.
Comment #11
andrewmacpherson commented@modulist deserves an issue credit for contributions in the Slack chat.
Comment #12
kreynen commented100% agree
Since I mentioned that we were evaluating Tenon.io in #4, I'll just add a bit about what we found in that evaluation. We decided not to license Tenon since it had too many false negatives (meaning it didn't catch obvious accessibility issues). We left our examples of things we thought should fail at https://www.colorado.edu/tenon-tests/. Some of these are more nuanced and required an understanding of what the test was actually testing, but several of the tests listed in UI just didn't fail like https://www.colorado.edu/tenon-tests/content/114-select-element-less-5-o.... That test should be really straightforward, but it would always appear to have passed.
Giving users a false sense of being WCAG compliant with tests that pass incorrectly is just as much an issue for us as tests that fail incorrectly.
We decided that the way UNL had implemented the aXe tests along with other metrics in https://github.com/UNLSiteMaster/site_master was a better fit for our needs. That project runs fewer tests with more confidence in each test and is only testing things that are likely to be something the user can fix. Instead of looking at a number of tests services like Tenon or Site Improve and going with the service that had the most tests, we are treating a combined score of failed accessibility tests, spelling errors and broken links as dead canaries that indicate a site is being poorly maintained and needs a manual review.
Tenon may still be a good fit for scanning contrib, but it wasn't a good fit for our needs.
Comment #13
andrewmacpherson commentedI would also say that false positives don't worry me, but they add a potentially massive review burden and/or issue friction.
In an ideal world, I'd like some way of tracking the false positives and advisory warnings. So we could say "Manually reviewed by andrewmacpherson on 2018-10-15, works-as-designed". Preferably somewhere that non-a11y contributors could check, say before RTBC, or before committing a patch. Maybe a code comment in the relevant Drupal test file about a false positive we're expecting?
Comment #14
mgiffordWould be good to have more folks looking at incorporating https://www.previousnext.com.au/blog/automate-your-drupal-accessibility-...
The more things can be tied into workflows like CircleCI the more likely developers will pay attention to these automated tests.
Comment #15
mgiffordAccessibility efforts need to be able to demonstrate that the product is more accessible today than it was yesterday.
The Drupal Accessibility Scanner module has a nice mechanism to see changes over time.
Like many accessibility tools, it is following the best practices of using Deque's open source axe-core engine. Axe has been developed to avoid false positives. Axe does give warnings as well as errors, but these need to be manually validated.
To replicate & advance on the TestSwarm which was part of D7's history with QuailJS, I would recommend using Pa11y to with the axe engine (much as described in this blog post for GitHub Pages). I do not know if the Pa11y Integration module is of any use, but think not.
Ideally before every commit (and possibly with every PR) Drupal core would be tested for axe errors through the CI/CD pipeline to see if axe reports any errors. We should be able to say (at some point) that all Drupal Core is "axe clean" or has no axe errors. We would need to test sample pages against with pa11y (with axe) for the Core themes. This would absolutely need to include the home page, search and login page, but should also include sample content types and standard views.
It should also include tests for the authoring/admin side, as this is also part of our commitment to WCAG 2.1 AA. Fortunately, there are some resources for how to manage logins with pa11y that might come in handy. Also from Albert Albala's blog here. There's also docs for this too. I don't know what paths we will need to explore on the admin side, but we should start with the ones used most commonly by editors and administrators and move from there.
This will catch many common accessibility issues early. Unfortunately, it is only between 30-60% of them, but it is sizeable and important. Pa11y catches the pages as they are generated and does not evaluate dynamically changing content. Cypress-axe can do that, but first lets get pa11y set up to evaluate the basics.
Comment #16
mgiffordComment #17
mgiffordComment #18
mgiffordWanting to add a note about the Pa11y Integration module.
Comment #19
mgiffordComment #20
itmaybejj commentedThis would be good for developers.
I don't know if it helps, but I will be tagging a v2 -dev release of Editoria11y in the coming week that adds a REST API callback for issues discovered and generates a dashboard. Something like that might work well for editorial issue detection, and could be batch updated by a headless crawler if I set up a role/permission to let the crawler write to the database.
Comment #21
rkollerJust reposting my thoughts from Slack where @mgifford asked me. The suggested pa11y solution sounds like a good choice since it is based on aXe. If pa11y would be preferably over the other solutions brought up in the other comments and the IS i am unable to assess. At least one advantage to note is that for pa11y there is already an existing integration with gitlab out of the box available according to their docs: https://docs.gitlab.com/ee/user/project/merge_requests/accessibility_tes... which i would consider as a big plus.
and in regards of the general testing strategy i've stumble across the following article: https://blog.testproject.io/2022/02/07/accessibility-testing-best-practi... which brought up one or two good additional ideas.
The author suggests that linting would be worth a thought as an initial step. So would it make sense to add instructions to the developer documentation how to set up the coding environment for the work in drupal core and contrib and add there an instructional part about a11y linting? That way developers have already an initial feedback directly in their coding environment. That could create more initial awareness and could lower the number of warnings and errors in the next step as soon as a11y checks are added to the CI process.
And the points he makes in the
Create a Testing Strategysection of the article sound reasonable and thoughtful by not starting of with the whole set of tests but go in stepwise over the weeks and introduce more of the desired set of tests. So maybe make the steps @mgifford added and suggested even more granular?Comment #22
dmundraAgreed that a testing strategy could help with roadmapping accessibility testing. I like the idea of layering the approach to accessibility testing i.e. linting, accessibility unit tests with Nightwatch, pa11y for full page and sitewide testing.
I looked at what it would take to add @rikki_iki's nightwatch-axe-core package to core's Nightwatch tests and here is what I came up with.
Easy enough to add the package using yarn and it installs axe-core 4.4.2:
Following https://www.previousnext.com.au/blog/automate-your-drupal-accessibility-..., I had to add axe-core commands to the Nightwatch configuration. I did that by editing 'core/tests/Drupal/Nightwatch/nightwatch.conf.js' and adding two lines. Here is the diff:
I then created a example test, 'tests/Drupal/Nightwatch/Tests/exampleA11yTest.js' (copy of exampleTest.js),
Running the test returned no errors (nice!):
I also injected 'axe()' in the 'search narrow form is accessible' test from 'tests/Drupal/Nightwatch/Tests/Olivero/oliveroSearchFormTest.js' and ran that and I got a few errors but that was for the entire page. Here is what the output looks like (removed the other test results):
I think those Axe errors can be reviewed and the issues potentially fixed.
The 'axe()' function can take a context and options to focus only on the area that you want to test instead of the entire page (example shown here https://github.com/rikki-iki/nightwatch-axe-core#per-test-configuration). Here is the test code with 'axe()' function only focusing on the search fields:
Rerunning the test produced no Axe errors.
I think accessibility testing in core with Nightwatch and specifically with the nightwatch-axe-core package by @rikki_iki is doable and something that maybe should be pursued sooner?
Comment #23
rikki_iki commentedOoh glad to hear nightwatch-axe-core was simple to include as a POC. Happy to address any questions, concerns or feedback around potentially including it (happy to share access and what not). We've had it running on all our projects for the last 2 years and hardly come across any issues. It probably does need a bit of updating but this would be a good push for me to do that lol
Comment #24
dmundraThanks @rikki_iki. What's your recommendation for the axe.conf.js, do you leave it the default or add specifics wcag values? Also I think the location of that file for Drupal core would be the core folder which might be fine. I was thinking maybe it should go into the core/tests/Drupal/Nightwatch but would that file be picked up? I can give it a try but wanted to ask as well.
Comment #25
mgiffordIt would be great to get a list of the URLs that are presently being covered by axe. There are some issues sneaking into Core that should have been caught by automated testing.
As with any good CI/CD process, it is important to monitor that list of URLs on a regular basis to ensure that we are using the best sampling that we can.
Phase 1 & 2 in the description identified some key URLs. It is unclear (without digging into the code) which URLs are being tested.
Comment #26
kentr commentedRE #25, I found these test case URLs.
navigationmoduleIn these files:
I'm wondering if there's an error in the admin tests.
Should perhaps be:
Comment #27
kentr commentedSome of these missed issues may be a result of the limited
nightwatch_a11y_testingprofile. A bunch of Axe errors appear when I use the modules from the standard profile.I've been digging into it a little more before I create an issue.
Comment #28
the_g_bomb commentedCertainly, that create article path looks wrong.
Comment #29
the_g_bomb commentedI created this issue and fixed the path.
#3501457: Incorrect path used in a A11y Test Admin
Comment #30
the_g_bomb commentedI have also created: #3501493: Get nightwatch a11y test coverage to use Standard profile to pickup the rest of the coverage
Comment #31
the_g_bomb commentedComment #32
kentr commentedI can see also this for:
Comment #33
kentr commentedI'd also like to have a policy / coding standard for tests regarding the locating of elements by name, or role & name, when possible.
It's closer to how users interact with the page and would build in a check for the correctness of the name (if the name is incorrect, the element won't be found). Sweeps with Axe will find missing names but won't confirm that they are correct.
It looks like Nightwatch doesn't currently offer a clean solution, but Playwright does. So, maybe after #3467492: [policy, no patch] Replace Nightwatch with Playwright. Or, we could implement the workaround described in the Nightwatch GitHub issue as a custom Nightwatch command.
Comment #34
drummTesting for Drupal core now pretty much fully within core itself. (If a custom container is needed, there is https://www.drupal.org/project/drupalci_environments, although well-supported 3rd-party containers are preferred.) If this can land in a way that contributed projects could take advantage of, there is https://www.drupal.org/project/gitlab_templates