Saturday, March 12, 2011

Using Android monkeyrunner from Eclipse

Amazingly, this post is at the top of the stats meaning that still a lot of people are still using monkeyrunner and haven't discovered yet AndroidViewClient/culebra. Come on! It's time to evolve.



You may want to edit scripts and run them from Eclipse.
To be able to do this you must first install PyDev from Eclipse Marketplace.

Latest versions of PyDev don't work with monkeyrunner because it is not detected as a valid interpreter. I'm sure this will be finxed in the future. In the meantime you should stick to PyDev 1.6.5.


Then you have to define a new python interpreter


but before you can do it you need to do some changes to the Android installation. We need to replace the monkeyrunner interpreter because Eclipse invokes it using the -u command line option,  unbuffer stdin, stdout and stderr, which is not supported by monkeyrunner. To solve it we should rename the original interpreter to monkeyrunner-original and then use this script as a replacement for  monkeyrunner.

# /bin/bash
if [ "$1" = '-u' ]
then
 shift
fi

exec /opt/android-sdk-linux_86/tools/monkeyrunner-original "$@"
if you are using Microsoft Windows, you should use something like this (script contributed by tagmaster)

REM
@echo off
if("%1")==("-u") shift
"C:\Program Files\Android\android-sdk\tools"/monkeyrunner-original %1 %2 %3 %4 %5 %6 %7 %8 
Once the new interpreter is defined and assigned to a PyDev project you will be able to edit and run monkeyrunner scripts from Eclipse



Don't forget to set the previously defined interpreter to the project properties.




Update: July 2011
This patch was added to monkeyrunner to ignore the -u option sent by PyDev:
http://android.git.kernel.org/?p=platform/sdk.git;a=commitdiff;h=f07d8c2026606633f1de7e1ab9d985c74ad8b340
However, the usage string does not include the -u option yet. BTW, credit would be nice.
So, the wrapper is not needed any more.

Update: September 2011
monkeyrunner included in Android SDK Tools revision 12 supports -u option, however as it was mentioned before it is not described in the help text.
Come on, we are only one step behind...

Update: March 2012
A working Eclipse configuration that works with monkeyrunner has been detailed in a new post: Eclipse: working monkeyrunner configuration

70 comments:

mikita.kharytonenka said...

Thanks! Great! It really works!
But how can we use Eclipse to write monkeyrunner scripts in Windows?

Diego Torres Milano said...

Thanks for you comments.

I think you could do the same on Windows just adapting the monkeyrunner.bat.

Am I missing something ?

mikita.kharytonenka said...

I mean, may be you exactly know how to adapt monkeyrunner.but to use it as interpreter in Eclipse

Diego Torres Milano said...

Sorry, no Windows here, but take a look at the bat file it shouldn't be so difficult.

Android Mobile Guru said...

neat trick, Fred Grott(mobilebytes.wordpress.com)

Diego Torres Milano said...

Thanks

Silicon Sillu said...

Hi!

I need a help regadring this japanese link - http://itpro.nikkeibp.co.jp/article/COLUMN/20101019/353162/?ST=develop

Kindly help me :) a small request!

Vijay
vijeeth at gmail dot com

tagmaster said...

REM @echo off
if("%1")==("-u") shift
"C:\Program Files\Android\android-sdk\tools"/monkeyrunner-original %1 %2 %3 %4 %5 %6 %7 %8

Diego Torres Milano said...

Thanks for contributing this.
I will add it to the post giving you the credit.

Gus said...

It works on Linux, but in Windows the script does not bring me the reference to monkeyrunner.jar when creating the interpreter. Does anyone know how to solve it?

Gus said...
This comment has been removed by the author.
Gus said...
This comment has been removed by the author.
Gus said...
This comment has been removed by the author.
Gus said...

Here's what i'm getting (from my previous post) http://i55.tinypic.com/11ch215.png

cleF said...
This comment has been removed by the author.
Truebit said...

I already done the wrapper trick as described in Windows 7, but an error with "Python stdlib not found" pops up after selecting OK for the selections of standard libary.
Anyone know why?

Ex said...

Diego: you rock!

And for dodos like me who forget they're using a Mac, replace 'linux_86' with 'mac_x86' in the monkeyrunner script!

When I try to add the interpreter to Eclipse, the /opt/android-sdk-mac_x86/tools/lib/Lib folder is expected to be added to the python path, but the folder does not exist by default. What step did I miss?

Diego Torres Milano said...

