Monkey – using a stress test tool
Monkey is a random event generator that can be run on a device against the particular package. It can be used to stress applications under a development in order to find weak points. There is plenty of useful information on official Android Monkey website.
We can use this information to build the script that will do the following:
- run Monkey against particular package or all of them
- store logs
- analyse logs
- show the results of the test
First, lets establish all variables. We know that Monkey will run against different packages – therefore it’s clear that we should have a variable for this. Next will be a number of random events send to device (aka seeds) and finally device S/N – so we can run tests when multiple devices are plugged in.
Let’s start scripting:
1. Passing parameters to script:
There will be three variables passed to scripts as parameters: $package, $seeds and $Device
#!/bin/bash # Loading the parameters package=$1 seeds=$2 Device=$3
2. Constructing condition statement for running different test variants:
We want to have a choice to run either one app or all of them. In order to run all packages instead of a package name, we would send ‘all’ parameter. This requires a script to distinguish both choices:
# Condition for test variations if [ "$package" == "all" ] ; then # Obtaining list of all packages on device with S/N $ adb -s $Device shell pm list packages -f > ./packages_list.txt # Counting number of the packages on device number_of_packages=$(cat ./packages_list.txt | wc -l) # Selecting 1st package for test run from the list package_selected=$(head -1 ./packages_list.txt | cut -d "=" -f2 | cut -d " " -f1 | tr -d ' ') else # When running tests against particular package number_of_packages=1 package_selected=$package fi
3. Creating a test results container:
Let’s create a simple HTML web page where we can easily store the test results data.
# Building simple table to store tests results echo "<table><tr><th>Package Name</th><th>Errors detected</th><th> Number of events</th><th>Logs</th></tr>" > ./monkey_report.html
4. Building a test runner:
Based on the conditional statement and parameters provided we can now build a loop that will run the tests.
# Creating a variable for the loop start=1 # Creating a directory for test results mkdir ./test_results # Condition for the loop to start while [ $start -le $number_of_packages ] ; do # Displaying which package the test will be run against (just for clarity) echo "Current test package: $package_selected" # Running the Monkey - with tee output will be printed both to screen and file adb -s $Device shell monkey -p $package_selected --ignore-crashes -v $seeds --monitor-native-crashes | tee ./test_results/"$start"_test.txt # Now lets analyze the results of the test run - we will be looking for specific key words is_fatal=$(cat ./test_results/"$start"_test.txt | grep -i 'fatal' | wc -l) is_null_point=$(cat ./test_results/"$start"_test.txt | grep -i 'NullPointerException' | wc -l) is_runtime=$(cat ./test_results/"$start"_test.txt | grep -i 'RuntimeException' | wc -l) # With the results analysed build conditions statement that will check for the errors and select message for our report is the next step if [ $is_fatal -gt 0 ] ; then is_fatal_desc=$(echo " $is_fatal FATAL(S) ") else is_fatal_desc=$(echo "") fi if [ $is_null_point -gt 0 ] ; then is_null_desc=$(echo " $is_null_point NULL POINT EXCEPTION(S) ") else is_null_desc=$(echo "") fi if [ $is_runtime -gt 0 ] ; then is_runtime_desc=$(echo " $is_runtime RUNTIME EXCEPTION(S) ") else is_runtime_desc=$(echo "") fi # Creating a message that will be added to the test report if [[ $is_fatal -gt 0 || $is_null_point -gt 0 || $is_runtime -gt 0 ]] ; then # Adding message if error detected fatal_exist=$(echo "A problem was detected: "$is_fatal_desc" "$is_null_desc" "$is_runtime_desc" ") else # Adding message if no errors fatal_exist=$(echo "No problems with running Monkey :)") fi # Adding link to the raw logs file and events count Log=$(echo "<a href="./test_results/"$start"_test.txt" target="_blank">Log</a>") Events=$(cat ./test_results/"$start"_test.txt | wc -l) # Finally - adding test results to the table echo "<tr><td> $package_selected </td><td> "$fatal_exist" </td><td>$Events</td><td>$Log</td></tr>" >> ./monkey_report.html # Incrementing the variable - so the test won't get stuck in loop let start=start+1 # Preparing for next run if all packages selected if [ "$package" == "all" ] ; then # Selecting next package from the list package_selected=$(head -$start ./packages.txt | tail -1 | cut -d "=" -f2 | cut -d " " -f1 | tr -d ' ') fi # Closing the loop and results table done echo "</table>" >> ./monkey_report.html
Now with this script, it’s possible to easily stress an app or entire system with few commands, example:
sh ./test_monkey.sh "com.android.settings" 1000 Q4E9KH75G3