1

I'm tryng to test some app using monkeyrunner and AndroidViewClient, also I have used culebra to generate code, But I have this erro:

from com.dtmilano.android.viewclient import ViewClient, TextView, EditText
SyntaxError: ("mismatched input 'as' expecting COLON", ('/home/experts/AndroidViewClient-master/src/com/dtmilano/android/viewclient.py', 3795, 35, ''))

This is my script whit monkeyrunner and AndroidViewClient

import re
import sys
import os

try:
   sys.path.append(os.path.join(os.environ['ANDROID_VIEW_CLIENT_HOME'], 'src'))
except:
   pass

from com.dtmilano.android.viewclient import ViewClient, TextView, EditText
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice, MonkeyImage

def main():
# Connects to the current device, returning a MonkeyDevice object
   emulatorid = 'emulator-5558'
   device = MonkeyRunner.waitForConnection('',emulatorid)
   print "waiting for connection...\n"

   package = "com.duolingo"
   activity = "app.LoginActivity"

   # sets the name of the component to start
   runComponent = package + "/." + activity

   #Runs the component
   print "Start Component"
   device.startActivity(component=runComponent)
   MonkeyRunner.sleep(10)

   vc = ViewClient(device)
   vc.dump()
   vc.sleep(_s)
   vc.dump(window=-1)
   vc.findViewWithTextOrRaise(u'GET STARTED').touch()
   vc.sleep(_s)
   vc.dump(window=-1)
   vc.findViewWithTextOrRaise(u'Spanish', root=self.vc.findViewByIdOrRaise('id/no_id/3')).touch()

   # Takes a screenshot
   screenshot = device.takeSnapshot()

   # Writes the screenshot to a file
   screenshot.writeToFile('./device1.png','png')

   print "end"
   if __name__ == '__main__':
   main()

If I execute this wthiout monkeyrunner it show an erro about "ViewClient(device)", This script is inside an loop (for).

EDIT:

I executed culebra and now I have my scripts running fine!! But, it works by CommandLine ($ myscripttest.py emulator-5554) If I call it using subprocess.call, where emulatorid='emulator-5554'

subprocess.call('path/script_files/myscripttest.py' + ' ' + emulatorid, shell=True)

it shows an error:

  File "/path/script_files/myscripttest.py", line 9, in <module>
from com.dtmilano.android.viewclient import ViewClient
File "/usr/local/lib/python2.7/dist-packages/androidviewclient-11.0.7-py2.7.egg/com/dtmilano/android/viewclient.py", line 43, in <module>
import xml.parsers.expat
File "/usr/lib/python2.7/xml/parsers/expat.py", line 4, in <module>
from pyexpat import *
ImportError: /usr/lib/python2.7/lib-dynload/pyexpat.x86_64-linux-gnu.so: undefined symbol: XML_SetHashSalt

I verify with this code: Where is the error?

$ ldd /usr/lib/python2.7/lib-dynload/pyexpat.x86_64-linux-gnu.so 
linux-vdso.so.1 =>  (0x00007fffe5dc2000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f55d2fd4000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f55d2c0f000)
libexpat.so.1 => /lib/x86_64-linux-gnu/libexpat.so.1 (0x00007f55d29e5000)
/lib64/ld-linux-x86-64.so.2 (0x00007f55d3403000)
CodeIK
  • 177
  • 1
  • 14

1 Answers1

8

AndroidViewClient/culebra is a monkeyrunner replacement. You should use one or the other, not both together in a script.

culerba or Culebra GUI will generate the correct test or script template for you that you can further customize.

All the tests and scripts generated by these tools should be executed with python 2.x.

I think I could guess what you are trying to achieve with your script and I'm going to give a step-by-step example using culebra so you can understand how easy it is.

Step 1

Launch culebra telling that you also want to start a specific Activity

$ culebra -GuU --start-activity=com.duolingo/.app.LoginActivity --scale=0.5 -o ~/tmp/duolingo-screenshot.py

this runs the GUI (-G), does not verify the Views in the dump (-u), create a unit test (-U), start the Activity (--start-activity), scales the window 50% so it fits on the screen (--scale) and saves the test in a file (-o).

If everything goes well, you will see Culebra GUI.

enter image description here

Step 2

Click on the GET STARTED button on the window.

enter image description here

Step 3

Click on Spanish

enter image description here

Step 4

Take the desired screenshot using the context menu (alternate click on the window) or keyboard shortcut

enter image description here

Step 5

Close the window.

At this point the test is generated and it contains something like this

#! /usr/bin/env python
# -*- coding: utf-8 -*-
'''
Copyright (C) 2013-2014  Diego Torres Milano
Created on 2015-12-22 by Culebra v11.0.8
                      __    __    __    __
                     /  \  /  \  /  \  /  \ 
____________________/  __\/  __\/  __\/  __\_____________________________
___________________/  /__/  /__/  /__/  /________________________________
                   | / \   / \   / \   / \   \___
                   |/   \_/   \_/   \_/   \    o \ 
                                           \_____/--<
@author: Diego Torres Milano
@author: Jennifer E. Swofford (ascii art snake)
'''


