blob: 7aedb000057dd7c1bea41c91f0723f09488b2994 [file] [log] [blame]
#!/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()