Let me know what you think.
Now, to the point. We have presented an analyzed here many monkeyrunner scripts and techniques but we haven't explicitly created some unit tests, and this is precisely what we are going to do.
As our Application Under Test (AUT) we are using the well-known Temperature Converter, which was used many times to demonstrate other concepts as well.
The source code is as usual available through github.
Additionally, we are also using the help of AndroidViewClient which is available at github too and was introduced in monkeyrunner: interacting with the Views. The central idea is to use AndroidViewClient facilities to create a unit test. Let's name this script temperature-converter-view-client.mr.
#! /usr/bin/env monkeyrunner
'''
Created on 2012-03-08
@author: diego
'''
import sys
import unittest
import subprocess
import socket
import re
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
import viewclient
class TemperatureConverterActivityTests(unittest.TestCase):
def setUp(self):
# connect to the device
self.device = MonkeyRunner.waitForConnection(60)
self.assertNotEqual(None, self.device)
self.device.wake()
# start TemperatureConverter
self.device.startActivity(component="com.example.i2at.tc/.TemperatureConverterActivity")
# clear the field
for n in range(10):
self.device.press('DEL', MonkeyDevice.DOWN_AND_UP)
# create the client
self.viewclient = viewclient.ViewClient(self.device)
def tearDown(self):
pass
def testConversion(self):
C = '123'
F = '253.4'
MonkeyRunner.sleep(1)
self.device.type(C)
MonkeyRunner.sleep(1)
self.viewclient.dump()
celsius = self.viewclient.findViewById('id/celsius')['mText']
fahrenheit = self.viewclient.findViewById('id/fahrenheit')['mText']
self.assertEqual(celsius, C)
self.assertEqual(fahrenheit, F)
if __name__ == '__main__':
unittest.main()
It is noticeable how the use of AndroidViewClient simplifies this test.
So if everything goes well, providing that your emulator or device is running and reachable, you will receive this output for the test run:
Hope this helps.
So if everything goes well, providing that your emulator or device is running and reachable, you will receive this output for the test run:
$ ./temperature-converter-view-client.mr
.
----------------------------------------------------------------------
Ran 1 test in 8.801s
OK
Hope this helps.
16 comments:
Thanks for this unique testing.
Sample Assessments
Hi Diego,
i was wondering how can i automate certain tests like, playing audio/video multiple times(locally or streaming). when we use adb shell, we can use "am start" commands(eg: am start -d -n package name).
how can i do the same in monkeyrunner? i know there is command called "shell" that can help me do this, is there any other way?
Thanks in advance,
Avinash
@Avinash Rao,
Yes, there's another way when you use monkeyrunner, despite the fact you mentioned of MonkeyDevice.shell() still being a valid option.
This alternative is MonkeyDevice.startActivity().
Hi Diego,
so if i want to convert the command:
am start -d /mnt/sdcard/lighters.mp3 -n com.android.gallery3d/com.android.gallery3d.app.MovieActivity
to monkeyrunner format, how will it look?
I tried this,
device.startActivity('ACTION_RUN','/mnt/sdcard/lighters.mp3','com.android.gallery3d/com.android.gallery3d.app.MovieActivity')
but its not working.
-Avinash Rao
Hey Diego,
I found out the correct command :)
device.startActivity(action='android.intent.action.VIEW',data='/mnt/sdcard/397b_av_h264_bl_640x480_15fps_1Mbps_aac_128kbps.3gp',component='com.google.android.gallery3d/com.android.gallery3d.app.MovieActivity')
was doing it wrong previously.
NOTE: i am using a different package and intent also a different file, from my previous comment.
Thanks a lot for helping Diego, will contact you if i need more info
-Avinash Rao
Diego,
Is it possible to run multiple monkey runner scripts that have different unit test cases inside them. I want to be able to run 2 sets of scripts of 2 different devices. I need to start script1 on device1 and later if needed i need to start script2 on deivce2,is there a way to acheive this currently as i understand monkey runner can only handle multiple devices if they are in same script. Not 2 separate instances carrying 2 separate scripts.Please help
@Mallik Mahankali,
You are right, there's no problem creating connections for several devices in a monkeyrunner script but running several scripts concurrently usually lead to exceptions and broken connections. I think the best approach to cope with this limitation is to handle the logic inside a single monkeyrunner script (you can also import other tests) which hold the connections to the devices.
Hi Diego,
Imagine you have 2 tests on this TemperatureConverterActivityTests class.
I think it will get stuck during the 2nd tests at setUp method. It will hang in self.device = MonkeyRunner.waitForConnection(60)
I guess the reason is that it tries to connect to a device that is already connected (i am not sure though)
Do you have ideas on how to handle that?
Thanks
@Diego,
Issue seems to happen due to same view server port being assigned by monkeyrunner to multiple devices only when running 2 scripts.Can you help me understand how to control logic to connect all devices in 1 script. do u mean some ting like this
test1:
check a config file to see if phone and test cases are needed and if yes run them
repeat same for test2, test3...
Diego,
Is there a way to use AndroidViewClient on a real device?
@Unknown,
Yes, it can be run on real rooted devices as long as the variables ro.secure and ro.debuggable have the right values.
This one-liner can be used to test the conditions:
$ (eval $(adb -s shell getprop | egrep '\[ro\.secure]|\[ro\.debuggable]' | sed 's/\./_/g; s/]: /=/g; s/[][\r]//g'); [[ 1 == $ro_secure && 0 == $ro_debuggable ]] && echo "System is secure: AVC won't work" || echo "System is not secure: AVC will work")
I think I will add this test to AVC.
In the previous comment it's: -s <serialno> but blogspot removed it
Hi Diego,
In your example, there is only one test in the class. If you had had multiple tests in your class, would you still have waitForConnection or connectToDeviceOrExit in the setUp? I would think that only doing this once would be ideal instead of before every test.
Just curious of your opinion.
Thanks,
Andrew
Also, I see that you use findViewById on your viewclient object. I have yet to have success with this method. The only IDs that show up for me are the unique IDs, which I will have no knowledge of at the time I write the test script. Is this a known effect of AndroidViewClient? In comparison, I can getViewById using MonkeyDevice, but getLocation doesn't work on the MonkeyView class. The most useful workflow I've found is to leverage the text field and use AndroidViewClient with findViewWithTextOrRaise. Still, I'm unable to use it successfully with RegEx, so far, but that may be user error.
Thanks again for all the posts, it has been very helpful!
-Andrew
Hi Diego,
Your AndroidViewClient is simply awesome. I do have a little problem with the MonkeyRunner.waitForConnection. If I have two tests cases, the code gets stuck in the second time it is running the waitForConnection. I tried this on your coe and I managed to reproduce. Do you have any thoughts?
appreciate it
@Rafael Lima,
There should be a single ViewClient.connectToDeviceOrExit() or MonkeyRunner.waitForConnection() per script.
Post a Comment