Search code examples
androidadbmonkeyrunner

MonkeyRunner instrumentation sends a ShellCommandUnresponsiveException during test execution


I am trying to run some test instrumentations using MonkeyRunner, but I somehow can't get it to work like it should. After only a few seconds of test, the execution stops with a ShellCommandUnresponsiveException, while the test is actually still running on the device.

My MonkeyRunner script is the following :

# -*- coding: utf-8 -*-

# Imports the monkeyrunner modules used by this program
import os
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice

# Connects to the current device, returning a MonkeyDevice object
device = MonkeyRunner.waitForConnection()

# Variables for commands
params = dict()
params['class'] = 'com.foo.test.TestCases#testMethod'

device.instrument('com.foo.test.test/android.test.InstrumentationTestRunner', params)

And I get the exception

160205 17:33:48.856:S [MainThread] [com.android.chimpchat.adb.AdbChimpDevice] Error executing command: am instrument -w -r -e class com.foo.test.TestCases#testMethod com.foo.test.test/android.test.InstrumentationTestRunner
160205 17:33:48.856:S [MainThread] [com.android.chimpchat.adb.AdbChimpDevice] com.android.ddmlib.ShellCommandUnresponsiveException
...

What I do not understand is that if I try to use the mentioned command separately with adb shell it works perfectly fine and the test passes, so the problem doesn't come from the command's syntax or the test being executed.

I tried replacing device.instrument with device.shell and input the command, and while it doesn't throw an exception it does not wait for the end of the test before moving on the rest of the code.

The problem might come from the fact my tests use Thread.sleep() to wait for a certain time. I noticed one of the tests that had a really short sleep time seems to pass and not cause the exception. Is there a way to prevent this exception from happening ? I guess I could switch to the device.shell method and wait for an arbitrary amount of time, but this would considerably slow down my tests as I cannot predict how long the test will be.


Solution

  • I think you can use AndroidViewClient/culebra to achieve your goal. More specifically if you take a look at RunTestsThread class it does almost exactly what you need. Also take a look at its usage, mainly the way AdbClient is created with no timeout in UiAutomatorHelper.__runtests:

    # We need a new AdbClient instance with timeout=None (means, no timeout) for the long running test service
    newAdbClient = AdbClient(self.adbClient.serialno, self.adbClient.hostname, self.adbClient.port, timeout=None)
    self.thread = RunTestsThread(adbClient=newAdbClient, testClass=self.TEST_CLASS, testRunner=self.TEST_RUNNER)
    if DEBUG:
        print >> sys.stderr, "__runTests: starting thread"
    self.thread.start()