Hi Ex,
Thanks for your contribution.
/opt/android-sdk-mac_x86/tools/lib/Lib is a kind of default directory added to the python library path and it doesn't exist on linux either.

ExPluribus said...

I found a workaround for the frustrating python library problem and posted it here:

http://www.mail-archive.com/android-developers@googlegroups.com/msg157812.html

I'd be curious to hear if anyone has a less kludgy solution.

Ravi said...

I am getting error as


See error log for details.
Unable to recreate the Interpreter info (Its format changed. Please, re-create your Interpreter information).Contents found:Unrecognized argument: -u.
Usage: monkeyrunner [options] SCRIPT_FILE

-s MonkeyServer IP Address.
-p MonkeyServer TCP Port.
-v MonkeyServer Logging level (ALL, FINEST, FINER, FINE, CONFIG, INFO, WARNING, SEVERE, OFF)


please help

Ravi said...

http://ravinderacharya.blogspot.com/

Ravi said...
This comment has been removed by the author.
Diego Torres Milano said...

According to your error message you are still using an interpreter not supporting -u, probably the original and not the modified one.

Truebit said...

in win7 x64, I have already made the soft link to Jython2.5.2 Lib folder to sdk\lib\Lib using command mklink and the configuation finished with no errors.

http://img27.imageshack.us/i/96706149.png


But the Location of MonkeyRunner is None instead of the its real location. That made me not possible to new a project with MonkeyRunner.

And the PYTHONPATH to monkeyrunner.jar is weired too.

Ravi said...

http://ravinderacharya.blogspot.com/2011/06/monkey-runner-modified.html

Is this the modified one. Please reply.
Thanks in Advance.

Ravi said...

It's very urgent please reply.
I am not getting where ,I am going wrong.

Diego Torres Milano said...

@Truebit: the location of the interpreter shouldn't be None. When you click New... you have the opportunity of selecting Interpreter Name: and Interpreter Exceutable:, which sould be the path to your wrapper.
Then, you also have a problem with the path to the monkeyrunner.jar, check my screenshot.

Diego Torres Milano said...

@Ravi, you only need a wrapper to the original script. There's no need to copy it completely.

Use the instructions provided in the original post to create it.

Truebit said...

@Diego, I know that mine is incorrect.It should not be None. But following you guide, I selected the wrapper .bat file in the Interpreter path and then created a soft link for the Lib folder. It could finish creating the MonkeyRunner Interpreter. But the result is what you saw, the Location is None and the monkeyrunner.jar with weired suffix of PySrc

Ravi said...
This comment has been removed by the author.
Ravi said...

@Diego Torres Milano . I did everything you told. But still i am getting error.

Diego Torres Milano said...

I updated the post with valuable information regarding the problems some users found using versions newer than PyDev 1.6.5.

ermedian said...

thanks, appreciate for your guidance.
but i have few problems and questions. when i try to import runner and device, I get an error such as Unresolved error. Also i could not get what i need to do at one of first steps, -u command. i didn't have any interpreter at the beginning and probably i failed that stage. also i'm confused about python and jython. should i make jython or python interpreter
thanks for your help

Diego Torres Milano said...

Eclipse will invoke the interpreter passing the -u option, which is not supported by monkeyrunner, that's why you need the wrapper.
To test it just do:

$ monkeyrunner-wrapper -u

from the command line. If it works here it should work from Eclipse.

cj said...

Hi, thank you share
but if need using monkeyrunner and python lib can do that?

cj said...
This comment has been removed by the author.
Diego Torres Milano said...

Post updated.

robin zhou said...

Anyone have completed to setup the wrap dat file as a interpreter to eclipse? I have done on ubuntu but always failed on win7, after I add the new wrap file as the interpreter, the location always show none. so when I try to debug my script, it alway show can't find the wrap file.

Diego Torres Milano said...

As it was stated in this post's updates, the wrapper is not needed any more.
Install Android SDK Tools revision 12 and monkeyrunner will include -u option.

vijju said...

i am working on android on automation i have setup all the environment required for it like(eclipse,jdk, Android SDk) and i am having monkeyrunner installed.


Now i want to automate the process to do this task--The monkeyrunner API can apply one or more test
suites across multiple devices or emulators. You can physically attach all the
devices or start up all the emulators (or both) at once, connect to each one in
turn programmatically, and then run one or more tests


i thought of doing this through monkeyrunner extending plugins concept, this concept doesn't help me becoz communicaton between two or more plugins creating a new problem. so ,please help me how to get my task done through other approach

Diego Torres Milano said...

