| #!/usr/bin/env python |
| # -*- coding: utf-8 -*- |
| ''' |
| Copyright (C) 2013-2016 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__ = '11.5.9' |
| |
| 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): |
| s = "" |
| for i in range(max(len(short_opts), len(CulebraOptions.LONG_OPTS))): |
| l = '' |
| try: |
| l = short_opts[i] |
| except IndexError: |
| pass |
| L = '' |
| try: |
| L = CulebraOptions.LONG_OPTS[i] |
| except IndexError: |
| pass |
| s += "%3s - %s\n" % (l, L) |
| raise Exception('There is a mismatch between short and long options: short=%d, long=%d\n%s' % |
| (len(short_opts), len(CulebraOptions.LONG_OPTS), s)) |
| 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: |
| logAction(u'finding view with text=%s' % text) |
| print u'%s%s = %svc.findViewWithTextOrRaise(%s)' % (indent, var, prefix, text) |
| elif op == Operation.LONG_TOUCH_VIEW: |
| root = ', root=%svc.findViewByIdOrRaise(\'%s\')' % (prefix, arg.getUniqueId()) if arg else '' |
| if options[CulebraOptions.MULTI_DEVICE]: |
| logAction(u'long touch view with text=%s on ${serialno}' % text) |
| print u'%s[_vc.findViewWithTextOrRaise(%s%s).longTouch() for _vc in %sallVcs()]' % (indent, text, root, prefix) |
| else: |
| logAction(u'long touch view with text=%s' % text) |
| print u'%s%svc.findViewWithTextOrRaise(%s%s).longTouch()' % (indent, prefix, text, root) |
| elif op == Operation.TOUCH_VIEW: |
| root = ', root=%svc.findViewByIdOrRaise(\'%s\')' % (prefix, arg.getUniqueId()) if arg else '' |
| if options[CulebraOptions.MULTI_DEVICE]: |
| logAction(u'touching view with text=%s on ${serialno}' % text) |
| print u'%s[_vc.findViewWithTextOrRaise(%s%s).touch() for _vc in %sallVcs()]' % (indent, text, root, prefix) |
| 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.SET_TEXT: |
| if options[CulebraOptions.MULTI_DEVICE]: |
| warnings.warn('Multi-device not implemented yet for this case') |
| else: |
| print '%s%svc.findViewWithTextOrRaise(%s).setText(u"%s")' % (indent, prefix, text, arg) |
| elif op in [Operation.FLING_BACKWARD, Operation.FLING_FORWARD, Operation.FLING_TO_BEGINNING, Operation.FLING_TO_END]: |
| if options[CulebraOptions.MULTI_DEVICE]: |
| warnings.warn('Multi-device not implemented yet for this case') |
| else: |
| commandName = Operation.toCommandName(op) |
| logAction(u'flinging view with text=%s %s' % (text, commandName)) |
| print u'%s%svc.findViewWithTextOrRaise(%s).uiScrollable.%s()' % (indent, prefix, text, commandName) |
| 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: |
| logAction(u'finding view with content-description=%s' % contentDescription) |
| print '%s%s = %svc.findViewWithContentDescriptionOrRaise(%s)' % (indent, var, prefix, contentDescription) |
| elif op == Operation.LONG_TOUCH_VIEW: |
| if options[CulebraOptions.MULTI_DEVICE]: |
| logAction(u'long touch view with content-description=%s on ${serialno}' % contentDescription) |
| # print u'%s[_vc.findViewWithTextOrRaise(%s).touch() for _vc in %sallVcs()]' % (indent, text, root) |
| print u'%s[_vc.findViewWithContentDescriptionOrRaise(%s).longTouch() for _vc in %sallVcs()]' % (indent, contentDescription, prefix) |
| else: |
| logAction(u'long touch view with content-description=%s' % contentDescription) |
| print u'%s%svc.findViewWithContentDescriptionOrRaise(%s).longTouch()' % (indent, prefix, contentDescription) |
| elif op == Operation.TOUCH_VIEW: |
| if options[CulebraOptions.MULTI_DEVICE]: |
| logAction(u'touching view with content-description=%s on ${serialno}' % contentDescription) |
| # print u'%s[_vc.findViewWithTextOrRaise(%s).touch() for _vc in %sallVcs()]' % (indent, text, root) |
| print u'%s[_vc.findViewWithContentDescriptionOrRaise(%s).touch() for _vc in %sallVcs()]' % (indent, contentDescription, prefix) |
| else: |
| logAction(u'touching view with content-description=%s' % contentDescription) |
| print u'%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.SET_TEXT: |
| if options[CulebraOptions.MULTI_DEVICE]: |
| warnings.warn('Multi-device not implemented yet for this case') |
| else: |
| print '%s%svc.findViewWithContentDescriptionOrRaise(%s).setText(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) |
| elif op in [Operation.FLING_BACKWARD, Operation.FLING_FORWARD, Operation.FLING_TO_BEGINNING, Operation.FLING_TO_END]: |
| if options[CulebraOptions.MULTI_DEVICE]: |
| warnings.warn('Multi-device not implemented yet for this case') |
| else: |
| commandName = Operation.toCommandName(op) |
| logAction(u'flinging view with content-description=%s %s' % (contentDescription, commandName)) |
| print u'%s%svc.findViewWithContentDescriptionOrRaise(%s).uiScrollable.%s()' % (indent, prefix, contentDescription, commandName) |
| 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.LONG_TOUCH_VIEW: |
| if options[CulebraOptions.MULTI_DEVICE]: |
| logAction(u'long touch view with id=%s on ${serialno}' % _id) |
| print '%s[_vc.findViewByIdOrRaise("%s").longTouch() for _vc in %sallVcs()]' % (indent, _id, prefix) |
| else: |
| logAction(u'long touch view with id=%s' % _id) |
| print '%s%svc.findViewByIdOrRaise("%s").longTouch()' % (indent, 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=%s' % (arg, _id)) |
| print '%s%svc.findViewByIdOrRaise("%s").type(u"%s")' % (indent, prefix, _id, arg) |
| elif op == Operation.SET_TEXT: |
| if options[CulebraOptions.MULTI_DEVICE]: |
| warnings.warn('Multi-device not implemented yet for this case') |
| else: |
| logAction('setting text "%s" on view with id=%s' % (arg, _id)) |
| print '%s%svc.findViewByIdOrRaise("%s").setText(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) |
| elif op in [Operation.FLING_BACKWARD, Operation.FLING_FORWARD, Operation.FLING_TO_BEGINNING, Operation.FLING_TO_END]: |
| if options[CulebraOptions.MULTI_DEVICE]: |
| warnings.warn('Multi-device not implemented yet for this case') |
| else: |
| commandName = Operation.toCommandName(op) |
| logAction(u'flinging view with id=%s %s' % (_id, commandName)) |
| print u'%s%svc.findViewWithIdOrRaise(u"%s").uiScrollable.%s()' % (indent, prefix, _id, commandName) |
| 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 printWake(): |
| ''' |
| Prints a wake. |
| |
| :return: |
| ''' |
| |
| if options[CulebraOptions.MULTI_DEVICE]: |
| print '%s[_vc.device.wake() for _vc in %sallVcs()]' % (indent, prefix) |
| else: |
| print '%s%svc.device.wake()' % (indent, prefix) |
| |
| 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 printStartActivity(component): |
| ''' |
| Prints the corresponding startActivity(). |
| |
| :param component: the component |
| ''' |
| |
| if options[CulebraOptions.MULTI_DEVICE]: |
| warnings.warn('Multi-device not implemented yet for this case') |
| else: |
| logAction(u'starting activity=%s' % (component)) |
| print '%s%sdevice.startActivity(\'%s\')' % (indent, prefix, component) |
| printSleep(3) |
| |
| |
| def printTouchViewUiAutomatorHelper(view, selector): |
| ''' |
| Prints the corresponding touch |
| ''' |
| if options[CulebraOptions.MULTI_DEVICE]: |
| warnings.warn('Multi-device not implemented yet for this case') |
| else: |
| logAction(u'touching View by selector=%s' % (selector)) |
| print '%s%svc.touch(selector=\'%s\')' % (indent, prefix, selector) |
| |
| |
| def printLongTouchViewUiAutomatorHelper(view, selector): |
| ''' |
| Prints the corresponding long touch |
| ''' |
| if options[CulebraOptions.MULTI_DEVICE]: |
| warnings.warn('Multi-device not implemented yet for this case') |
| else: |
| logAction(u'long-touching View by selector=%s' % (selector)) |
| print '%s%svc.longTouch(selector=\'%s\')' % (indent, prefix, selector) |
| |
| |
| def printSwipeUiAutomatorHelper(startX, startY, endX, endY, steps, unit, orientation): |
| ''' |
| Prints a swipe |
| ''' |
| |
| if unit == Unit.PX: |
| if options[CulebraOptions.MULTI_DEVICE]: |
| warnings.warn('Multi-device not implemented yet for this case') |
| else: |
| print '%s%svc.swipe(startX=%d, startY=%d, endX=%d, endY=%d, steps=%d)' % (indent, prefix, startX, startY, endX, endY, steps) |
| elif unit == Unit.DIP: |
| if options[CulebraOptions.MULTI_DEVICE]: |
| warnings.warn('Multi-device not implemented yet for this case') |
| else: |
| print '%s%svc.swipe(startX=%d, startY=%d, endX=%d, endY=%d, steps=%d)' % (indent, prefix, startX, startY, endX, endY, steps) |
| else: |
| raise RuntimeError('Invalid unit: %s' % unit) |
| |
| |
| def printPressBackUiAutomatorHelper(): |
| ''' |
| Prints the corresponding press |
| ''' |
| if options[CulebraOptions.MULTI_DEVICE]: |
| warnings.warn('Multi-device not implemented yet for this case') |
| else: |
| logAction(u'pressing BACK') |
| print '%s%svc.pressBack()' % (indent, prefix) |
| |
| def printPressHomeUiAutomatorHelper(): |
| ''' |
| Prints the corresponding press |
| ''' |
| if options[CulebraOptions.MULTI_DEVICE]: |
| warnings.warn('Multi-device not implemented yet for this case') |
| else: |
| logAction(u'pressing HOME') |
| print '%s%svc.pressHome()' % (indent, prefix) |
| |
| def printPressRecentAppsUiAutomatorHelper(): |
| ''' |
| Prints the corresponding press |
| ''' |
| if options[CulebraOptions.MULTI_DEVICE]: |
| warnings.warn('Multi-device not implemented yet for this case') |
| else: |
| logAction(u'pressing RECENT APPS') |
| print '%s%svc.pressRecentApps()' % (indent, prefix) |
| |
| |
| 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.PRESS_BACK: |
| printPress('BACK') |
| return |
| elif op == Operation.PRESS_BACK_UI_AUTOMATOR_HELPER: |
| printPressBackUiAutomatorHelper() |
| return |
| elif op == Operation.PRESS_HOME: |
| printPress('HOME') |
| return |
| elif op == Operation.PRESS_HOME_UI_AUTOMATOR_HELPER: |
| printPressHomeUiAutomatorHelper() |
| return |
| elif op == Operation.PRESS_RECENT_APPS: |
| printPress('RECENT_APPS') |
| return |
| elif op == Operation.PRESS_RECENT_APPS_UI_AUTOMATOR_HELPER: |
| printPressRecentAppsUiAutomatorHelper() |
| 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.TOUCH_VIEW_UI_AUTOMATOR_HELPER: |
| printTouchViewUiAutomatorHelper(view=view, selector=args[0]) |
| 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.LONG_TOUCH_VIEW_UI_AUTOMATOR_HELPER: |
| printLongTouchViewUiAutomatorHelper(view=view, selector=args[0]) |
| 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.SWIPE_UI_AUTOMATOR_HELPER: |
| printSwipeUiAutomatorHelper(startX=args[0], startY=args[1], endX=args[2], endY=args[3], steps=args[4], unit=args[5], orientation=args[6]) |
| return |
| elif op == Operation.VIEW_SNAPSHOT: |
| printSaveViewScreenshot(view, filename=args[0], _format=args[1]) |
| return |
| # FIXME: I moved this to printFindViewWithContentDescription(..,op.,,) to solve the problem of variable not defined when |
| # the script is invoked with -u |
| # 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 |
| elif op == Operation.START_ACTIVITY: |
| printStartActivity(component=args[0]) |
| return |
| elif op == Operation.WAKE: |
| printWake() |
| 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): |
| if len(v) < 1 or len(v) > 5: |
| # len('false')=5 |
| warnings.warn("str2bool: strange value for conversion '%s' will be considered 'false'" % 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-2016 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, device, serialno, printOperation, options[CulebraOptions.SCALE], options[CulebraOptions.CONCERTINA]) |
| 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, |
| ViewClientOptions.USE_UIAUTOMATOR_HELPER: False, |
| } |
| 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, |
| CulebraOptions.NULL_BACK_END: False, |
| CulebraOptions.CONCERTINA: False, |
| CulebraOptions.INSTALL_APK: None, |
| } |
| 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[ViewClientOptions.FORCE_VIEW_SERVER_USE] = True |
| elif o in ['S', CulebraOptions.DO_NOT_START_VIEW_SERVER]: |
| kwargs2[ViewClientOptions.START_VIEW_SERVER] = False |
| elif o in ['k', CulebraOptions.DO_NOT_IGNORE_UIAUTOMATOR_KILLED]: |
| kwargs2[ViewClientOptions.IGNORE_UIAUTOMATOR_KILLED] = 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 |
| elif o in ['0', CulebraOptions.NULL_BACK_END]: |
| options[CulebraOptions.NULL_BACK_END] = True |
| elif o in ['h', CulebraOptions.USE_UIAUTOMATOR_HELPER]: |
| kwargs2[ViewClientOptions.USE_UIAUTOMATOR_HELPER] = True |
| elif o in ['c', CulebraOptions.CONCERTINA]: |
| options[CulebraOptions.CONCERTINA] = True |
| elif o in ['1', CulebraOptions.INSTALL_APK]: |
| options[CulebraOptions.INSTALL_APK] = a |
| |
| 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') |
| |
| if kwargs2[ViewClientOptions.FORCE_VIEW_SERVER_USE] and options[CulebraOptions.NULL_BACK_END]: |
| warnings.warn(ViewClientOptions.FORCE_VIEW_SERVER_USE + " and " + CulebraOptions.NULL_BACK_END + " cannot be specified at the same time.") |
| |
| if options[CulebraOptions.MULTI_DEVICE] and not options[CulebraOptions.UNIT_TEST_CLASS]: |
| error("--" + CulebraOptions.MULTI_DEVICE + " only supported for unit tests (please specify --" + CulebraOptions.UNIT_TEST_CLASS + ")", fatal=True) |
| |
| 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]) |
| if not options[CulebraOptions.NULL_BACK_END]: |
| vc = ViewClient(device, serialno, **kwargs2) |
| else: |
| vc = None |
| 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 |
| ''', |
| |
| if options[CulebraOptions.INSTALL_APK]: |
| print '''\ |
| if self.vc.installPackage(\"%s\") != 0: |
| return False |
| ''' % (options[CulebraOptions.INSTALL_APK]), |
| |
| print '''\ |
| 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()''' |
| |
| if not options[CulebraOptions.GUI]: |
| 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()) |
| else: |
| print '''\ |
| ## your test code here ## |
| ''' |
| |
| 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] |
| |
| if vc: |
| 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 kwargs2[ViewClientOptions.USE_UIAUTOMATOR_HELPER]: |
| try: |
| vc.uiAutomatorHelper.quit() |
| except: |
| pass |
| |
| 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() |
| |