Testing for Accessibility: Keyboard, High Contrast, and Assistive Technology Compatibility

Consider this my testament as an Accessibility Tester. I am a Software Designer Engineer in Test on the Visual Studio Core Team. My team owns the critical aspects of the integrated shell, and I am responsible for the quality of the shell's Accessibility.

When I first started Accessibility testing two years ago, I had never heard of Accessibility in terms of software. Sure, I had seen the Accessibility Options icon in my Control Panel, but that was really the extent of my knowledge at that time. When I was asked to do ad-hoc directed Accessibility testing against Visual Studio , my first question to the Program Manager was, "How do I test for this? How do I test using a screen reader?" He replied, "Turn off your monitor, I guess." And so I did...

There is a lot of information out there about what it means to be Accessible. A couple of examples:

  1. Does your application work with a Screen Reader?
  2. Does your application respond to High Contrast?

From a tester' s perspective, we need specific details in order to test. Just saying "Does the feature work" isn't deterministic. What are these details? What does a tester need to know in order to verify something works with either an Assistive Technology device (aka screen reader) or an Accessibility Feature (aka High Contrast)?

It is critical to know not only the "what" to test in terms of Accessibility, but also the "how" to test, which is the more important. For now, I'll only discuss three categories of Accessibility:

  1. Keyboard Access
  2. High Contrast
  3. Assistive Technology Compatibility - specifically screen readers.

For each category, I will go into detail regarding what a tester is looking for and also how to find it.

What is Keyboard Accessibility

This is the easiest of the three to test. Most people have used this category without even realizing it was related to Accessibility. Anytime someone uses Ctrl-X and Ctrl-C to cut and copy text without the mouse, he/she is using Accessibility. Not convinced? Let us compare the keyboard versus the mouse in this cut/paste scenario:

Constants in both scenarios:

  • Outlook 2003 Mail Message using Word as Editor
  • Cursor is at the end of the sentence to move
  • Move the first sentence after the second sentence.

Keyboard Steps:

  1. Press Ctrl + Shift + Home
  2. Press Ctrl-X
  3. Press Ctrl-End
  4. Press Ctrl-V

Mouse Steps:

  1. Move mouse to beginning of document
  2. Highlight the text to copy
  3. Right click (bring up context menu)
  4. Select "cut"
  5. Move mouse to end of document
  6. Left-click
  7. Right-click
  8. Select paste.

Although both scenarios took approximately the same amount of time (5 seconds), the Mouse Steps are obviously much longer than the Keyboard Steps. Another thing I noticed while timing myself was how error prone the Mouse Steps were. Sometimes I didn't get the mouse pointer exactly at the same point as system cursor, so I had to redo the highlight. This error took an extra few seconds to correct, even more if I didn't notice it until after I did the paste.

When testing for keyboard accessibility, keep in mind the the minimum number of keystrokes must always be used. It's either a design issue or a coding defect. A design issue is using the keyboard shortcut "Ctrl + Alt + Shift + T" to perform a function, whereas "Enter" works just as well. I'll explore this example in more detail in the next section. A coding defect is when a control with a tab stop is missing its Accelerator or Mnemonic. This is the underlined letter that appears when you have Control Panel - Accessibility Options - Keyboard Tab's "Show extra keyboard help in programs" checked. Yeah, not the best name for the feature, but now you know what it does! Consider a dialog that has about twenty controls with Tab stops. Suppose focus is on the 10th control, but the user needs to reach the 20th control. Of course, the 20th control doesn't have a keyboard shortcut, so the user is forced to hit tab 10 times. A keyboard shortcut requires just the Alt + Underlined letter - 2 keystrokes. This is especially important for someone with a mobility disability or has pain in their wrists when typing.

The What of keyboard accessibility is doing everything that a mouse can do using the keyboard. That's all it is. QED.

How to Test Keyboard Accessibility

Unplug your mouse. You cannot test a feature for keyboard accessibility if your mouse is just inches away from you for the following reasons:

  • We are creatures of habit
  • We can be bias without knowing it
  • We might accidentally cheat

Consider reading new mail in your Outlook inbox. I always use the mouse to select a new piece of mail. Suppose the focus wasn't on the inbox list and was on the folder view instead. I would have to actually look up the keyboard shortcut in the docs to get to the list view. However, I've trained myself to use the mouse to read mail. If I knew the mouse was still there, I could subconsciously use it instead of the keyboard. Trust me on this one as I've done it before. It's better just to remove the mouse and avoid the temptation.

Another critical point is knowing which features map 1-1 with the keyboard and which don't. For example, the keyboard shortcut to drop down a combo box's list is Alt-DownArrow. This is virtually the same thing as using the mouse to press the combo box's button. However, what's interesting is how to test drag-and-drop. In some situations, you don't want the user to literally capture an object via the keyboard and drag it to a new location. An example is dragging a toolbox icon, like a button, onto a winform designer. The user simply has to press Enter for the button to appear on the designer. By the way, the keyboard shortcut to force the toolbox to appear in Visual Studio .NET is Ctrl + Alt + x.

