Development/Accessibility Unit Tests

This page is a work in progress documenting writing and porting tests for the UI accessibility layer in LibreOffice.

Converting Java tests
Here we will use toolkit/qa/complex/toolkit/AccessibleStatusBar.java as an example (and you can check out the actual conversion to CppUnit). This is a test of the actual UI in action.

Overview
Translating from Java is fairly straightforward for the most part, but some key points require to be familiar with the UNO integration for each language.

Replace calls like  with. You can use  if the result is optional. This works for any the object implements. To get a hold on the accessible interfaces, go through the associated accessible context on which they are implemented:.

The other main difference is the test infrastructure, that is the boilerplate around the actual test code that actually runs the tests. The Cpp Unit Tests page gives some useful insight on the matter. Specifics for our example will be discussed below.

Use assertions whenever an issue is encountered, don't needlessly propagate return values. Doing so simply makes it harder to find the root location of the issue. Some of the JUnit tests did so, but it's not really an example to follow. Instead, convert manual checks and error messages to assertions (see below).

Make use of  when useful. Among other things, it provides CppUnit  for some   classes. Including the  header is enough for assertions like   and   to make use of it, which means they will be able to better compare and display differences between accessible objects.

Setup
First off, the CppUnit test class will inherit from for all the heavy lifting setting up the environment.

We will want to load documents (or more specifically, create new ones), so we'll need to set up the for that purpose, and   has the  we'll need. So, in our overridden  we'll chain up and then call.

With this we can call to create our documents and thus the frames and windows that come with it. The Java version made use of a helper we don't have, but basically it's a matter of calling  or similar.

We'll then need a bit of shenanigans to get the containing window so to access elements and their accessible, and possibly bring the new window to the front in case we need it.

Then, we will want to get the interface on some object, depending on what the test actually is. To do so, simply query this interface on a relevant object, e.g. .  You can get the  from there using, and then any more specific accessible interfaces the object might implement by querying that context for it (e.g. ).

Once done with the test, we'll close the document using it's interface:

This gives a test class looking somewhat like this:

Actually testing something
We are not really gonna reimplement the whole Java example here, but simply a subset we're gonna fold in the main test here instead of using helper classes as done in the real example, for simplicity's sake. As an example, we're going to implement test for. We're gonna do this on the window itself, as it's slightly simpler than locating the status bar first, but once done it should be fairly obvious how to port what the actual Java version does.

First, we need to query the object to get the interface (we assume that interface ought to be implemented, which is the case for an  ): Then, we can implement the test:

…and that's all there is to it.

Awaiting changes
It is often required to wait for events being dispatched before some changes actually happen when interacting with user interfaces.

The naive solution is to use, which is almost a good one, but if the change might happen after the next idle state (e.g. being triggered by a timeout or similar).

Instead, one can use the family of helper functions. They are basically identical to, but they process events until a condition is met, or a timeout limit is reached, whichever comes first.

As an example, an excerpt of :

takes a callable that is used to poll for the expected state, dispatching events in-between. In the example above, a lambda is used to check whether the listener's  member got set. It is a good idea to limit the amount of work done in the callable as it might be called numerous times; yet it's not a critical path as it's a test scenario.

Awaiting an accessible state could be achieved like this:

returns the value from the callable, so it is suitable as an assertion value: if the call terminated because it reached the timeout without the condition being satisfied, it will return. So, this could be used as such:

Creating an XAccessibleStateSet
If a test warrants creating a custom, e.g. for comparison purposes, one has to go through :

and add  to the   call in the .mk.