Testing an accessibility announcement in Flutter

Testing an accessibility (semantic) announcement made using SemanticsService.announce is not straight forward. This article describes how to do so.

What does SemanticsService do?

SemanticsService manages the communication between Flutter and the OS using Platform Channels.

The announce method in this class is used to make a semantics announcement in cases where the system can’t. For example, if you have a countdown timer and want a semantic announcement to be made every 5 seconds. Its used in numerous places in the Flutter framework too.

To keep things simple and focus on how we test this method, we’ll make an announcement when a button is clicked. Check the sample code & the demo that follows:

Sample Code

Semantics Announcement Demo

Testing Semantic Announcement in Flutter

To test this if we’re making the correct announcement we need a way to intercept the announcement.

To be able to do so we’ll need some knowledge of what announce method does. Looking at the code, we see that it uses a platform channel with the channel name accessibility. It uses an object AnnounceSemanticsEvent internally to represent an announcement.

Flutter provides a way to mock platform channels in tests using TestDefaultBinaryMessenger. This class provides ways to capture and test any platform message by intercepting them and hooking into callbacks.

Check this code to see how the Flutter framework tests SemanticsService. All this code does is register a mock message handler that stores all data passed to the SystemChannel.accessibility channel into a map which is then used to assert.

This approach works well for the framework, but for us our unit tests would be depending on implementation details of the framework. Which is why is makes sense to abstract this away.

Introducing semantic_announcement_tester

I’ve published a tiny package called semantic_announcement_tester, which makes testing Semantic announcements made using SemanticsService.announce dead simple by providing some matchers.

Usage

  1. Create an object for MockSemanticAnnouncements in your widget test.
  2. Write the test code as usual.
  3. Use one of the matchers: hasOneAnnouncement, hasNAnnouncements or hasZeroAnnouncements to assert.

Sample Tests

To test one announcement:

To test N announcements made:

To test zero announcements made:

Happy testing!

Software Engineer