You would not need plugins at all. Just add an argument to your test script specifying the serial number for the connection (i.e. emulator-5554).
Then in another script iterate the list of serial numbers and emulator where you want to run the tests and invoke the test script with the specific serial number.
I think that's all you need.
Or am I missing something.

vijju said...

Thank u so much sir. Could you please show me a sample test script where this can be done? some example please. will give me clarity specially the iteration script.


I think my second part of question was not precise. We plan to test scalability aspect of our client-server model based on client Android architecture. Here, as u see we are trying to use monkey runner script to simulate number of devices (emulators) on my single machine. (Here, we also face a problem that a single instance of emulator slows my machine considerably) Can u suggest us some workaround - something like simulation without launching the GUI of the emulator ??

latha said...

Hi Diego, I wanted to ask that can i write a monkey runner script which controls a web based apk ? Eg; I install youtube.apk which is nothing but a browser with hardcoded youtube url. Now my monkeyrunner script shall install this apk and then pass events such as a search string etc on this web based application. All this i want to do and control externally through the monkey runner script. Is this possible? If yes, then could you please guide me by some pseudo code?

DaDa said...

Hi, Diego
Do you know why I encountered this when I add the Monkeyrunner to interpreter? And do you know how to solve it?

See error log for details.
No output was in the standard output when trying to create the interpreter info.
The error output contains:>>java.lang.NoClassDefFoundError: org/python/util/jython
Caused by: java.lang.ClassNotFoundException: org.python.util.jython
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
Exception in thread "main" <<

Diego Torres Milano said...

@Dada, what did you do exactly to get this error ?

Diego Torres Milano said...

@latha, you question may help other people so I'm preparing a post with the detailed answer

DaDa said...
This comment has been removed by the author.
DaDa said...
This comment has been removed by the author.
Truebit said...

Windows never worked,even with the latest PyDev 2.2.3

I think the author should mention that he never tried on Windows. That would save lots of time for others.

Raj said...

Hi Diego,

Since I am very new to eclipse and PyDev environment, I could only manage to configure PyDev to Eclipse and got stuck at importing monkeyrunner package into my application testing .py file.

Got vexed of all trails even your script step. Tried adding monkeyrunner at project --> External Libs and preferences --> libraries. Which is in fact not accepting as version conflict.

Can you please resolve my problem with below declared current environment.

Env details
PyDev:2.2.4
Python 2.6
Eclipse Helios Service Release 2

Please let me know if you require more details from my side

Android app development said...

This is one of the wonderful and good post.I like your blog technique.Nice post.
Android app developers

Android developer said...

This blog is looking good and its having the useful information, so it can easily to reach the correct market place.

Android developers

teju said...

should we change the whole monkeyrunner scripting in bash file or just v should add the provided script

Diego Torres Milano said...

Sorry, I don't know if this is exactly what you are asking for but according to what was stated in the Update: September 2011 to this post, the wrapper it's not needed any more with the latest tools.

Feel free to post another question if you were asking something different.

teju said...

i need monkey runner configuration for python 2.4 and indigo 3.7 and sdk 15 in linux

teju said...

hi diego am getting error like from com.android.monkeyrunner import MonkeyDevice ,MonkeyRunner
no module Named MonkeyRunner And MonkeyDevice

teju said...

i want small example for monkey runner .i.e with main android application and android junit testcase and monkeyrunner scripting with plugins .how to create plugins .i need complete example plz help me out

teju said...

plz help me out diego am unable to get it plz send me the complete example with main application,testcase and plugins..and also how to configure the monkeyrunner tool in eclipse indigo 3.7 and android sdk 15 and python 2.4 .plz help me out

teju said...

its for ubuntu 10.04

teju said...

my main android application:New
package com.android.New;


import android.app.Activity;
import android.os.Bundle;