In the previous example, I mentioned the shortcut "Enter." In the letter of the law, I could substitute "Ctrl + Alt + Shift + T" and still achieve the desired effect. Considering the spirit of the law, how intuitive is "Ctrl + Alt + Shift + T" compared to "Enter"? How will the user know to use this command, besides reading through lots of documentation? In other words, keep it simple, direct, and intuitive as possible. If the keyboard shortcut doesn't fall into one of these categories, there's a potential keyboard accessibility bug lurking around.

A keyboard shortcut must never be used to replace broken keyboard functionality. For example, to check a checkbox, the user presses spacebar. If there's ever a keyboard shortcut to replace spacebar to check a checkbox, it is an accessibility bug. Check out the standard Windows XP shortcuts. If there's a keyboard shortcut that is replacing these standard keyboard shortcuts, it is most likely an accessibility bug. It goes back to "how would the user know?" There are standard keyboard shortcuts for a reason: we cannot force users to memorize different keyboard shortcuts for standard tasks among different applications.

What is High Contrast

Go to Control Panel - Accessibility Options - Display Tab. There's a checkbox for High Contrast. High Contrast will modify OS font size and colors. When high contrast is set, the High Contrast OS System bit is set. If you enjoy working outside on a laptop on sunny days, try using High Contrast Black (large) scheme to improve visibility.

The difference between checking the High Contrast checkbox and manually customizing the display settings is the OS System bit is set. If the user manually customizes the OS System Colors to look exactly like High Contrast Black (large) scheme, the application must respond just as it would under the High Contrast scheme. This response should occur because all colors are taken from the OS System Settings.

How To Test High Contrast

Always turn on High Contrast before starting your application. Supporting in-place High Contrast toggling is more difficult. If the application doesn't respond to High Contrast having been enabled prior to launch, the application is definitely not going to respond to in-place toggling.

Here is a listing of items to check to whether the application is responding correctly to High Contrast. Note I'm taking these items directly from our accessibility test plan that I co-authored.

High Contrast Items to Verify

  1. Verify all UI elements and controls are visible

If the background changes to black and the font color is hard-coded black, the application or dialog is not usable.

  1. Verify differentiable appearance of inactive and active selection

Explanation of Focus and Selection

Focus: Only one control or UI Element can take focus at a time. If I were to press a key on the keyboard, the keystroke can only be sent to that control with focus.

Selection: Multiple controls can have multiple items selected. List boxes can have as many or as few items selected.

Inactive Selection: When focus moves away from the list box (with selected items) to another control, those list box items are said to have inactive selection:

Active Selection: The selected list box item with focus. Hence, only one item can have Active Selection.

Regardless whether High Contrast is set, Active Selection and Inactive Selection must correctly respond to their appropriate system colors. Additional testing is required in High Contrast mode, because although it might work in some default Windows display scheme, it isn't guaranteed to work in High Contrast.

  1. Verify visual focus is available in high contrast mode

Focus must be shown at all times. A great way to find bugs is to tab around the application. If focus ever disappears, it is an Accessibility bug.

  1. Verify multiple schemes function

All color schemes should work, since font sizes and colors come from the OS. However, due to time and resource constraints, it is important to test with the most commonly-used schemes, like High Contrast Black (large). With some certainty, if the application responds correctly to one scheme, it in theory responds to all, because it is reading the color data from the same location. Only the data is changing values.

  1. Verify no text truncation occurs

There's some gray area here. The text must be readable; yet, it's never good for text to be truncated. The rule I've been using is to say if more than 20% of the text's height is truncated, it's an accessibility bug.

  1. Verify no hard-coded colors

All colors must come from the OS system settings. If the application has custom colors that cannot be mapped to the OS system settings, there must be a way for the user to customize these colors. For example, in Visual Studio , we have custom colors for squiggles. Since there isn't an OS system setting for squiggles, we provide a means via Tools Options for users to customize these settings.

What is Assistive Technology Compatibility

Assistive Technology Compatibility depends on Microsoft Active Accessibility (MSAA) support. If an application does not support MSAA, it will not support Assistive Technology Devices.

Narrator is a screen reader that ships with Windows XP. It's great for just learning the basics of how screen readers work. It isn't a full-version or industry-standard, because there are third-parties who have spend years on end producing screen reader technologies. Most people who are blind will use one of these third-parties products. Make sure you are testing with an industry-standard screen reader, but it doesn't hurt to try out Narrator to become more familiar with how screen readers work. Also, it'll make you appreciate an industry-standard screen reader even more!

How MSAA Works for Retrieving a Standard Win32 Button Accessible Name

Client (Screen Reader) asks MSAA for a pointer to the IAccessible object via AccessibleObjectFromWindow, AccessibleObjectFromEvent, and so forth.... MSAA asks the server (aka the button) for a pointer to the IAccessible implementation. Since it is standard control and doesn't have its own IAccessible implementation, it returns 0. In this case, MSAA uses a proxy to return methods and property values. For IAccessible::get_accName, MSAA returns the value from GetWindowText().

