Testing your first Android Things driver

Controlling any peripheral device from an Android Things board requires a driver. If no driver is available it’s down to you to write your own. Once that’s written, how do you know it will keep working? You need to test it. Let’s take a look at unit testing for Android Things device drivers.


In my previous blog post we learnt about input/output protocols to write an Android Things driver for a new peripheral device. Taking the WS2801 chip protocol as an example and writing a driver to control its LEDs. In this blog post we’ll discuss how the driver can be unit tested to give us the confidence to use for a real project.

Testing to complete our hacking

This is probably the most important part of writing a driver, especially if you’re going to share it with others: we have to make sure it works and we have to prove it with tests. If you haven’t read this blog post on testing Android Things by my colleague Paul Blundell then I’d recommend you take a look now. It includes useful insights on how to tackle testing an Android Things app when peripheral devices are involved (spoiler: it doesn’t involve peripherals).

As a TLDR: write your code as if the hardware was a replaceable component, just an implementation detail, so you can swap it with a fake implementation (or a mock) and test your code easily.

Android Things driver testing

Looking specifically at testing a driver, you can apply the same principle. This means the SpiDevice, Gpio or whatever component you use, should be an external collaborator that gets injected into the constructor (this may sound similar to the dependency inversion principle). This will allow you to use a mock object during your tests to abstract you from the platform. Here’s how the first iteration of Ws2801Test.java might look:

One problem you may face when unit testing a driver is that you may be relying on some of Android’s built in utilities (mainly static methods) that aren’t available in a test environment as these tests will run on your computer using a mockable android.jar1.

In my case I had a method in Ws2801.java that returned a byte[] with the red, green and blue values of a given colour. It looked like this:

When executing the above method during a JUnit test, a Stub! error would be thrown because the methods in Color couldn’t be mocked. Color is an Android framework class with static methods. To avoid this Stub! problem there’s a couple of things you can do:

  1. Use mocking framework that makes use of bytecode manipulation to mock static methods, such as Powermock.
  2. Extract the behaviour that relies on the non-mockable components and test them separately (without testing the framework).

I went for option 2, since mocking static methods felt a bit like cheating. I extracted a ColorUnpacker class to hold that method, which can be unit tested separately and mocked in the original tests. This is the result:

Now the setUp method of the Ws2801Test class should look something like this:

With this, changing the direction of the LED strip is very easy to test because we only need to verify that the unpack method in ColorUnpacker gets called as many times as we expect with the expected values. Since the new class is small and simple, we can easily unit test it too:

Notice that in Ws2801Test.java we’re verifying the internal behaviour of the Ws2801 driver and ensuring it interacts correctly with the SpiDevice. In ColorUnpackerTest.java we’re asserting if a function returns the expected result given predefined inputs.

Here’s the full source code for the unit tests.

Conclusion

We made it! At this point we can use this driver in multiple projects really easily and have the confidence from our test that it behaves correctly. We could even publish the driver in a maven repository so that it can be used by other developers.

I hope you enjoyed the process and found this informative. I think once you’ve made one driver, the next time should be a lot easier as you’ll be familiar with the terminology in datasheets and you’ll have some knowledge of which pins can be used for what in your Android Things device.

To learn more, download the Android Things SDK documentation. It will go up on the Android Developer website once it comes out of preview.

You can find the full source code of this blog post on Github and please feel free to chat with me about this on Twitter or Google+. Happy coding and happy hacking!

Last but not least I’d like to give a big thanks to Paul Blundell for reviewing this post.


Originally published at novoda.com on February 7, 2017.