//import com.google.common.base.Predicate;
//import org.python.util.PythonInterpreter;
//import com.android.monkeyrunner;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnKeyListener;
import android.widget.EditText;
public class New extends Activity {
static final String TAG = "Weight";
EditText editKilos, editPounds;
public static final String ERROR = "ERROR";

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

// Find views
editKilos = (EditText) findViewById(R.id.editKilos);
editPounds = (EditText) findViewById(R.id.editPounds);

// Setup listener for Kilos to Pounds
editKilos.setOnKeyListener(new OnKeyListener() {
public boolean onKey(View view, int keyCode, KeyEvent event) {
if (event.getAction() != KeyEvent.ACTION_UP)
return false;
try {
Log.d(TAG, String
.format("Kilos: %s", editKilos.getText().toString()));
double kilos = Double.parseDouble(editKilos.getText().toString());
double pounds = kilos * 2.20462262;
editPounds.setText(new Double(pounds).toString());
} catch (NumberFormatException e) {
editPounds.setText(ERROR);
Log.e(TAG, "e:" + e);
}
return true;
}
});

// Setup listener for Pounds to Kilos
editPounds.setOnKeyListener(new OnKeyListener() {
public boolean onKey(View view, int keyCode, KeyEvent event) {
if (event.getAction() != KeyEvent.ACTION_UP)
return false;
try {
Log.d(TAG, String.format("Pounds: %s", editPounds.getText()
.toString()));
System.out.println("entet the weight");
double pounds = Double.parseDouble(editPounds.getText().toString());
double kilos = pounds * 0.45359237;
editKilos.setText(new Double(kilos).toString());
} catch (NumberFormatException e) {
editKilos.setText(ERROR);
Log.e(TAG, "e:" + e);
}
return true;
}
});

}
}

teju said...

my androidJunit test application:NewTest

package com.android.New.test;

//import android.test.AndroidTestRunner;
//import android.test.InstrumentationTestRunner;
import android.test.ActivityInstrumentationTestCase2;
import android.test.TouchUtils;
import android.test.ViewAsserts;
import android.test.suitebuilder.annotation.SmallTest;
import android.widget.EditText;
import com.android.New.New;

/*
* Test code to test com.marakana.TestDemo
*
* To run on command line:
* adb -e shell am instrument -w -e class com.marakana.test.TestDemoTests
* com.marakana.test/android.test.InstrumentationTestRunner
*/
public class NewTest extends ActivityInstrumentationTestCase2 {
EditText editKilos, editPounds;
New activity;

public NewTest(String name) {
super("com.android.New", New.class);
setName(name);
}

protected void setUp() throws Exception {
super.setUp();

// Find views

activity = getActivity();
Thread.sleep(10000);
editKilos = (EditText)activity.findViewById(com.android.New.R.id.editKilos);
editPounds = (EditText)activity.findViewById(com.android.New.R.id.editPounds);
}

protected void tearDown() throws Exception {
super.tearDown();
}

@SmallTest
public void testViewsCreated() {
assertNotNull(getActivity());
assertNotNull(editKilos);
assertNotNull(editPounds);
}

@SmallTest
public void testViewsVisible() {
ViewAsserts.assertOnScreen(editKilos.getRootView(), editPounds);
ViewAsserts.assertOnScreen(editPounds.getRootView(), editKilos);
}

@SmallTest
public void testStartingEmpty() {
assertTrue("Kilos field is empty", "".equals(editKilos.getText().toString()));
assertTrue("Pounds field is empty", "".equals(editPounds.getText().toString()));
}

@SmallTest
public void testKilosToPounds() {
editKilos.clearComposingText();
editPounds.clearComposingText();

TouchUtils.tapView(this, editKilos);
sendKeys("1");

double pounds;
try {
pounds = Double.parseDouble(editPounds.getText().toString());
} catch (NumberFormatException e) {
pounds = -1;
}
assertTrue("1 kilo is 2.20462262 pounds", pounds > 2.2 && pounds < 2.3);
}

}

teju said...

my plugin class:Plugin.java in same android junit package

package com.android.New.test;


import org.python.util.PythonInterpreter;
import com.google.common.base.Predicate;


public class Plugin implements Predicate {

@Override
public boolean apply(PythonInterpreter python) {

python.set("hello", "Hello, monkeyrunner!");

return true;
}

}

teju said...

my monkeyrunner scripts:newtest.py and newtestplugin.py
'''
Created on Mar 7, 2012

@author: teju
'''
# Imports the monkeyrunner modules used by this program
from com.android.monkeyrunner import MonkeyDevice, MonkeyRunner
from com.android.New import New

# Connect to the current device
device = MonkeyRunner;
# Install package
device.installPackage("teju/home/workspace/New/bin/New.apk")
# Run activity
device.startActivity(component='com.android.New')
# Press the Menu button
device.press('KEYCODE_MENU','DOWN_AND_UP')
# Press Add Note menu item
device.press('KEYCODE_A','DOWN_AND_UP')

# Press the Menu button
device.press('KEYCODE_MENU','DOWN_AND_UP')
# Press save menu item
device.press('KEYCODE_S','DOWN_AND_UP')
# Take snapshot
screenshot = device.takeSnapshot()
# Write snapshot to file system
screenshot.writeToFile('example1.png','png')

teju said...

