1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072 |
- #!C:\tools\Python27\python.exe
- # -*- coding: utf-8 -*-
- '''
- Copyright (C) 2013-2015 Diego Torres Milano
- Created on Mar 28, 2013
- Culebra helps you create AndroidViewClient scripts generating a working template that can be
- modified to suit more specific needs.
- __ __ __ __
- / \ / \ / \ / \
- ____________________/ __\/ __\/ __\/ __\_____________________________
- ___________________/ /__/ /__/ /__/ /________________________________
- | / \ / \ / \ / \ \___
- |/ \_/ \_/ \_/ \ o \
- \_____/--<
- @author: Diego Torres Milano
- @author: Jennifer E. Swofford (ascii art snake)
- '''
- __version__ = '10.3.0'
- import re
- import sys
- import os
- import getopt
- import warnings
- import subprocess
- import codecs
- import calendar
- from datetime import date
- try:
- sys.path.insert(0, os.path.join(os.environ['ANDROID_VIEW_CLIENT_HOME'], 'src'))
- except:
- pass
- from com.dtmilano.android.viewclient import ViewClient, ViewClientOptions, View, CulebraOptions
- from com.dtmilano.android.culebron import Culebron, Operation, Unit
- DEBUG = False
- USAGE = 'usage: %s [OPTION]... [serialno]'
- TAG = 'CULEBRA'
- class Descriptor:
- CONTENT_DESCRIPTION = 'content-description'
- TEXT = 'text'
- ID = 'id'
- @staticmethod
- def findBestDescriptor(view):
- '''
- Finds the best possible descriptor for the View
- '''
-
- cd = view.getContentDescription()
- if cd and options[CulebraOptions.FIND_VIEWS_WITH_CONTENT_DESCRIPTION]:
- return Descriptor.CONTENT_DESCRIPTION
- else:
- t = view.getText()
- if t and options[CulebraOptions.FIND_VIEWS_WITH_TEXT]:
- return Descriptor.TEXT
- return Descriptor.ID
-
- def fillAutoRegexpsRes():
- are = {}
- are['clock'] = re.compile('[012]?\d:[0-5]\d')
- d = "("
- for i in range(7):
- d += calendar.day_abbr[i]
- if i != 6:
- d += '|'
- d += '), ('
- for i in range(1, 13):
- d += calendar.month_name[i]
- if i != 12:
- d += '|'
- d += ') [0123]\d'
- are['date'] = re.compile(d, re.IGNORECASE)
- are['battery'] = re.compile('Charging, \d\d%')
- return are
- CulebraOptions.AUTO_REGEXPS_RES = fillAutoRegexpsRes()
- SB_NO_JAR = 'no-jar'
- SB_JAR = 'jar'
- SB_JAR_LINUX = 'jar-linux'
- SHEBANG = {
- SB_NO_JAR: '#! /usr/bin/env python',
- SB_JAR: '#! /usr/bin/env shebang monkeyrunner -plugin $ANDROID_VIEW_CLIENT_HOME/bin/androidviewclient-$ANDROID_VIEW_CLIENT_VERSION.jar @!',
- SB_JAR_LINUX: '#! /usr/local/bin/shebang monkeyrunner -plugin $AVC_HOME/bin/androidviewclient-$AVC_VERSION.jar @!'
- }
- indent = ''
- prefix = ''
- def shortAndLongOptions():
- '''
- @return: the list of corresponding (short-option, long-option) tuples
- '''
- short_opts = CulebraOptions.SHORT_OPTS.replace(':', '')
- if len(short_opts) != len(CulebraOptions.LONG_OPTS):
- raise Exception('There is a mismatch between short and long options')
- t = tuple(short_opts) + tuple(CulebraOptions.LONG_OPTS)
- l2 = len(t) / 2
- sl = []
- for i in range(l2):
- sl.append((t[i], t[i + l2]))
- return sl
- def usage(exitVal=1):
- print >> sys.stderr, USAGE % progname
- print >> sys.stderr, "Try '%s --help' for more information." % progname
- sys.exit(exitVal)
- def help():
- print >> sys.stderr, USAGE % progname
- print >> sys.stderr
- print >> sys.stderr, "Options:"
- for so, lo in shortAndLongOptions():
- o = ' -%c, --%s' % (so, lo)
- if lo[-1] == '=':
- o += CulebraOptions.LONG_OPTS_ARG[lo[:-1]]
- try:
- o = '%-34s %-45s' % (o, CulebraOptions.OPTS_HELP[so])
- except:
- pass
- print >> sys.stderr, o
- sys.exit(0)
- def version():
- print progname, __version__
- sys.exit(0)
- def autoRegexpsHelp():
- print >> sys.stderr, "Available %s options:" % CulebraOptions.AUTO_REGEXPS
- print >> sys.stderr, "\thelp: prints this help"
- print >> sys.stderr, "\tall: includes all the available regexps"
- for r in CulebraOptions.AUTO_REGEXPS_RES:
- print >> sys.stderr, "\t%s: %s" % (r, CulebraOptions.AUTO_REGEXPS_RES[r].pattern)
- print >> sys.stderr
- sys.exit(0)
- def error(msg, fatal=False):
- print >> sys.stderr, "%s: ERROR: %s" % (progname, msg)
- if fatal:
- sys.exit(1)
- def notNull(val, default):
- if val:
- return val
- return default
- def printVerboseComments(view):
- '''
- Prints the verbose comments for view.
- '''
- print '\n%s# class=%s' % (indent, view.getClass()),
- try:
- text = view.getText()
- if text:
- u = 'u' if isinstance(text, unicode) else ''
- if '\n' in text:
- text = re.sub(r'\n(.)', r'\n#\1', text)
- print " text=%c'%s'" % (u, text),
- except:
- pass
- try:
- contentDescription = view.getContentDescription()
- if contentDescription:
- print u" cd='%s'" % contentDescription,
- except:
- pass
- try:
- tag = view.getTag()
- if tag and tag != 'null':
- print ' tag=%s' % tag,
- except:
- pass
- print
- def variableNameFromIdOrKey(view):
- '''
- Returns a suitable variable name from the id.
- @type view: L{View}
- @param id: the View from where the I{uniqueId} is obtained
- @return: the variable name from the id
- '''
- var = view.variableNameFromId()
- if options[CulebraOptions.USE_DICTIONARY]:
- return '%sviews[\'%s\']' % (prefix, notNull(dictionaryKeyFrom(options[CulebraOptions.DICTIONARY_KEYS_FROM], view), var))
- else:
- return var
- def dictionaryKeyFrom(key, view):
- if key == 'id':
- return view.getUniqueId()
- elif key == 'text':
- return view.getText()
- elif key == 'content-description':
- return view.getContentDescription()
- else:
- raise Exception('Not a valid dictionary key: %s' % key)
- def escapeRegexpSpecialChars(text):
- return re.escape(text)
- def printFindViewWithText(view, useregexp, op=Operation.ASSIGN, arg=None):
- '''
- Prints the corresponding statement.
- @type view: L{View}
- @param view: the View
- '''
- text = view.getText()
- isUnicode = isinstance(text, unicode)
- if isUnicode and sys.stdout.encoding is None:
- warnings.warn('''\
- You are trying to print unicode characters to an unencoded stdout, it will probably fail.
- You have to set PYTHONIOENCODING environment variable. For example:
- export PYTHONIOENCODING=utf-8
- ''')
- u = 'u' if isUnicode else ''
- if text:
- var = variableNameFromIdOrKey(view)
- if text.find(u"\n") > 0 or text.find(u"'") > 0:
- # 2 quotes + 1 quote = 3 quotes
- text = "''%s''" % text
- if useregexp:
- # if there are special chars already in the text escape them
- text = escapeRegexpSpecialChars(text)
- if options[CulebraOptions.AUTO_REGEXPS]:
- for r in options[CulebraOptions.AUTO_REGEXPS]:
- autoRegexp = CulebraOptions.AUTO_REGEXPS_RES[r]
- if autoRegexp.match(text):
- text = autoRegexp.pattern
- break
- text = "re.compile(%s'%s')" % (u, text)
- else:
- text = "%s'%s'" % (u, text)
-
- if op == Operation.ASSIGN:
- if options[CulebraOptions.MULTI_DEVICE]:
- warnings.warn('Multi-device not implemented yet for this case')
- else:
- print u'%s%s = %svc.findViewWithTextOrRaise(%s)' % (indent, var, prefix, text)
- elif op == Operation.TOUCH_VIEW:
- root = ', root=%svc.findViewByIdOrRaise(\'%s\')' % (prefix, arg.getUniqueId()) if arg else ''
- if options[CulebraOptions.MULTI_DEVICE]:
- print u'%s[_vc.findViewWithTextOrRaise(%s%s).touch() for _vc in %sallVcs()]' % (indent, text, prefix, root)
- else:
- logAction(u'touching view with text=%s' % text)
- print u'%s%svc.findViewWithTextOrRaise(%s%s).touch()' % (indent, prefix, text, root)
- elif op == Operation.TYPE:
- if options[CulebraOptions.MULTI_DEVICE]:
- warnings.warn('Multi-device not implemented yet for this case')
- else:
- print '%s%svc.findViewWithTextOrRaise("%s").type(u"%s")' % (indent, prefix, text, arg)
- elif op == Operation.TEST:
- if options[CulebraOptions.MULTI_DEVICE]:
- warnings.warn('Multi-device not implemented yet for this case')
- else:
- print '%s%sassertIsNotNone(%svc.findViewWithText(%s))' % (indent, prefix, prefix, text)
- elif kwargs1[CulebraOptions.VERBOSE]:
- warnings.warn('View with id=%s has no text' % view.getUniqueId())
- def printFindViewWithContentDescription(view, useregexp, op=Operation.ASSIGN, arg=None):
- '''
- Prints the corresponding statement.
- @type view: L{View}
- @param view: the View
- '''
- contentDescription = view.getContentDescription()
- if contentDescription:
- var = variableNameFromIdOrKey(view)
- if useregexp:
- if options[CulebraOptions.AUTO_REGEXPS]:
- for r in options[CulebraOptions.AUTO_REGEXPS]:
- autoRegexp = CulebraOptions.AUTO_REGEXPS_RES[r]
- if autoRegexp.match(contentDescription):
- contentDescription = autoRegexp.pattern
- break
- contentDescription = "re.compile(u'''%s''')" % contentDescription
- else:
- contentDescription = "u'''%s'''" % contentDescription
-
- if op == Operation.ASSIGN:
- if options[CulebraOptions.MULTI_DEVICE]:
- warnings.warn('Multi-device not implemented yet for this case')
- else:
- print '%s%s = %svc.findViewWithContentDescriptionOrRaise(%s)' % (indent, var, prefix, contentDescription)
- elif op == Operation.TOUCH_VIEW:
- if options[CulebraOptions.MULTI_DEVICE]:
- warnings.warn('Multi-device not implemented yet for this case')
- else:
- logAction(u'touching view with content-description=%s' % contentDescription)
- print '%s%svc.findViewWithContentDescriptionOrRaise(%s).touch()' % (indent, prefix, contentDescription)
- elif op == Operation.TYPE:
- if options[CulebraOptions.MULTI_DEVICE]:
- warnings.warn('Multi-device not implemented yet for this case')
- else:
- print '%s%svc.findViewWithContentDescriptionOrRaise(%s).type(u"%s")' % (indent, prefix, contentDescription, arg)
- elif op == Operation.TEST:
- if options[CulebraOptions.MULTI_DEVICE]:
- warnings.warn('Multi-device not implemented yet for this case')
- else:
- print '%s%sassertEquals(%svc.findViewWithContentDescriptionOrRaise(%s).getText(), u\'\'\'%s\'\'\')' % (indent, prefix, prefix, contentDescription, arg)
- else:
- error("Invalid operation in %s: %s" % (sys._getframe().f_code.co_name), op)
-
- elif kwargs1[CulebraOptions.VERBOSE]:
- warnings.warn('View with id=%s has no content-description' % view.getUniqueId())
- def printFindViewById(view, op=Operation.ASSIGN, arg=None):
- '''
- Prints the corresponding statement.
- @type view: L{View}
- @param view: the View
- '''
- var = variableNameFromIdOrKey(view)
- _id = view.getId() if view.getId() else view.getUniqueId()
- if op == Operation.ASSIGN:
- if options[CulebraOptions.MULTI_DEVICE]:
- logAction('finding view with id=%s on ${serialno}' % _id)
- print '%s%s = [_vc.findViewByIdOrRaise("%s") for _vc in %sallVcs()]' % (indent, var, _id, prefix)
- else:
- logAction('finding view with id=%s' % _id)
- print '%s%s = %svc.findViewByIdOrRaise("%s")' % (indent, var, prefix, _id)
- elif op == Operation.TOUCH_VIEW:
- if options[CulebraOptions.MULTI_DEVICE]:
- logAction(u'touching view with id=%s on ${serialno}' % _id)
- print '%s[_vc.findViewByIdOrRaise("%s").touch() for _vc in %sallVcs()]' % (indent, _id, prefix)
- else:
- logAction(u'touching view with id=%s' % _id)
- print '%s%svc.findViewByIdOrRaise("%s").touch()' % (indent, prefix, _id)
- elif op == Operation.TYPE:
- if options[CulebraOptions.MULTI_DEVICE]:
- warnings.warn('Multi-device not implemented yet for this case')
- else:
- logAction('typing "%s" on view with id=' % (arg, _id))
- print '%s%svc.findViewByIdOrRaise("%s").type(u"%s")' % (indent, prefix, _id, arg)
- elif op == Operation.TEST:
- if options[CulebraOptions.MULTI_DEVICE]:
- warnings.warn('Multi-device not implemented yet for this case')
- else:
- print '%s%sassertEquals(%svc.findViewByIdOrRaise("%s").getText(), u\'\'\'%s\'\'\')' % (indent, prefix, prefix, _id, arg)
- else:
- error("Invalid operation in %s: %s" % (sys._getframe().f_code.co_name, op))
- def printTraverse(dump=None):
- '''
- Prints the result of traversing the tree.
- A previously obtained dump can be passed as a parameter and in such case that
- tree is used.
-
- @param dump: Dump of Views previously obtained via L{ViewClient.dump()}
- @type dump: list
- '''
-
- print
- if dump:
- for view in dump:
- transform(view)
- else:
- vc.traverse(transform=transform)
- print
- def printDump(window, dump=None):
- '''
- Prints a dump.
-
- @param window: The window id to use to print the dump
- @type window: int or str
- @param dump: Dump of Views previously obtained via L{ViewClient.dump()}
- @type dump: list
- '''
-
- if options[CulebraOptions.MULTI_DEVICE]:
- logAction('dumping content of window=%s on ${serialno}' % window)
- print '%s[_vc.dump(window=%s) for _vc in %sallVcs()]' % (indent, window, prefix)
- else:
- logAction('dumping content of window=%s' % window)
- print '%s%svc.dump(window=%s)' % (indent, prefix, window)
-
- if not options[CulebraOptions.DO_NOT_VERIFY_SCREEN_DUMP]:
- printTraverse(dump)
-
- def printSleep(secs):
- '''
- Prints a sleep.
-
- This method relies on shortcut variables being set (i.e. _s)
- '''
-
- if options[CulebraOptions.MULTI_DEVICE]:
- print '%s[_vc.sleep(%s) for _vc in %sallVcs()]' % (indent, secs if secs != Operation.DEFAULT else '_s', prefix)
- else:
- print '%s%svc.sleep(%s)' % (indent, prefix, secs if secs != Operation.DEFAULT else '_s')
-
- def printPress(keycode):
- '''
- Prints a key press
- '''
-
- if options[CulebraOptions.MULTI_DEVICE]:
- logAction(u'pressing key=%s on ${serialno}' % keycode)
- print '%s[_d.press(\'%s\') for _d in %sallDevices()]' % (indent, keycode, prefix)
- else:
- logAction(u'pressing key=%s' % keycode)
- print '%s%sdevice.press(\'%s\')' % (indent, prefix, keycode)
-
- def printDrag(start, end, duration, steps, unit, orientation):
- '''
- Prints a drag
- '''
-
- if unit == Unit.PX:
- if options[CulebraOptions.MULTI_DEVICE]:
- warnings.warn('Multi-device not implemented yet for this case')
- else:
- print '%s%sdevice.drag(%s, %s, %d, %d, %d)' % (indent, prefix, start, end, duration, steps, orientation)
- elif unit == Unit.DIP:
- if options[CulebraOptions.MULTI_DEVICE]:
- warnings.warn('Multi-device not implemented yet for this case')
- else:
- print '%s%sdevice.dragDip(%s, %s, %d, %d, %d)' % (indent, prefix, start, end, duration, steps, orientation)
- else:
- raise RuntimeError('Invalid unit: %s' % unit)
-
- def printTouch(x, y, unit, orientation):
- '''
- Prints a touch
- '''
-
- if unit == Unit.PX:
- if options[CulebraOptions.MULTI_DEVICE]:
- warnings.warn('Multi-device not implemented yet for this case')
- else:
- logAction(u'touching point by PX @ (%s, %s) orientation=%s' % (x, y, orientation))
- print '%s%sdevice.touch(%s, %s, %s)' % (indent, prefix, x, y, orientation)
- elif unit == Unit.DIP:
- if options[CulebraOptions.MULTI_DEVICE]:
- warnings.warn('Multi-device not implemented yet for this case')
- else:
- logAction(u'touching point by DIP @ (%s, %s) orientation=%s' % (x, y, orientation))
- print '%s%sdevice.touchDip(%s, %s, %s)' % (indent, prefix, x, y, orientation)
- else:
- raise RuntimeError('Invalid unit: %s' % unit)
-
- def printLongTouch(x, y, duration, unit, orientation):
- '''
- Prints a long touch
- '''
-
- if unit == Unit.PX:
- if options[CulebraOptions.MULTI_DEVICE]:
- warnings.warn('Multi-device not implemented yet for this case')
- else:
- logAction(u'long touching point by PX @ (%s, %s) duration=%s orientation=%s' % (x, y, duration, orientation))
- print '%s%sdevice.longTouch(%s, %s, %s, %s)' % (indent, prefix, x, y, duration, orientation)
- elif unit == Unit.DIP:
- if options[CulebraOptions.MULTI_DEVICE]:
- warnings.warn('Multi-device not implemented yet for this case')
- else:
- logAction(u'long touching point by DIP @ (%s, %s) duration=%s orientation=%s' % (x, y, duration, orientation))
- print '%s%sdevice.longTouch(%s, %s, %s, %s)' % (indent, prefix, x, y, duration, orientation)
- else:
- raise RuntimeError('Invalid unit: %s' % unit)
-
- def printSaveViewScreenshot(view, filename, _format):
- '''
- Prints the writeImageToFile for the specified L{View}.
-
- @type view: L{View}
- @param view: the View
- @type filename: str
- @param filename: the filename to store the image
- @type _format: str
- @param _format: The image format (i.e. PNG)
- '''
- if options[CulebraOptions.MULTI_DEVICE]:
- warnings.warn('Multi-device not implemented yet for this case')
- else:
- # FIXME: if -u was passed in the command line then we are not saving the variables and thus
- # next line will generate an error in the script as the variable is 'undefined'
- print '%s%s.writeImageToFile(\'%s\', \'%s\')' % (indent, view.variableNameFromId(), filename, _format)
-
- def printFlingBackward(view):
- if options[CulebraOptions.MULTI_DEVICE]:
- warnings.warn('Multi-device not implemented yet for this case')
- else:
- # FIXME: if -u was passed in the command line then we are not saving the variables and thus
- # next line will generate an error in the script as the variable is 'undefined'
- logAction('flinging backward view with id=%s' % view.getId())
- print '%s%s.uiScrollable.flingBackward()' % (indent, view.variableNameFromId())
-
- def printFlingForward(view):
- if options[CulebraOptions.MULTI_DEVICE]:
- warnings.warn('Multi-device not implemented yet for this case')
- else:
- # FIXME: if -u was passed in the command line then we are not saving the variables and thus
- # next line will generate an error in the script as the variable is 'undefined'
- logAction('flinging forward view with id=%s' % view.getId())
- print '%s%s.uiScrollable.flingForward()' % (indent, view.variableNameFromId())
-
- def printFlingToBeginning(view):
- if options[CulebraOptions.MULTI_DEVICE]:
- warnings.warn('Multi-device not implemented yet for this case')
- else:
- # FIXME: if -u was passed in the command line then we are not saving the variables and thus
- # next line will generate an error in the script as the variable is 'undefined'
- logAction('flinging to beginning view with id=%s' % view.getId())
- print '%s%s.uiScrollable.flingToBeginning()' % (indent, view.variableNameFromId())
-
- def printFlingToEnd(view):
- if options[CulebraOptions.MULTI_DEVICE]:
- warnings.warn('Multi-device not implemented yet for this case')
- else:
- # FIXME: if -u was passed in the command line then we are not saving the variables and thus
- # next line will generate an error in the script as the variable is 'undefined'
- logAction('flinging to end view with id=%s' % view.getId())
- print '%s%s.uiScrollable.flingToEnd()' % (indent, view.variableNameFromId())
-
- def printOpenNotification():
- if options[CulebraOptions.MULTI_DEVICE]:
- warnings.warn('Multi-device not implemented yet for this case')
- else:
- logAction('opening Notification')
- print '%s%svc.uiDevice.openNotification()' % (indent, prefix)
-
- def printOpenQuickSettings():
- if options[CulebraOptions.MULTI_DEVICE]:
- warnings.warn('Multi-device not implemented yet for this case')
- else:
- logAction('opening Quick Settings')
- print '%s%svc.uiDevice.openQuickSettings()' % (indent, prefix)
-
- def printChangeLanguage(code):
- if options[CulebraOptions.MULTI_DEVICE]:
- warnings.warn('Multi-device not implemented yet for this case')
- else:
- logAction('Changing language to %s' % code)
- print '%s%svc.uiDevice.changeLanguage("%s")' % (indent, prefix, code)
- def printTakeSnapshot(filename, _format, deviceart, dropshadow, screenglare):
- '''
- Prints the corresponding writeImageToFile() to take a snapshot
- '''
-
- if options[CulebraOptions.MULTI_DEVICE]:
- warnings.warn('Multi-device not implemented yet for this case')
- else:
- logAction(u'taking snapshot @ %s format=%s %s %s %s' % (filename, _format, deviceart, dropshadow, screenglare))
- print '%s%svc.writeImageToFile(\'%s\', \'%s\', \'%s\', %s, %s)' % (indent, prefix, filename, _format, deviceart, dropshadow, screenglare)
-
-
- def traverseAndPrint(view):
- '''
- Traverses the View tree and prints the corresponding statement.
- @type view: L{View}
- @param view: the View
- '''
- if DEBUG:
- print >> sys.stderr, "traverseAndPrint(view=%s)" % view.getId()
- if options[CulebraOptions.VERBOSE_COMMENTS]:
- printVerboseComments(view)
- if options[CulebraOptions.FIND_VIEWS_BY_ID]:
- printFindViewById(view)
- if options[CulebraOptions.FIND_VIEWS_WITH_TEXT]:
- printFindViewWithText(view, options[CulebraOptions.USE_REGEXPS])
- if options[CulebraOptions.FIND_VIEWS_WITH_CONTENT_DESCRIPTION]:
- printFindViewWithContentDescription(view, options[CulebraOptions.USE_REGEXPS])
- if options[CulebraOptions.SAVE_VIEW_SCREENSHOTS]:
- _format = 'PNG'
- filename = options[CulebraOptions.SAVE_VIEW_SCREENSHOTS] + os.sep + view.variableNameFromId() + '.' + _format.lower()
- printSaveViewScreenshot(view, filename, _format)
- def printOperation(view, op, *args):
- if len(args) == 0:
- # We use tuple values in the rest of this method, so if an empty tuple was passed
- # replace it by one containing None
- args = ( None, None )
- elif len(args) < 2:
- # We use tuple values in the rest of this method, so if an empty tuple was passed
- # replace it by one containing None
- args = ( args[0], None )
- if DEBUG:
- print >> sys.stderr, "printOperation(",
- print >> sys.stderr, view.__str__(),
- print >> sys.stderr, ",", op, ",",
- for a in args:
- if isinstance(a, unicode):
- print >> sys.stderr, a.encode(encoding='ascii', errors='replace'), ", ",
- else:
- print >> sys.stderr, a,
- print >> sys.stderr, ")"
- if op == Operation.SLEEP:
- printSleep(secs=args[0])
- return
- elif op == Operation.PRESS:
- printPress(keycode=args[0])
- return
- elif op == Operation.DUMP:
- printDump(window=args[0], dump=args[1])
- return
- elif op == Operation.DRAG:
- printDrag(start=args[0], end=args[1], duration=args[2], steps=args[3], unit=args[4], orientation=args[5])
- return
- elif op == Operation.TOUCH_POINT:
- printTouch(x=args[0], y=args[1], unit=args[2], orientation=args[3])
- return
- elif op == Operation.LONG_TOUCH_POINT:
- printLongTouch(x=args[0], y=args[1], duration=args[2], unit=args[3], orientation=args[4])
- return
- elif op == Operation.TRAVERSE:
- printTraverse()
- return
- elif op == Operation.SNAPSHOT:
- printTakeSnapshot(filename=args[0], _format=args[1], deviceart=args[2], dropshadow=args[3], screenglare=args[4])
- return
- elif op == Operation.VIEW_SNAPSHOT:
- printSaveViewScreenshot(view, filename=args[0], _format=args[1])
- return
- elif op == Operation.FLING_BACKWARD:
- printFlingBackward(view)
- return
- elif op == Operation.FLING_FORWARD:
- printFlingForward(view)
- return
- elif op == Operation.FLING_TO_BEGINNING:
- printFlingToBeginning(view)
- return
- elif op == Operation.FLING_TO_END:
- printFlingToEnd(view)
- return
- elif op == Operation.OPEN_NOTIFICATION:
- printOpenNotification()
- return
- elif op == Operation.OPEN_QUICK_SETTINGS:
- printOpenQuickSettings()
- return
- elif op == Operation.CHANGE_LANGUAGE:
- printChangeLanguage(code=args[0])
- return
-
- if view is None:
- warnings.warn('view is None. Perhaps you forgot to add some "op" in the previous if.')
-
- bd = Descriptor.findBestDescriptor(view)
- if bd == Descriptor.CONTENT_DESCRIPTION:
- printFindViewWithContentDescription(view, options[CulebraOptions.USE_REGEXPS], op, args[0])
- elif bd == Descriptor.TEXT:
- printFindViewWithText(view, options[CulebraOptions.USE_REGEXPS], op, args[0])
- else:
- printFindViewById(view, op, args[0])
-
- def str2bool(v):
- return v.lower() in ("yes", "true", "t", "1", "on")
- def value2dictionaryKey(v):
- v = v.lower()
- k = ['id', 'text', 'content-description']
- sk = ['i', 't', 'd']
- if v in k:
- return v
- if v in sk:
- return k[sk.index(v)]
- error("Invalid dictionary key: %s" % v)
- usage()
- def getShebangJar():
- if options[CulebraOptions.USE_JAR]:
- import java
- osName = java.lang.System.getProperty('os.name')
- if osName == 'Linux':
- return SHEBANG[SB_JAR_LINUX]
- else:
- return SHEBANG[SB_JAR]
- else:
- return SHEBANG[SB_NO_JAR]
- def getWindowOption():
- return options[CulebraOptions.WINDOW] if isinstance(options[CulebraOptions.WINDOW], str) and options[CulebraOptions.WINDOW][0] in '-0123456789' else "'%s'" % options[CulebraOptions.WINDOW]
- def printScriptHeader():
- print '''%s
- # -*- coding: utf-8 -*-
- \'\'\'
- Copyright (C) 2013-2014 Diego Torres Milano
- Created on %s by Culebra v%s
- __ __ __ __
- / \ / \ / \ / \
- ____________________/ __\/ __\/ __\/ __\_____________________________
- ___________________/ /__/ /__/ /__/ /________________________________
- | / \ / \ / \ / \ \___
- |/ \_/ \_/ \_/ \ o \
- \_____/--<
- @author: Diego Torres Milano
- @author: Jennifer E. Swofford (ascii art snake)
- \'\'\'
- import re
- import sys
- import os
- ''' % (getShebangJar(), date.today(), __version__)
- def printUnittestImport():
- print '''
- import unittest
- '''
- def printAppendToSysPath():
- print '''
- try:
- sys.path.append(os.path.join(os.environ['ANDROID_VIEW_CLIENT_HOME'], 'src'))
- except:
- pass
- '''
- def printPrependToSysPath():
- print '''
- try:
- sys.path.insert(0, os.path.join(os.environ['ANDROID_VIEW_CLIENT_HOME'], 'src'))
- except:
- pass
- '''
- def printLogAction(action, priority='D'):
- # FIXME: This works only for CulebraTestCases
- # This relies on shortcut variables already set (i.e. _v)
- if options[CulebraOptions.MULTI_DEVICE]:
- print u'%s[_d.Log.%s(TAG, "%s", _v) for _d in %sallDevices()]' % (indent, priority.lower(), action, prefix)
- else:
- print '%s%sdevice.Log.%s(TAG, "%s", _v)' % (indent, prefix, priority.lower(), action)
-
- def logAction(action):
- if options[CulebraOptions.LOG_ACTIONS]:
- printLogAction(action)
-
- def runCulebron():
- Culebron.checkSupportedSdkVersion(device.getSdkVersion())
- Culebron.checkDependencies()
- culebron = Culebron(vc, printOperation, options[CulebraOptions.SCALE])
- if options[CulebraOptions.DEVICE_ART]:
- culebron.deviceArt = options[CulebraOptions.DEVICE_ART]
- culebron.dropShadow = options[CulebraOptions.DROP_SHADOW]
- culebron.screenGlare = options[CulebraOptions.SCREEN_GLARE]
- culebron.takeScreenshotAndShowItOnWindow()
- culebron.mainloop()
-
- def printShortcutVariables():
- if options[CulebraOptions.UNIT_TEST_CLASS] or options[CulebraOptions.UNIT_TEST_METHOD]:
- print '''\
- _s = CulebraTests.sleep
- _v = CulebraTests.verbose
- '''
- else:
- print '''\
- _s = 5
- _v = '--verbose' in sys.argv
- '''
-
- ################
- # __main__
- ################
- progname = os.path.basename(sys.argv[0])
- try:
- optlist, args = getopt.getopt(sys.argv[1:], CulebraOptions.SHORT_OPTS, CulebraOptions.LONG_OPTS)
- sys.argv[1:] = args
- except getopt.GetoptError, e:
- error(str(e))
- usage()
- kwargs1 = {CulebraOptions.VERBOSE: False, 'ignoresecuredevice': False, 'ignoreversioncheck': False}
- serialno = None
- kwargs2 = {ViewClientOptions.FORCE_VIEW_SERVER_USE: False, ViewClientOptions.START_VIEW_SERVER: True,
- ViewClientOptions.AUTO_DUMP: False, ViewClientOptions.IGNORE_UIAUTOMATOR_KILLED: True,
- ViewClientOptions.COMPRESSED_DUMP: True}
- options = {CulebraOptions.FIND_VIEWS_BY_ID: True, CulebraOptions.FIND_VIEWS_WITH_TEXT: True, CulebraOptions.FIND_VIEWS_WITH_CONTENT_DESCRIPTION: True,
- CulebraOptions.USE_REGEXPS: False, CulebraOptions.VERBOSE_COMMENTS: False,
- CulebraOptions.UNIT_TEST_CLASS: False, CulebraOptions.UNIT_TEST_METHOD: None, CulebraOptions.USE_JAR: False,
- CulebraOptions.USE_DICTIONARY: False, CulebraOptions.DICTIONARY_KEYS_FROM: 'id',
- CulebraOptions.AUTO_REGEXPS: None, CulebraOptions.START_ACTIVITY: None, CulebraOptions.OUTPUT: None, CulebraOptions.INTERACTIVE: False,
- CulebraOptions.WINDOW:-1, CulebraOptions.PREPEND_TO_SYS_PATH: False,
- CulebraOptions.SAVE_SCREENSHOT: None, CulebraOptions.SAVE_VIEW_SCREENSHOTS: None,
- CulebraOptions.GUI: False,
- CulebraOptions.DO_NOT_VERIFY_SCREEN_DUMP: False,
- CulebraOptions.SCALE: 1,
- CulebraOptions.ORIENTATION_LOCKED: None,
- CulebraOptions.MULTI_DEVICE: False,
- CulebraOptions.LOG_ACTIONS: False,
- CulebraOptions.DEVICE_ART: None,
- CulebraOptions.DROP_SHADOW: False,
- CulebraOptions.SCREEN_GLARE: False,
- }
- transform = traverseAndPrint
- for o, a in optlist:
- o = o.strip('-')
- if o in ['H', CulebraOptions.HELP]:
- help()
- elif o in ['V', CulebraOptions.VERBOSE]:
- kwargs1[CulebraOptions.VERBOSE] = True
- elif o in ['v', CulebraOptions.VERSION]:
- version()
- elif o in ['I', CulebraOptions.IGNORE_SECURE_DEVICE]:
- kwargs1['ignoresecuredevice'] = True
- elif o in ['E', CulebraOptions.IGNORE_VERSION_CHECK]:
- kwargs1['ignoreversioncheck'] = True
- elif o in ['F', CulebraOptions.FORCE_VIEW_SERVER_USE]:
- kwargs2['forceviewserveruse'] = True
- elif o in ['S', CulebraOptions.DO_NOT_START_VIEW_SERVER]:
- kwargs2['startviewserver'] = False
- elif o in ['k', CulebraOptions.DO_NOT_IGNORE_UIAUTOMATOR_KILLED]:
- kwargs2['ignoreuiautomatorkilled'] = False
- elif o in ['w', CulebraOptions.WINDOW]:
- options[CulebraOptions.WINDOW] = a
- elif o in ['i', CulebraOptions.FIND_VIEWS_BY_ID]:
- options[CulebraOptions.FIND_VIEWS_BY_ID] = str2bool(a)
- elif o in ['t', CulebraOptions.FIND_VIEWS_WITH_TEXT]:
- options[CulebraOptions.FIND_VIEWS_WITH_TEXT] = str2bool(a)
- elif o in ['d', CulebraOptions.FIND_VIEWS_WITH_CONTENT_DESCRIPTION]:
- options[CulebraOptions.FIND_VIEWS_WITH_CONTENT_DESCRIPTION] = str2bool(a)
- elif o in ['r', CulebraOptions.USE_REGEXPS]:
- options[CulebraOptions.USE_REGEXPS] = True
- elif o in ['C', CulebraOptions.VERBOSE_COMMENTS]:
- options[CulebraOptions.VERBOSE_COMMENTS] = True
- elif o in ['U', CulebraOptions.UNIT_TEST_CLASS]:
- options[CulebraOptions.UNIT_TEST_CLASS] = True
- elif o in ['M', CulebraOptions.UNIT_TEST_METHOD]:
- if not a.startswith('test'):
- warnings.warn('Method name should start with "test"')
- options[CulebraOptions.UNIT_TEST_METHOD] = a
- elif o in ['j', CulebraOptions.USE_JAR]:
- options[CulebraOptions.USE_JAR] = str2bool(a)
- elif o in ['D', CulebraOptions.USE_DICTIONARY]:
- options[CulebraOptions.USE_DICTIONARY] = str2bool(a)
- elif o in ['K', CulebraOptions.DICTIONARY_KEYS_FROM]:
- options[CulebraOptions.DICTIONARY_KEYS_FROM] = value2dictionaryKey(a)
- elif o in ['R', CulebraOptions.AUTO_REGEXPS]:
- options[CulebraOptions.AUTO_REGEXPS] = a.split(',')
- for r in options[CulebraOptions.AUTO_REGEXPS]:
- if r == 'help':
- autoRegexpsHelp()
- if r == 'all':
- options[CulebraOptions.AUTO_REGEXPS] = CulebraOptions.AUTO_REGEXPS_RES.keys()
- break
- if r not in CulebraOptions.AUTO_REGEXPS_RES:
- error("invalid auto regexp: %s\n" % (r))
- usage()
- # CulebraOptions.AUTO_REGEPXS implies CulebraOptions.USE_REGEXPS
- options[CulebraOptions.USE_REGEXPS] = True
- elif o in ['a', CulebraOptions.START_ACTIVITY]:
- options[CulebraOptions.START_ACTIVITY] = a
- elif o in ['o', CulebraOptions.OUTPUT]:
- options[CulebraOptions.OUTPUT] = a
- elif o in ['p', CulebraOptions.PREPEND_TO_SYS_PATH]:
- options[CulebraOptions.PREPEND_TO_SYS_PATH] = True
- elif o in ['f', CulebraOptions.SAVE_SCREENSHOT]:
- options[CulebraOptions.SAVE_SCREENSHOT] = a
- elif o in ['W', CulebraOptions.SAVE_VIEW_SCREENSHOTS]:
- options[CulebraOptions.SAVE_VIEW_SCREENSHOTS] = a
- elif o in ['G', CulebraOptions.GUI]:
- options[CulebraOptions.GUI] = True
- elif o in ['u', CulebraOptions.DO_NOT_VERIFY_SCREEN_DUMP]:
- options[CulebraOptions.DO_NOT_VERIFY_SCREEN_DUMP] = True
- elif o in ['P', CulebraOptions.SCALE]:
- options[CulebraOptions.SCALE] = float(a)
- elif o in ['O', CulebraOptions.ORIENTATION_LOCKED]:
- options[CulebraOptions.ORIENTATION_LOCKED] = 'PENDING'
- elif o in ['s', CulebraOptions.SERIALNO]:
- __devices = a.split()
- if len(__devices) > 1:
- warnings.warn('List of devices not supported yet. Using first device instead.')
- serialno = __devices[0]
- elif o in ['m', CulebraOptions.MULTI_DEVICE]:
- options[CulebraOptions.MULTI_DEVICE] = True
- elif o in ['L', CulebraOptions.LOG_ACTIONS]:
- options[CulebraOptions.LOG_ACTIONS] = True
- elif o in ['A', CulebraOptions.DEVICE_ART]:
- options[CulebraOptions.DEVICE_ART] = a
- elif o in ['Z', CulebraOptions.DROP_SHADOW]:
- options[CulebraOptions.DROP_SHADOW] = True
- elif o in ['B', CulebraOptions.SCREEN_GLARE]:
- options[CulebraOptions.SCREEN_GLARE] = True
- if not (options[CulebraOptions.FIND_VIEWS_BY_ID] or options[CulebraOptions.FIND_VIEWS_WITH_TEXT] or options[CulebraOptions.FIND_VIEWS_WITH_CONTENT_DESCRIPTION]):
- if not options[CulebraOptions.VERBOSE_COMMENTS]:
- warnings.warn('All printing options disabled. Output will be empty.')
- else:
- warnings.warn('Only verbose comments will be printed')
- device, serialno = ViewClient.connectToDeviceOrExit(serialno=serialno, **kwargs1)
- if options[CulebraOptions.ORIENTATION_LOCKED] == 'PENDING':
- options[CulebraOptions.ORIENTATION_LOCKED] = device.display['orientation']
- if options[CulebraOptions.START_ACTIVITY]:
- device.startActivity(component=options[CulebraOptions.START_ACTIVITY])
- vc = ViewClient(device, serialno, **kwargs2)
- if options[CulebraOptions.OUTPUT]:
- sys.stdout = codecs.open(options[CulebraOptions.OUTPUT], mode='w', encoding='utf-8', errors='replace')
- import stat
- st = os.stat(options[CulebraOptions.OUTPUT])
- os.chmod(options[CulebraOptions.OUTPUT], st.st_mode | stat.S_IEXEC)
- if options[CulebraOptions.UNIT_TEST_CLASS] or (not options[CulebraOptions.UNIT_TEST_METHOD]):
- printScriptHeader()
- if options[CulebraOptions.UNIT_TEST_CLASS]:
- printUnittestImport()
- if options[CulebraOptions.PREPEND_TO_SYS_PATH]:
- printPrependToSysPath()
- if options[CulebraOptions.UNIT_TEST_CLASS] or (not options[CulebraOptions.UNIT_TEST_METHOD]):
- print '''\
- from com.dtmilano.android.viewclient import ViewClient%s
- TAG = '%s'
- ''' % (', CulebraTestCase' if options[CulebraOptions.UNIT_TEST_CLASS] else '', TAG)
- if options[CulebraOptions.UNIT_TEST_CLASS]:
- print '''
- class CulebraTests(CulebraTestCase):
- @classmethod
- def setUpClass(cls):
- cls.kwargs1 = %s
- cls.kwargs2 = %s
- cls.options = %s
- cls.sleep = 5
- ''' % (kwargs1, kwargs2, options),
- print '''\
- def setUp(self):
- super(CulebraTests, self).setUp()
- '''
- print '''\
- def tearDown(self):
- super(CulebraTests, self).tearDown()
- '''
- print '''\
- def preconditions(self):
- if not super(CulebraTests, self).preconditions():
- return False
- return True
- def %s(self):
- if not self.preconditions():
- self.fail('Preconditions failed')
- ''' % (options[CulebraOptions.UNIT_TEST_METHOD] if options[CulebraOptions.UNIT_TEST_METHOD] else 'testSomething')
- printShortcutVariables()
-
- if options[CulebraOptions.SAVE_SCREENSHOT]:
- print '''\
- self.vc.writeImageToFile('%s')
- ''' % options[CulebraOptions.SAVE_SCREENSHOT]
-
- if options[CulebraOptions.USE_DICTIONARY]:
- print '''\
- self.views = dict()'''
- vc.dump(window=options[CulebraOptions.WINDOW])
- indent = ' ' * 8
- prefix = 'self.'
-
- # if not options[CulebraOptions.DO_NOT_VERIFY_SCREEN_DUMP]:
- # print '''\
- # self.vc.dump(%s)
- # ''' % getWindowOption()
- # vc.traverse(transform=transform)
- # print
- if options[CulebraOptions.GUI]:
- runCulebron()
- elif not options[CulebraOptions.DO_NOT_VERIFY_SCREEN_DUMP]:
- printDump(getWindowOption())
- print '''
- if __name__ == '__main__':
- CulebraTests.main()
- '''
- else:
- # Not a unittest class, still could be a unittest method as we allow to generate methods separately from their classes
- if not options[CulebraOptions.UNIT_TEST_METHOD]:
- printShortcutVariables()
- print '''
- kwargs1 = %s
- device, serialno = ViewClient.connectToDeviceOrExit(**kwargs1)
- ''' % kwargs1,
- if options[CulebraOptions.START_ACTIVITY] and not options[CulebraOptions.UNIT_TEST_METHOD]:
- print '''\
- device.startActivity(component='%s')''' % options[CulebraOptions.START_ACTIVITY]
- if not options[CulebraOptions.UNIT_TEST_METHOD]:
- print '''\
- kwargs2 = %s
- vc = ViewClient(device, serialno, **kwargs2)
- #vc.dump(window=%s) # FIXME: seems not needed
- ''' % (kwargs2, getWindowOption())
- if options[CulebraOptions.USE_DICTIONARY]:
- print '''views = dict()'''
- if options[CulebraOptions.SAVE_SCREENSHOT]:
- print '''\
- vc.writeImageToFile('%s')
- ''' % options[CulebraOptions.SAVE_SCREENSHOT]
-
- vc.dump(window=options[CulebraOptions.WINDOW])
- if options[CulebraOptions.UNIT_TEST_METHOD]:
- print '''
- def %s(self):
- \'\'\'
- Test method.
- \'\'\'
- if not self.preconditions():
- self.fail('Preconditions failed')
- ''' % (options[CulebraOptions.UNIT_TEST_METHOD])
- indent = ' ' * 8
- prefix = 'self.'
- printShortcutVariables()
-
- if options[CulebraOptions.GUI]:
- runCulebron()
- elif not options[CulebraOptions.DO_NOT_VERIFY_SCREEN_DUMP]:
- printDump(getWindowOption())
-
-
- if options[CulebraOptions.INTERACTIVE]:
- import socket
- HOST = 'localhost'
- PORT = 8900
- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- s.connect((HOST, PORT))
- s.sendall("RECORD EVENTS START\n")
- fin = open("/dev/tty")
- while True:
- print >> sys.stderr, "Reading events..."
- data = s.recv(1024)
- code = ViewClient.excerpt(data)
- exec code
- resp = raw_input("Continue recording events? [Y/n]: ")
- if resp in ['N', 'n']:
- break
- s.sendall("RECORD EVENTS STOP\n")
- s.close()
|