Understanding Android’s Monkey Tool

The Monkey tool included as part of the Android operating system provides an effective way to stress test your application (and the Android OS itself) in a random but repeatable fashion. That is, the Monkey tool will generate a pseudo-random series of inputs based on a seed; if you run the Monkey tool again with the same seed it will generate the same series of inputs and in theory, allow you to reproduce any crash encountered.

In practice, this works well to identify race conditions and other non-trivial error cases that conventional automated and manual testing may not.

Basic Usage

The Monkey tool is incredibly simply to use, but offers extensive customisability. It runs directly on the Android device rather than on a workstation, so needs to be executed from an adb shell:

adb shell monkey <event-count>

This will start the Monkey tool on the connected device or emulator and run a total of event-count events before exiting.

When launched with these options, the Monkey tool will start injecting input events immediately. Assuming that you want to test an application’s stability rather than that of the whole platform, you’re probably going to want to direct the events after the application is launched and prevent the Monkey tool from launching any other applications. The -p option restricts the Monkey tool to just the specified package, for example:

adb shell monkey -p <package-name> <event-count>

The -p option can be given multiple times for restricting the Monkey tool to multiple packages.

You will likely find that the Monkey tool can still escape your application and inject events when your activity is not visible – this is by design and is a result of the fact that there’s many more ways to switch away from an activity other than launching a different one – for example, by pressing the menu or back button. Methods of limiting this effect are mentioned later.

Input Events

By default, the distribution of random events generated by the Monkey tool are:

EventProportionCommand Option
Touch (Down and Up in a single position on the screen)15%--pct-touch <pct>
Motion (Down, some movement and then Up in a different position)10%--pct-motion <pct>
Trackball (Random movements and then sometimes a click)15%--pct-trackball <pct>
Nav (e.g. Up, Down, Left, Right buttons)25%--pct-nav <pct>
Major Nav (e.g. Centre, Back, Menu buttons)15%--pct-majornav <pct>
System Keys (e.g. Home, Volume, Start/End Call buttons)2%--pct-syskeys <pct>
App Switch (Activity launch)2%--pct-appswitch <pct>
Other (other keypresses and buttons)15%--pct-anyevent <pct>

This distribution can be modified by setting the proportion using the corresponding command option. You can set a single event’s proportion or multiple events, however if you provide proportions for all events then these need to add up to 100% otherwise the Monkey tool will generate an error.

The default proportions for the unspecified events will be adjusted such that they add up to 100%. For example, if you were to increase the Touch event proportion to 50%, the proportions of the other events would go down accordingly but will still maintain the same ratio – a Motion event will occur on average 5x as often as an App Switch event.

Scripting

As well as being able to generate pseudo-random input events, it’s also possible to inject a predefined series of events. There are two different ways of doing this:

You may also consider the monkeyrunner tool, which is unrelated to the Monkey tool but also allows for injecting predefined events on a device or emulator. It provides a Python API and is extensible with Java plugins, as well as providing the ability to retrieve screen captures, making it a very useful tool for automated regression and functional testing.

Tips and Tricks

Maximising the time spent in your application

The default proportions are very effective at exploring every possible interaction with your application extending above and beyond the usual methods that a user would perform. This is great for catching bugs that would be very unlikely to be discovered with normal manual explorative testing, but does mean that it will take a lot longer for the Monkey tool to discover all parts of your application.

Adjusting the input event distribution can allow you to tip the scales in favour of inputs that will keep your application in focus, therefore maximising the amount of time spent in the application and therefore (hopefully) exploring more of the application that a user is likely to encounter. This will of course limit (or even exclude entirely) the Monkey tool’s ability to find the more nuanced bugs involving complex interactions, but in time-constrained cases this may be desirable.

The -p <package> argument is an absolute must. This will stop the Monkey tool from allowing other apps to launch, but does not stop the Monkey tool from exploring the other parts of the Android OS which can also be accessed by system buttons and certain gestures.

If you want to restrict these interactions, you will need to decrease (or disable entirely) the following input events: --pct-motion (stops gestures activated from screen edges), --pct-majornav (stops home/menu/back buttons), --pct-appswitch (stops app switching – shouldn’t do anything when -p is set), --pct-anyevent (stops any additional buttons like the camera or search).

 

Leave a Reply