am getting dalvick error when i run my android junit classes coz for plugin.java file i imported jar files like jython and google_src_10.jar files .
and if i run my jython scripts i get error like:


Traceback (most recent call last):
File "/home/teju/workspace/Newtestpy/src/com/android/monkeyrunner/newtest.py", line 7, in
from com.android.monkeyrunner import MonkeyDevice, MonkeyRunner
ImportError: cannot import name MonkeyDevice

teju said...

how to resolve tiz error and if i run through terminal i get error like:

./monkeyrunner -plugin Plugin.jar newtestplugin.py
120307 05:23:52.911:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions] Script terminated due to an exception
120307 05:23:52.911:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions]Traceback (most recent call last):
File "/home/teju/Downloads/android-sdk-linux/tools/newtestplugin.py", line 8, in
from com.android.New import New
ImportError: No module named New

120307 05:23:52.911:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions] at org.python.core.PyException.fillInStackTrace(PyException.java:70)
120307 05:23:52.911:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions] at java.lang.Throwable.(Throwable.java:198)
120307 05:23:52.911:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions] at java.lang.Exception.(Exception.java:46)
120307 05:23:52.911:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions] at java.lang.RuntimeException.(RuntimeException.java:49)
120307 05:23:52.911:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions] at org.python.core.PyException.(PyException.java:46)
120307 05:23:52.911:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions] at org.python.core.PyException.(PyException.java:43)
120307 05:23:52.911:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions] at org.python.core.PyException.(PyException.java:61)

teju said...

120307 05:23:52.911:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions] at org.python.core.Py.ImportError(Py.java:264)
120307 05:23:52.911:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions] at org.python.core.imp.import_logic(imp.java:692)
120307 05:23:52.911:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions] at org.python.core.imp.import_name(imp.java:746)
120307 05:23:52.911:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions] at org.python.core.imp.importName(imp.java:791)
120307 05:23:52.911:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions] at org.python.core.ImportFunction.__call__(__builtin__.java:1236)
120307 05:23:52.911:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions] at org.python.core.PyObject.__call__(PyObject.java:367)
120307 05:23:52.911:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions] at org.python.core.__builtin__.__import__(__builtin__.java:1207)
120307 05:23:52.911:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions] at org.python.core.imp.importFromAs(imp.java:869)
120307 05:23:52.911:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions] at org.python.core.imp.importFrom(imp.java:845)
120307 05:23:52.911:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions] at org.python.pycode._pyx0.f$0(/home/teju/Downloads/android-sdk-linux/tools/newtestplugin.py:28)
120307 05:23:52.911:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions] at org.python.pycode._pyx0.call_function(/home/teju/Downloads/android-sdk-linux/tools/newtestplugin.py)
120307 05:23:52.911:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions] at org.python.core.PyTableCode.call(PyTableCode.java:165)
120307 05:23:52.911:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions] at org.python.core.PyCode.call(PyCode.java:18)
120307 05:23:52.911:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions] at org.python.core.Py.runCode(Py.java:1197)
120307 05:23:52.911:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions] at org.python.core.__builtin__.execfile_flags(__builtin__.java:538)
120307 05:23:52.911:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions] at org.python.util.PythonInterpreter.execfile(PythonInterpreter.java:156)
120307 05:23:52.911:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions] at com.android.monkeyrunner.ScriptRunner.run(ScriptRunner.java:116)
120307 05:23:52.911:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions] at com.android.monkeyrunner.MonkeyRunnerStarter.run(MonkeyRunnerStarter.java:77)
120307 05:23:52.911:S [main] [com.android.monkeyrunner.MonkeyRunnerOptions] at com.android.monkeyrunner.MonkeyRunnerStarter.main(MonkeyRunnerStarter.java:189)


plz help me out

Kay said...

Dear Diego, thanks for all of your help! I am receiving a null pointer exception when I try to run my program in Eclipse. It is upset with the line "MonkeyRunner.waitforconnection()". All blogs seem to link to this webpage for help, but I still cannot figure out the problem. Any help is much appreciated. Again, thanks for all the help so for with this article!

Diego Torres Milano said...

Hi Kay,
Does your script run from the command line or do you receive the same error message as when run from Eclipse ?

menacel said...

Hi,
I followed all of the steps in but I am not able to run scripts.

It gives me the message. The interpreter configured does not exist in the filesystem. Any help?

Diego Torres Milano said...

@menacel,
You may have used the wrong path somewhere.
There are some updates (at the bottom) with a link to a series of screenshots. You should follow them.