import re
import sys
import os


import unittest

from com.dtmilano.android.viewclient import ViewClient, CulebraTestCase

TAG = 'CULEBRA'


class CulebraTests(CulebraTestCase):

    @classmethod
    def setUpClass(cls):
        cls.kwargs1 = {'ignoreversioncheck': False, 'verbose': False, 'ignoresecuredevice': False}
        cls.kwargs2 = {'forceviewserveruse': False, 'useuiautomatorhelper': False, 'ignoreuiautomatorkilled': True, 'autodump': False, 'startviewserver': True, 'compresseddump': True}
        cls.options = {'start-activity': 'com.duolingo/.app.LoginActivity', 'concertina': False, 'device-art': None, 'use-jar': False, 'multi-device': False, 'unit-test-class': True, 'save-screenshot': None, 'use-dictionary': False, 'glare': False, 'dictionary-keys-from': 'id', 'scale': 0.5, 'find-views-with-content-description': True, 'window': -1, 'orientation-locked': None, 'save-view-screenshots': None, 'find-views-by-id': True, 'log-actions': False, 'use-regexps': False, 'null-back-end': False, 'auto-regexps': None, 'do-not-verify-screen-dump': True, 'verbose-comments': False, 'gui': True, 'find-views-with-text': True, 'prepend-to-sys-path': False, 'install-apk': None, 'drop-shadow': False, 'output': None, 'unit-test-method': None, 'interactive': False}
        cls.sleep = 5

    def setUp(self):
        super(CulebraTests, self).setUp()

    def tearDown(self):
        super(CulebraTests, self).tearDown()

    def preconditions(self):
        if not super(CulebraTests, self).preconditions():
            return False
        return True

    def testSomething(self):
        if not self.preconditions():
            self.fail('Preconditions failed')

        _s = CulebraTests.sleep
        _v = CulebraTests.verbose

        self.vc.dump(window=-1)
        self.vc.findViewWithTextOrRaise(u'GET STARTED').touch()
        self.vc.sleep(_s)
        self.vc.dump(window=-1)
        self.vc.findViewWithTextOrRaise(u'Spanish', root=self.vc.findViewByIdOrRaise('id/no_id/5')).touch()
        self.vc.sleep(_s)
        self.vc.dump(window=-1)
        self.vc.writeImageToFile('/tmp/${serialno}-${focusedwindowname}-${timestamp}.png', 'PNG', 'None', False, False)


if __name__ == '__main__':
    CulebraTests.main()

So when you run the test again, you will obtain a new screenshot.

IMPORTANT: because the test does not contain any specific information about the device or its characteristics like screen size and such and it's not using coordinates to touch but View properties like text or id you can run the same test on a very different device, like let's say a table, and it will run successfully. Even the screenshots are saved prefixed by the device's serial number so you can run all of them at the same time and on the same CI server if you like.

Extra tip

If you run the test more than once without reinstalling the app perhaps the second time you are not presented with the GET STARTED screen but with Pick a Daily Goal. If we wanted to consider this alternative too we can just edit the script and add the corresponding condition

def testSomething(self):
    if not self.preconditions():
        self.fail('Preconditions failed')

    _s = CulebraTests.sleep
    _v = CulebraTests.verbose

    self.vc.dump(window=-1)
    if not self.vc.findViewWithText(u'Pick a Daily Goal'):
        self.vc.findViewWithTextOrRaise(u'GET STARTED').touch()
        self.vc.sleep(_s)
        self.vc.dump(window=-1)
        self.vc.findViewWithTextOrRaise(u'Spanish', root=self.vc.findViewByIdOrRaise('id/no_id/5')).touch()
        self.vc.sleep(_s)
        self.vc.dump(window=-1)
    self.vc.writeImageToFile('/tmp/${serialno}-${focusedwindowname}-${timestamp}.png', 'PNG', 'None', False, False)

Even if you want to frame the screenshot in a device image you can do it much easier than with Android Studio where you have to re-select the options again and again. Just change the parameters of takeScreenshot, set the STUDIO_DIR environment variable pointing to your Studio installation

self.vc.writeImageToFile('/tmp/${serialno}-${focusedwindowname}-${timestamp}.png', 'PNG', 'nexus_5', True, True)

and voila!

enter image description here

Diego Torres Milano
  • 65,697
  • 9
  • 111
  • 134
  • I use culebra thanks by the steps. Now I have my test working by CommandLine. But if I execute it using subprocess.call it shows an erro I copied the erro on EDIT (section) Thanks!! @dtmilano – CodeIK Dec 23 '15 at 18:16