How MSAA Works for a Custom-Drawn Button

Client (Screen Reader) asks MSAA for a pointer to the IAccessible object via AccessibleObjectFromWindow, AccessibleObjectFromEvent, and so forth.... MSAA asks the server (aka the button) for a pointer to the IAccessible implementation. Since it is custom control, the developer has implemented IAccessible, so a pointer to this implementation is returned. The client calls IAccessible::get_accName on the interface pointer and the value set by the developer is returned. Note here that it might not be the same as GetWindowText(), although it must be. Custom controls are prime targets for Accessibility testing.

How MSAA Works for a Owner-Drawn Button

A slight combination of both Standard and Custom. It works exactly the same way as Standard. When the client asks for the Name, GetWindowText() may return a null BSTR. All controls, especially visible controls, must support name. Another great target for Accessibility testing.

Once the client has a pointer to the Accessible object, the Assistive Technology will perform actions based on the object's role. This value is returned by IAccessible::get_accRolethat maps to a structure of known MSAA Role types, like push button or combo box. It is possible for a server to return its own customer role type; however, will the Assistive Technology know how to interact with the controls? EVERYTHING IS BASED ON THE MSAA ROLE. Seriously. If the role is wrong, don't expect anything to work.

How To Test for Assistive Technology Compatibility

The MSAA information must be as correct as possible to support Assistive Technologies. So, the first thing to test is MSAA. AccExploreris a great tool to view the IAccessible properties and method of a particular control; however, there is no mechanism to tell you if the properties or methods are supported correctly. AccExplorer has its own verifications associated with it. Unfortunately, these verifications were written with an Assistive Technology vendor in mind. For example, on a button, the test will log a failure if DISP_E_MEMEBERNOTFOUND is returned for ::get_accValue. This is actually by design, because a button does not support value. If a method is not supported, return DISP_E_MEMBERNOTFOUND.

In order to determine which properties and methods must be supported, review the UI Element Referece doc contained in the MSAA SDK Docs. This website describes a virtual contract between MSAA and Assistive Technology vendors. Even if a server were to set that value property on a push button, the Assistive Technology device wouldn t read it because, from the docs, buttons are designed not to support value.

Once the MSAA information is verified, the tester can moved on to using the Assistive Technology device. I am most familiar with screen readers, so I will limit this discussion to just them.

First and foremost, the tester must become familiar with all of the common keyboard shortcuts. Second, and probably equally important, the tester should work with someone who uses the Assistive Technology on a routine basis. Even if there is no one to work with, it is still possible to test with the Assistive Technology. It just requires a deeper understanding of what all the keyboard shortcuts do. Lastly, the tester can only use the keyboard. A user who is blind will not be able to use the mouse.

Once the Screen Reader is installed, the tester opens up a common dialog (like start -> Run dialog) and interacts with it by tabbing to each control. The tester trains his/her ear to listen for patterns. An example pattern a screen reader could speak is <control name> <control role> < additional properties based on role>. If focus were on the Run Dialog's push button, the tester listens for "OK PushButton." If focus were on the combo box, the tester listens for "Open: ComoBox notepad.exe" , where notepad.exe is the text within the combo box's edit box.

When doing Screen Reader testing, turn off the monitor. It forces the tester to really listen to what the screen reader is saying. And even then that is not enough. As I've used VS for days on end for the past 4 years, I've become so bias towards how things should work, it is easy for me to miss certain bugs. For example, I might hear the screen reader read the text for a link, but not realize that the screen reader did not say "link" at the end. I am bias because I know it is a link, so I accidentally stop listening once it is finished reading the name of the link. Turning off your monitor helps break that sense of comfort knowing where focus is at, so you are forced to listen to things more carefully.

From my experiences, there are two categories of Assistive Technology bugs against the server (aka, the application itself).

  1. Functionality bugs like dangling pointers, infinite loops, and so forth...

Example is when the Screen Reader tries to access inforamtion from a dangling pointer. The application crashed due to a null pointer reference exception.

  1. MSAA bugs

Example is a push button that doesn't have a Name. This is the same thing as an OK button not having a Caption.

The tricky part to Assistive Technology testing is knowing when it is a bug against the application and when it is a bug against the Assistive Technology. Historically, MSAA has not been reliable due to poor or no implementation for custom controls, so ATs use hooks, one of which is an Off-Screen Model, that queries for information outside of MSAA. Knowing if, how, and when an Assistive Technology uses such hooks is important for figuring out who gets the bug. If the MSAA information is correct (and it is not a functionality bug), there is a high probability that it will go against the Assistive Technology.

In conclusion, I have stated the "what" and "how" of Accessibility testing for keyboard, high contrast, and screen reader support. This testament is an honest collection of the knowledge and experiences I've accumulated in the past two years. I hope this doc will be helpful for other testers who are starting accessibility testing. Good luck and happy Accessibility bug hunting!

I look forward to your feedback!