culebra 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072
  1. #!C:\tools\Python27\python.exe
  2. # -*- coding: utf-8 -*-
  3. '''
  4. Copyright (C) 2013-2015 Diego Torres Milano
  5. Created on Mar 28, 2013
  6. Culebra helps you create AndroidViewClient scripts generating a working template that can be
  7. modified to suit more specific needs.
  8. __ __ __ __
  9. / \ / \ / \ / \
  10. ____________________/ __\/ __\/ __\/ __\_____________________________
  11. ___________________/ /__/ /__/ /__/ /________________________________
  12. | / \ / \ / \ / \ \___
  13. |/ \_/ \_/ \_/ \ o \
  14. \_____/--<
  15. @author: Diego Torres Milano
  16. @author: Jennifer E. Swofford (ascii art snake)
  17. '''
  18. __version__ = '10.3.0'
  19. import re
  20. import sys
  21. import os
  22. import getopt
  23. import warnings
  24. import subprocess
  25. import codecs
  26. import calendar
  27. from datetime import date
  28. try:
  29. sys.path.insert(0, os.path.join(os.environ['ANDROID_VIEW_CLIENT_HOME'], 'src'))
  30. except:
  31. pass
  32. from com.dtmilano.android.viewclient import ViewClient, ViewClientOptions, View, CulebraOptions
  33. from com.dtmilano.android.culebron import Culebron, Operation, Unit
  34. DEBUG = False
  35. USAGE = 'usage: %s [OPTION]... [serialno]'
  36. TAG = 'CULEBRA'
  37. class Descriptor:
  38. CONTENT_DESCRIPTION = 'content-description'
  39. TEXT = 'text'
  40. ID = 'id'
  41. @staticmethod
  42. def findBestDescriptor(view):
  43. '''
  44. Finds the best possible descriptor for the View
  45. '''
  46. cd = view.getContentDescription()
  47. if cd and options[CulebraOptions.FIND_VIEWS_WITH_CONTENT_DESCRIPTION]:
  48. return Descriptor.CONTENT_DESCRIPTION
  49. else:
  50. t = view.getText()
  51. if t and options[CulebraOptions.FIND_VIEWS_WITH_TEXT]:
  52. return Descriptor.TEXT
  53. return Descriptor.ID
  54. def fillAutoRegexpsRes():
  55. are = {}
  56. are['clock'] = re.compile('[012]?\d:[0-5]\d')
  57. d = "("
  58. for i in range(7):
  59. d += calendar.day_abbr[i]
  60. if i != 6:
  61. d += '|'
  62. d += '), ('
  63. for i in range(1, 13):
  64. d += calendar.month_name[i]
  65. if i != 12:
  66. d += '|'
  67. d += ') [0123]\d'
  68. are['date'] = re.compile(d, re.IGNORECASE)
  69. are['battery'] = re.compile('Charging, \d\d%')
  70. return are
  71. CulebraOptions.AUTO_REGEXPS_RES = fillAutoRegexpsRes()
  72. SB_NO_JAR = 'no-jar'
  73. SB_JAR = 'jar'
  74. SB_JAR_LINUX = 'jar-linux'
  75. SHEBANG = {
  76. SB_NO_JAR: '#! /usr/bin/env python',
  77. SB_JAR: '#! /usr/bin/env shebang monkeyrunner -plugin $ANDROID_VIEW_CLIENT_HOME/bin/androidviewclient-$ANDROID_VIEW_CLIENT_VERSION.jar @!',
  78. SB_JAR_LINUX: '#! /usr/local/bin/shebang monkeyrunner -plugin $AVC_HOME/bin/androidviewclient-$AVC_VERSION.jar @!'
  79. }
  80. indent = ''
  81. prefix = ''
  82. def shortAndLongOptions():
  83. '''
  84. @return: the list of corresponding (short-option, long-option) tuples
  85. '''
  86. short_opts = CulebraOptions.SHORT_OPTS.replace(':', '')
  87. if len(short_opts) != len(CulebraOptions.LONG_OPTS):
  88. raise Exception('There is a mismatch between short and long options')
  89. t = tuple(short_opts) + tuple(CulebraOptions.LONG_OPTS)
  90. l2 = len(t) / 2
  91. sl = []
  92. for i in range(l2):
  93. sl.append((t[i], t[i + l2]))
  94. return sl
  95. def usage(exitVal=1):
  96. print >> sys.stderr, USAGE % progname
  97. print >> sys.stderr, "Try '%s --help' for more information." % progname
  98. sys.exit(exitVal)
  99. def help():
  100. print >> sys.stderr, USAGE % progname
  101. print >> sys.stderr
  102. print >> sys.stderr, "Options:"
  103. for so, lo in shortAndLongOptions():
  104. o = ' -%c, --%s' % (so, lo)
  105. if lo[-1] == '=':
  106. o += CulebraOptions.LONG_OPTS_ARG[lo[:-1]]
  107. try:
  108. o = '%-34s %-45s' % (o, CulebraOptions.OPTS_HELP[so])
  109. except:
  110. pass
  111. print >> sys.stderr, o
  112. sys.exit(0)
  113. def version():
  114. print progname, __version__
  115. sys.exit(0)
  116. def autoRegexpsHelp():
  117. print >> sys.stderr, "Available %s options:" % CulebraOptions.AUTO_REGEXPS
  118. print >> sys.stderr, "\thelp: prints this help"
  119. print >> sys.stderr, "\tall: includes all the available regexps"
  120. for r in CulebraOptions.AUTO_REGEXPS_RES:
  121. print >> sys.stderr, "\t%s: %s" % (r, CulebraOptions.AUTO_REGEXPS_RES[r].pattern)
  122. print >> sys.stderr
  123. sys.exit(0)
  124. def error(msg, fatal=False):
  125. print >> sys.stderr, "%s: ERROR: %s" % (progname, msg)
  126. if fatal:
  127. sys.exit(1)
  128. def notNull(val, default):
  129. if val:
  130. return val
  131. return default
  132. def printVerboseComments(view):
  133. '''
  134. Prints the verbose comments for view.
  135. '''
  136. print '\n%s# class=%s' % (indent, view.getClass()),
  137. try:
  138. text = view.getText()
  139. if text:
  140. u = 'u' if isinstance(text, unicode) else ''
  141. if '\n' in text:
  142. text = re.sub(r'\n(.)', r'\n#\1', text)
  143. print " text=%c'%s'" % (u, text),
  144. except:
  145. pass
  146. try:
  147. contentDescription = view.getContentDescription()
  148. if contentDescription:
  149. print u" cd='%s'" % contentDescription,
  150. except:
  151. pass
  152. try:
  153. tag = view.getTag()
  154. if tag and tag != 'null':
  155. print ' tag=%s' % tag,
  156. except:
  157. pass
  158. print
  159. def variableNameFromIdOrKey(view):
  160. '''
  161. Returns a suitable variable name from the id.
  162. @type view: L{View}
  163. @param id: the View from where the I{uniqueId} is obtained
  164. @return: the variable name from the id
  165. '''
  166. var = view.variableNameFromId()
  167. if options[CulebraOptions.USE_DICTIONARY]:
  168. return '%sviews[\'%s\']' % (prefix, notNull(dictionaryKeyFrom(options[CulebraOptions.DICTIONARY_KEYS_FROM], view), var))
  169. else:
  170. return var
  171. def dictionaryKeyFrom(key, view):
  172. if key == 'id':
  173. return view.getUniqueId()
  174. elif key == 'text':
  175. return view.getText()
  176. elif key == 'content-description':
  177. return view.getContentDescription()
  178. else:
  179. raise Exception('Not a valid dictionary key: %s' % key)
  180. def escapeRegexpSpecialChars(text):
  181. return re.escape(text)
  182. def printFindViewWithText(view, useregexp, op=Operation.ASSIGN, arg=None):
  183. '''
  184. Prints the corresponding statement.
  185. @type view: L{View}
  186. @param view: the View
  187. '''
  188. text = view.getText()
  189. isUnicode = isinstance(text, unicode)
  190. if isUnicode and sys.stdout.encoding is None:
  191. warnings.warn('''\
  192. You are trying to print unicode characters to an unencoded stdout, it will probably fail.
  193. You have to set PYTHONIOENCODING environment variable. For example:
  194. export PYTHONIOENCODING=utf-8
  195. ''')
  196. u = 'u' if isUnicode else ''
  197. if text:
  198. var = variableNameFromIdOrKey(view)
  199. if text.find(u"\n") > 0 or text.find(u"'") > 0:
  200. # 2 quotes + 1 quote = 3 quotes
  201. text = "''%s''" % text
  202. if useregexp:
  203. # if there are special chars already in the text escape them
  204. text = escapeRegexpSpecialChars(text)
  205. if options[CulebraOptions.AUTO_REGEXPS]:
  206. for r in options[CulebraOptions.AUTO_REGEXPS]:
  207. autoRegexp = CulebraOptions.AUTO_REGEXPS_RES[r]
  208. if autoRegexp.match(text):
  209. text = autoRegexp.pattern
  210. break
  211. text = "re.compile(%s'%s')" % (u, text)
  212. else:
  213. text = "%s'%s'" % (u, text)
  214. if op == Operation.ASSIGN:
  215. if options[CulebraOptions.MULTI_DEVICE]:
  216. warnings.warn('Multi-device not implemented yet for this case')
  217. else:
  218. print u'%s%s = %svc.findViewWithTextOrRaise(%s)' % (indent, var, prefix, text)
  219. elif op == Operation.TOUCH_VIEW:
  220. root = ', root=%svc.findViewByIdOrRaise(\'%s\')' % (prefix, arg.getUniqueId()) if arg else ''
  221. if options[CulebraOptions.MULTI_DEVICE]:
  222. print u'%s[_vc.findViewWithTextOrRaise(%s%s).touch() for _vc in %sallVcs()]' % (indent, text, prefix, root)
  223. else:
  224. logAction(u'touching view with text=%s' % text)
  225. print u'%s%svc.findViewWithTextOrRaise(%s%s).touch()' % (indent, prefix, text, root)
  226. elif op == Operation.TYPE:
  227. if options[CulebraOptions.MULTI_DEVICE]:
  228. warnings.warn('Multi-device not implemented yet for this case')
  229. else:
  230. print '%s%svc.findViewWithTextOrRaise("%s").type(u"%s")' % (indent, prefix, text, arg)
  231. elif op == Operation.TEST:
  232. if options[CulebraOptions.MULTI_DEVICE]:
  233. warnings.warn('Multi-device not implemented yet for this case')
  234. else:
  235. print '%s%sassertIsNotNone(%svc.findViewWithText(%s))' % (indent, prefix, prefix, text)
  236. elif kwargs1[CulebraOptions.VERBOSE]:
  237. warnings.warn('View with id=%s has no text' % view.getUniqueId())
  238. def printFindViewWithContentDescription(view, useregexp, op=Operation.ASSIGN, arg=None):
  239. '''
  240. Prints the corresponding statement.
  241. @type view: L{View}
  242. @param view: the View
  243. '''
  244. contentDescription = view.getContentDescription()
  245. if contentDescription:
  246. var = variableNameFromIdOrKey(view)
  247. if useregexp:
  248. if options[CulebraOptions.AUTO_REGEXPS]:
  249. for r in options[CulebraOptions.AUTO_REGEXPS]:
  250. autoRegexp = CulebraOptions.AUTO_REGEXPS_RES[r]
  251. if autoRegexp.match(contentDescription):
  252. contentDescription = autoRegexp.pattern
  253. break
  254. contentDescription = "re.compile(u'''%s''')" % contentDescription
  255. else:
  256. contentDescription = "u'''%s'''" % contentDescription
  257. if op == Operation.ASSIGN:
  258. if options[CulebraOptions.MULTI_DEVICE]:
  259. warnings.warn('Multi-device not implemented yet for this case')
  260. else:
  261. print '%s%s = %svc.findViewWithContentDescriptionOrRaise(%s)' % (indent, var, prefix, contentDescription)
  262. elif op == Operation.TOUCH_VIEW:
  263. if options[CulebraOptions.MULTI_DEVICE]:
  264. warnings.warn('Multi-device not implemented yet for this case')
  265. else:
  266. logAction(u'touching view with content-description=%s' % contentDescription)
  267. print '%s%svc.findViewWithContentDescriptionOrRaise(%s).touch()' % (indent, prefix, contentDescription)
  268. elif op == Operation.TYPE:
  269. if options[CulebraOptions.MULTI_DEVICE]:
  270. warnings.warn('Multi-device not implemented yet for this case')
  271. else:
  272. print '%s%svc.findViewWithContentDescriptionOrRaise(%s).type(u"%s")' % (indent, prefix, contentDescription, arg)
  273. elif op == Operation.TEST:
  274. if options[CulebraOptions.MULTI_DEVICE]:
  275. warnings.warn('Multi-device not implemented yet for this case')
  276. else:
  277. print '%s%sassertEquals(%svc.findViewWithContentDescriptionOrRaise(%s).getText(), u\'\'\'%s\'\'\')' % (indent, prefix, prefix, contentDescription, arg)
  278. else:
  279. error("Invalid operation in %s: %s" % (sys._getframe().f_code.co_name), op)
  280. elif kwargs1[CulebraOptions.VERBOSE]:
  281. warnings.warn('View with id=%s has no content-description' % view.getUniqueId())
  282. def printFindViewById(view, op=Operation.ASSIGN, arg=None):
  283. '''
  284. Prints the corresponding statement.
  285. @type view: L{View}
  286. @param view: the View
  287. '''
  288. var = variableNameFromIdOrKey(view)
  289. _id = view.getId() if view.getId() else view.getUniqueId()
  290. if op == Operation.ASSIGN:
  291. if options[CulebraOptions.MULTI_DEVICE]:
  292. logAction('finding view with id=%s on ${serialno}' % _id)
  293. print '%s%s = [_vc.findViewByIdOrRaise("%s") for _vc in %sallVcs()]' % (indent, var, _id, prefix)
  294. else:
  295. logAction('finding view with id=%s' % _id)
  296. print '%s%s = %svc.findViewByIdOrRaise("%s")' % (indent, var, prefix, _id)
  297. elif op == Operation.TOUCH_VIEW:
  298. if options[CulebraOptions.MULTI_DEVICE]:
  299. logAction(u'touching view with id=%s on ${serialno}' % _id)
  300. print '%s[_vc.findViewByIdOrRaise("%s").touch() for _vc in %sallVcs()]' % (indent, _id, prefix)
  301. else:
  302. logAction(u'touching view with id=%s' % _id)
  303. print '%s%svc.findViewByIdOrRaise("%s").touch()' % (indent, prefix, _id)
  304. elif op == Operation.TYPE:
  305. if options[CulebraOptions.MULTI_DEVICE]:
  306. warnings.warn('Multi-device not implemented yet for this case')
  307. else:
  308. logAction('typing "%s" on view with id=' % (arg, _id))
  309. print '%s%svc.findViewByIdOrRaise("%s").type(u"%s")' % (indent, prefix, _id, arg)
  310. elif op == Operation.TEST:
  311. if options[CulebraOptions.MULTI_DEVICE]:
  312. warnings.warn('Multi-device not implemented yet for this case')
  313. else:
  314. print '%s%sassertEquals(%svc.findViewByIdOrRaise("%s").getText(), u\'\'\'%s\'\'\')' % (indent, prefix, prefix, _id, arg)
  315. else:
  316. error("Invalid operation in %s: %s" % (sys._getframe().f_code.co_name, op))
  317. def printTraverse(dump=None):
  318. '''
  319. Prints the result of traversing the tree.
  320. A previously obtained dump can be passed as a parameter and in such case that
  321. tree is used.
  322. @param dump: Dump of Views previously obtained via L{ViewClient.dump()}
  323. @type dump: list
  324. '''
  325. print
  326. if dump:
  327. for view in dump:
  328. transform(view)
  329. else:
  330. vc.traverse(transform=transform)
  331. print
  332. def printDump(window, dump=None):
  333. '''
  334. Prints a dump.
  335. @param window: The window id to use to print the dump
  336. @type window: int or str
  337. @param dump: Dump of Views previously obtained via L{ViewClient.dump()}
  338. @type dump: list
  339. '''
  340. if options[CulebraOptions.MULTI_DEVICE]:
  341. logAction('dumping content of window=%s on ${serialno}' % window)
  342. print '%s[_vc.dump(window=%s) for _vc in %sallVcs()]' % (indent, window, prefix)
  343. else:
  344. logAction('dumping content of window=%s' % window)
  345. print '%s%svc.dump(window=%s)' % (indent, prefix, window)
  346. if not options[CulebraOptions.DO_NOT_VERIFY_SCREEN_DUMP]:
  347. printTraverse(dump)
  348. def printSleep(secs):
  349. '''
  350. Prints a sleep.
  351. This method relies on shortcut variables being set (i.e. _s)
  352. '''
  353. if options[CulebraOptions.MULTI_DEVICE]:
  354. print '%s[_vc.sleep(%s) for _vc in %sallVcs()]' % (indent, secs if secs != Operation.DEFAULT else '_s', prefix)
  355. else:
  356. print '%s%svc.sleep(%s)' % (indent, prefix, secs if secs != Operation.DEFAULT else '_s')
  357. def printPress(keycode):
  358. '''
  359. Prints a key press
  360. '''
  361. if options[CulebraOptions.MULTI_DEVICE]:
  362. logAction(u'pressing key=%s on ${serialno}' % keycode)
  363. print '%s[_d.press(\'%s\') for _d in %sallDevices()]' % (indent, keycode, prefix)
  364. else:
  365. logAction(u'pressing key=%s' % keycode)
  366. print '%s%sdevice.press(\'%s\')' % (indent, prefix, keycode)
  367. def printDrag(start, end, duration, steps, unit, orientation):
  368. '''
  369. Prints a drag
  370. '''
  371. if unit == Unit.PX:
  372. if options[CulebraOptions.MULTI_DEVICE]:
  373. warnings.warn('Multi-device not implemented yet for this case')
  374. else:
  375. print '%s%sdevice.drag(%s, %s, %d, %d, %d)' % (indent, prefix, start, end, duration, steps, orientation)
  376. elif unit == Unit.DIP:
  377. if options[CulebraOptions.MULTI_DEVICE]:
  378. warnings.warn('Multi-device not implemented yet for this case')
  379. else:
  380. print '%s%sdevice.dragDip(%s, %s, %d, %d, %d)' % (indent, prefix, start, end, duration, steps, orientation)
  381. else:
  382. raise RuntimeError('Invalid unit: %s' % unit)
  383. def printTouch(x, y, unit, orientation):
  384. '''
  385. Prints a touch
  386. '''
  387. if unit == Unit.PX:
  388. if options[CulebraOptions.MULTI_DEVICE]:
  389. warnings.warn('Multi-device not implemented yet for this case')
  390. else:
  391. logAction(u'touching point by PX @ (%s, %s) orientation=%s' % (x, y, orientation))
  392. print '%s%sdevice.touch(%s, %s, %s)' % (indent, prefix, x, y, orientation)
  393. elif unit == Unit.DIP:
  394. if options[CulebraOptions.MULTI_DEVICE]:
  395. warnings.warn('Multi-device not implemented yet for this case')
  396. else:
  397. logAction(u'touching point by DIP @ (%s, %s) orientation=%s' % (x, y, orientation))
  398. print '%s%sdevice.touchDip(%s, %s, %s)' % (indent, prefix, x, y, orientation)
  399. else:
  400. raise RuntimeError('Invalid unit: %s' % unit)
  401. def printLongTouch(x, y, duration, unit, orientation):
  402. '''
  403. Prints a long touch
  404. '''
  405. if unit == Unit.PX:
  406. if options[CulebraOptions.MULTI_DEVICE]:
  407. warnings.warn('Multi-device not implemented yet for this case')
  408. else:
  409. logAction(u'long touching point by PX @ (%s, %s) duration=%s orientation=%s' % (x, y, duration, orientation))
  410. print '%s%sdevice.longTouch(%s, %s, %s, %s)' % (indent, prefix, x, y, duration, orientation)
  411. elif unit == Unit.DIP:
  412. if options[CulebraOptions.MULTI_DEVICE]:
  413. warnings.warn('Multi-device not implemented yet for this case')
  414. else:
  415. logAction(u'long touching point by DIP @ (%s, %s) duration=%s orientation=%s' % (x, y, duration, orientation))
  416. print '%s%sdevice.longTouch(%s, %s, %s, %s)' % (indent, prefix, x, y, duration, orientation)
  417. else:
  418. raise RuntimeError('Invalid unit: %s' % unit)
  419. def printSaveViewScreenshot(view, filename, _format):
  420. '''
  421. Prints the writeImageToFile for the specified L{View}.
  422. @type view: L{View}
  423. @param view: the View
  424. @type filename: str
  425. @param filename: the filename to store the image
  426. @type _format: str
  427. @param _format: The image format (i.e. PNG)
  428. '''
  429. if options[CulebraOptions.MULTI_DEVICE]:
  430. warnings.warn('Multi-device not implemented yet for this case')
  431. else:
  432. # FIXME: if -u was passed in the command line then we are not saving the variables and thus
  433. # next line will generate an error in the script as the variable is 'undefined'
  434. print '%s%s.writeImageToFile(\'%s\', \'%s\')' % (indent, view.variableNameFromId(), filename, _format)
  435. def printFlingBackward(view):
  436. if options[CulebraOptions.MULTI_DEVICE]:
  437. warnings.warn('Multi-device not implemented yet for this case')
  438. else:
  439. # FIXME: if -u was passed in the command line then we are not saving the variables and thus
  440. # next line will generate an error in the script as the variable is 'undefined'
  441. logAction('flinging backward view with id=%s' % view.getId())
  442. print '%s%s.uiScrollable.flingBackward()' % (indent, view.variableNameFromId())
  443. def printFlingForward(view):
  444. if options[CulebraOptions.MULTI_DEVICE]:
  445. warnings.warn('Multi-device not implemented yet for this case')
  446. else:
  447. # FIXME: if -u was passed in the command line then we are not saving the variables and thus
  448. # next line will generate an error in the script as the variable is 'undefined'
  449. logAction('flinging forward view with id=%s' % view.getId())
  450. print '%s%s.uiScrollable.flingForward()' % (indent, view.variableNameFromId())
  451. def printFlingToBeginning(view):
  452. if options[CulebraOptions.MULTI_DEVICE]:
  453. warnings.warn('Multi-device not implemented yet for this case')
  454. else:
  455. # FIXME: if -u was passed in the command line then we are not saving the variables and thus
  456. # next line will generate an error in the script as the variable is 'undefined'
  457. logAction('flinging to beginning view with id=%s' % view.getId())
  458. print '%s%s.uiScrollable.flingToBeginning()' % (indent, view.variableNameFromId())
  459. def printFlingToEnd(view):
  460. if options[CulebraOptions.MULTI_DEVICE]:
  461. warnings.warn('Multi-device not implemented yet for this case')
  462. else:
  463. # FIXME: if -u was passed in the command line then we are not saving the variables and thus
  464. # next line will generate an error in the script as the variable is 'undefined'
  465. logAction('flinging to end view with id=%s' % view.getId())
  466. print '%s%s.uiScrollable.flingToEnd()' % (indent, view.variableNameFromId())
  467. def printOpenNotification():
  468. if options[CulebraOptions.MULTI_DEVICE]:
  469. warnings.warn('Multi-device not implemented yet for this case')
  470. else:
  471. logAction('opening Notification')
  472. print '%s%svc.uiDevice.openNotification()' % (indent, prefix)
  473. def printOpenQuickSettings():
  474. if options[CulebraOptions.MULTI_DEVICE]:
  475. warnings.warn('Multi-device not implemented yet for this case')
  476. else:
  477. logAction('opening Quick Settings')
  478. print '%s%svc.uiDevice.openQuickSettings()' % (indent, prefix)
  479. def printChangeLanguage(code):
  480. if options[CulebraOptions.MULTI_DEVICE]:
  481. warnings.warn('Multi-device not implemented yet for this case')
  482. else:
  483. logAction('Changing language to %s' % code)
  484. print '%s%svc.uiDevice.changeLanguage("%s")' % (indent, prefix, code)
  485. def printTakeSnapshot(filename, _format, deviceart, dropshadow, screenglare):
  486. '''
  487. Prints the corresponding writeImageToFile() to take a snapshot
  488. '''
  489. if options[CulebraOptions.MULTI_DEVICE]:
  490. warnings.warn('Multi-device not implemented yet for this case')
  491. else:
  492. logAction(u'taking snapshot @ %s format=%s %s %s %s' % (filename, _format, deviceart, dropshadow, screenglare))
  493. print '%s%svc.writeImageToFile(\'%s\', \'%s\', \'%s\', %s, %s)' % (indent, prefix, filename, _format, deviceart, dropshadow, screenglare)
  494. def traverseAndPrint(view):
  495. '''
  496. Traverses the View tree and prints the corresponding statement.
  497. @type view: L{View}
  498. @param view: the View
  499. '''
  500. if DEBUG:
  501. print >> sys.stderr, "traverseAndPrint(view=%s)" % view.getId()
  502. if options[CulebraOptions.VERBOSE_COMMENTS]:
  503. printVerboseComments(view)
  504. if options[CulebraOptions.FIND_VIEWS_BY_ID]:
  505. printFindViewById(view)
  506. if options[CulebraOptions.FIND_VIEWS_WITH_TEXT]:
  507. printFindViewWithText(view, options[CulebraOptions.USE_REGEXPS])
  508. if options[CulebraOptions.FIND_VIEWS_WITH_CONTENT_DESCRIPTION]:
  509. printFindViewWithContentDescription(view, options[CulebraOptions.USE_REGEXPS])
  510. if options[CulebraOptions.SAVE_VIEW_SCREENSHOTS]:
  511. _format = 'PNG'
  512. filename = options[CulebraOptions.SAVE_VIEW_SCREENSHOTS] + os.sep + view.variableNameFromId() + '.' + _format.lower()
  513. printSaveViewScreenshot(view, filename, _format)
  514. def printOperation(view, op, *args):
  515. if len(args) == 0:
  516. # We use tuple values in the rest of this method, so if an empty tuple was passed
  517. # replace it by one containing None
  518. args = ( None, None )
  519. elif len(args) < 2:
  520. # We use tuple values in the rest of this method, so if an empty tuple was passed
  521. # replace it by one containing None
  522. args = ( args[0], None )
  523. if DEBUG:
  524. print >> sys.stderr, "printOperation(",
  525. print >> sys.stderr, view.__str__(),
  526. print >> sys.stderr, ",", op, ",",
  527. for a in args:
  528. if isinstance(a, unicode):
  529. print >> sys.stderr, a.encode(encoding='ascii', errors='replace'), ", ",
  530. else:
  531. print >> sys.stderr, a,
  532. print >> sys.stderr, ")"
  533. if op == Operation.SLEEP:
  534. printSleep(secs=args[0])
  535. return
  536. elif op == Operation.PRESS:
  537. printPress(keycode=args[0])
  538. return
  539. elif op == Operation.DUMP:
  540. printDump(window=args[0], dump=args[1])
  541. return
  542. elif op == Operation.DRAG:
  543. printDrag(start=args[0], end=args[1], duration=args[2], steps=args[3], unit=args[4], orientation=args[5])
  544. return
  545. elif op == Operation.TOUCH_POINT:
  546. printTouch(x=args[0], y=args[1], unit=args[2], orientation=args[3])
  547. return
  548. elif op == Operation.LONG_TOUCH_POINT:
  549. printLongTouch(x=args[0], y=args[1], duration=args[2], unit=args[3], orientation=args[4])
  550. return
  551. elif op == Operation.TRAVERSE:
  552. printTraverse()
  553. return
  554. elif op == Operation.SNAPSHOT:
  555. printTakeSnapshot(filename=args[0], _format=args[1], deviceart=args[2], dropshadow=args[3], screenglare=args[4])
  556. return
  557. elif op == Operation.VIEW_SNAPSHOT:
  558. printSaveViewScreenshot(view, filename=args[0], _format=args[1])
  559. return
  560. elif op == Operation.FLING_BACKWARD:
  561. printFlingBackward(view)
  562. return
  563. elif op == Operation.FLING_FORWARD:
  564. printFlingForward(view)
  565. return
  566. elif op == Operation.FLING_TO_BEGINNING:
  567. printFlingToBeginning(view)
  568. return
  569. elif op == Operation.FLING_TO_END:
  570. printFlingToEnd(view)
  571. return
  572. elif op == Operation.OPEN_NOTIFICATION:
  573. printOpenNotification()
  574. return
  575. elif op == Operation.OPEN_QUICK_SETTINGS:
  576. printOpenQuickSettings()
  577. return
  578. elif op == Operation.CHANGE_LANGUAGE:
  579. printChangeLanguage(code=args[0])
  580. return
  581. if view is None:
  582. warnings.warn('view is None. Perhaps you forgot to add some "op" in the previous if.')
  583. bd = Descriptor.findBestDescriptor(view)
  584. if bd == Descriptor.CONTENT_DESCRIPTION:
  585. printFindViewWithContentDescription(view, options[CulebraOptions.USE_REGEXPS], op, args[0])
  586. elif bd == Descriptor.TEXT:
  587. printFindViewWithText(view, options[CulebraOptions.USE_REGEXPS], op, args[0])
  588. else:
  589. printFindViewById(view, op, args[0])
  590. def str2bool(v):
  591. return v.lower() in ("yes", "true", "t", "1", "on")
  592. def value2dictionaryKey(v):
  593. v = v.lower()
  594. k = ['id', 'text', 'content-description']
  595. sk = ['i', 't', 'd']
  596. if v in k:
  597. return v
  598. if v in sk:
  599. return k[sk.index(v)]
  600. error("Invalid dictionary key: %s" % v)
  601. usage()
  602. def getShebangJar():
  603. if options[CulebraOptions.USE_JAR]:
  604. import java
  605. osName = java.lang.System.getProperty('os.name')
  606. if osName == 'Linux':
  607. return SHEBANG[SB_JAR_LINUX]
  608. else:
  609. return SHEBANG[SB_JAR]
  610. else:
  611. return SHEBANG[SB_NO_JAR]
  612. def getWindowOption():
  613. return options[CulebraOptions.WINDOW] if isinstance(options[CulebraOptions.WINDOW], str) and options[CulebraOptions.WINDOW][0] in '-0123456789' else "'%s'" % options[CulebraOptions.WINDOW]
  614. def printScriptHeader():
  615. print '''%s
  616. # -*- coding: utf-8 -*-
  617. \'\'\'
  618. Copyright (C) 2013-2014 Diego Torres Milano
  619. Created on %s by Culebra v%s
  620. __ __ __ __
  621. / \ / \ / \ / \
  622. ____________________/ __\/ __\/ __\/ __\_____________________________
  623. ___________________/ /__/ /__/ /__/ /________________________________
  624. | / \ / \ / \ / \ \___
  625. |/ \_/ \_/ \_/ \ o \
  626. \_____/--<
  627. @author: Diego Torres Milano
  628. @author: Jennifer E. Swofford (ascii art snake)
  629. \'\'\'
  630. import re
  631. import sys
  632. import os
  633. ''' % (getShebangJar(), date.today(), __version__)
  634. def printUnittestImport():
  635. print '''
  636. import unittest
  637. '''
  638. def printAppendToSysPath():
  639. print '''
  640. try:
  641. sys.path.append(os.path.join(os.environ['ANDROID_VIEW_CLIENT_HOME'], 'src'))
  642. except:
  643. pass
  644. '''
  645. def printPrependToSysPath():
  646. print '''
  647. try:
  648. sys.path.insert(0, os.path.join(os.environ['ANDROID_VIEW_CLIENT_HOME'], 'src'))
  649. except:
  650. pass
  651. '''
  652. def printLogAction(action, priority='D'):
  653. # FIXME: This works only for CulebraTestCases
  654. # This relies on shortcut variables already set (i.e. _v)
  655. if options[CulebraOptions.MULTI_DEVICE]:
  656. print u'%s[_d.Log.%s(TAG, "%s", _v) for _d in %sallDevices()]' % (indent, priority.lower(), action, prefix)
  657. else:
  658. print '%s%sdevice.Log.%s(TAG, "%s", _v)' % (indent, prefix, priority.lower(), action)
  659. def logAction(action):
  660. if options[CulebraOptions.LOG_ACTIONS]:
  661. printLogAction(action)
  662. def runCulebron():
  663. Culebron.checkSupportedSdkVersion(device.getSdkVersion())
  664. Culebron.checkDependencies()
  665. culebron = Culebron(vc, printOperation, options[CulebraOptions.SCALE])
  666. if options[CulebraOptions.DEVICE_ART]:
  667. culebron.deviceArt = options[CulebraOptions.DEVICE_ART]
  668. culebron.dropShadow = options[CulebraOptions.DROP_SHADOW]
  669. culebron.screenGlare = options[CulebraOptions.SCREEN_GLARE]
  670. culebron.takeScreenshotAndShowItOnWindow()
  671. culebron.mainloop()
  672. def printShortcutVariables():
  673. if options[CulebraOptions.UNIT_TEST_CLASS] or options[CulebraOptions.UNIT_TEST_METHOD]:
  674. print '''\
  675. _s = CulebraTests.sleep
  676. _v = CulebraTests.verbose
  677. '''
  678. else:
  679. print '''\
  680. _s = 5
  681. _v = '--verbose' in sys.argv
  682. '''
  683. ################
  684. # __main__
  685. ################
  686. progname = os.path.basename(sys.argv[0])
  687. try:
  688. optlist, args = getopt.getopt(sys.argv[1:], CulebraOptions.SHORT_OPTS, CulebraOptions.LONG_OPTS)
  689. sys.argv[1:] = args
  690. except getopt.GetoptError, e:
  691. error(str(e))
  692. usage()
  693. kwargs1 = {CulebraOptions.VERBOSE: False, 'ignoresecuredevice': False, 'ignoreversioncheck': False}
  694. serialno = None
  695. kwargs2 = {ViewClientOptions.FORCE_VIEW_SERVER_USE: False, ViewClientOptions.START_VIEW_SERVER: True,
  696. ViewClientOptions.AUTO_DUMP: False, ViewClientOptions.IGNORE_UIAUTOMATOR_KILLED: True,
  697. ViewClientOptions.COMPRESSED_DUMP: True}
  698. options = {CulebraOptions.FIND_VIEWS_BY_ID: True, CulebraOptions.FIND_VIEWS_WITH_TEXT: True, CulebraOptions.FIND_VIEWS_WITH_CONTENT_DESCRIPTION: True,
  699. CulebraOptions.USE_REGEXPS: False, CulebraOptions.VERBOSE_COMMENTS: False,
  700. CulebraOptions.UNIT_TEST_CLASS: False, CulebraOptions.UNIT_TEST_METHOD: None, CulebraOptions.USE_JAR: False,
  701. CulebraOptions.USE_DICTIONARY: False, CulebraOptions.DICTIONARY_KEYS_FROM: 'id',
  702. CulebraOptions.AUTO_REGEXPS: None, CulebraOptions.START_ACTIVITY: None, CulebraOptions.OUTPUT: None, CulebraOptions.INTERACTIVE: False,
  703. CulebraOptions.WINDOW:-1, CulebraOptions.PREPEND_TO_SYS_PATH: False,
  704. CulebraOptions.SAVE_SCREENSHOT: None, CulebraOptions.SAVE_VIEW_SCREENSHOTS: None,
  705. CulebraOptions.GUI: False,
  706. CulebraOptions.DO_NOT_VERIFY_SCREEN_DUMP: False,
  707. CulebraOptions.SCALE: 1,
  708. CulebraOptions.ORIENTATION_LOCKED: None,
  709. CulebraOptions.MULTI_DEVICE: False,
  710. CulebraOptions.LOG_ACTIONS: False,
  711. CulebraOptions.DEVICE_ART: None,
  712. CulebraOptions.DROP_SHADOW: False,
  713. CulebraOptions.SCREEN_GLARE: False,
  714. }
  715. transform = traverseAndPrint
  716. for o, a in optlist:
  717. o = o.strip('-')
  718. if o in ['H', CulebraOptions.HELP]:
  719. help()
  720. elif o in ['V', CulebraOptions.VERBOSE]:
  721. kwargs1[CulebraOptions.VERBOSE] = True
  722. elif o in ['v', CulebraOptions.VERSION]:
  723. version()
  724. elif o in ['I', CulebraOptions.IGNORE_SECURE_DEVICE]:
  725. kwargs1['ignoresecuredevice'] = True
  726. elif o in ['E', CulebraOptions.IGNORE_VERSION_CHECK]:
  727. kwargs1['ignoreversioncheck'] = True
  728. elif o in ['F', CulebraOptions.FORCE_VIEW_SERVER_USE]:
  729. kwargs2['forceviewserveruse'] = True
  730. elif o in ['S', CulebraOptions.DO_NOT_START_VIEW_SERVER]:
  731. kwargs2['startviewserver'] = False
  732. elif o in ['k', CulebraOptions.DO_NOT_IGNORE_UIAUTOMATOR_KILLED]:
  733. kwargs2['ignoreuiautomatorkilled'] = False
  734. elif o in ['w', CulebraOptions.WINDOW]:
  735. options[CulebraOptions.WINDOW] = a
  736. elif o in ['i', CulebraOptions.FIND_VIEWS_BY_ID]:
  737. options[CulebraOptions.FIND_VIEWS_BY_ID] = str2bool(a)
  738. elif o in ['t', CulebraOptions.FIND_VIEWS_WITH_TEXT]:
  739. options[CulebraOptions.FIND_VIEWS_WITH_TEXT] = str2bool(a)
  740. elif o in ['d', CulebraOptions.FIND_VIEWS_WITH_CONTENT_DESCRIPTION]:
  741. options[CulebraOptions.FIND_VIEWS_WITH_CONTENT_DESCRIPTION] = str2bool(a)
  742. elif o in ['r', CulebraOptions.USE_REGEXPS]:
  743. options[CulebraOptions.USE_REGEXPS] = True
  744. elif o in ['C', CulebraOptions.VERBOSE_COMMENTS]:
  745. options[CulebraOptions.VERBOSE_COMMENTS] = True
  746. elif o in ['U', CulebraOptions.UNIT_TEST_CLASS]:
  747. options[CulebraOptions.UNIT_TEST_CLASS] = True
  748. elif o in ['M', CulebraOptions.UNIT_TEST_METHOD]:
  749. if not a.startswith('test'):
  750. warnings.warn('Method name should start with "test"')
  751. options[CulebraOptions.UNIT_TEST_METHOD] = a
  752. elif o in ['j', CulebraOptions.USE_JAR]:
  753. options[CulebraOptions.USE_JAR] = str2bool(a)
  754. elif o in ['D', CulebraOptions.USE_DICTIONARY]:
  755. options[CulebraOptions.USE_DICTIONARY] = str2bool(a)
  756. elif o in ['K', CulebraOptions.DICTIONARY_KEYS_FROM]:
  757. options[CulebraOptions.DICTIONARY_KEYS_FROM] = value2dictionaryKey(a)
  758. elif o in ['R', CulebraOptions.AUTO_REGEXPS]:
  759. options[CulebraOptions.AUTO_REGEXPS] = a.split(',')
  760. for r in options[CulebraOptions.AUTO_REGEXPS]:
  761. if r == 'help':
  762. autoRegexpsHelp()
  763. if r == 'all':
  764. options[CulebraOptions.AUTO_REGEXPS] = CulebraOptions.AUTO_REGEXPS_RES.keys()
  765. break
  766. if r not in CulebraOptions.AUTO_REGEXPS_RES:
  767. error("invalid auto regexp: %s\n" % (r))
  768. usage()
  769. # CulebraOptions.AUTO_REGEPXS implies CulebraOptions.USE_REGEXPS
  770. options[CulebraOptions.USE_REGEXPS] = True
  771. elif o in ['a', CulebraOptions.START_ACTIVITY]:
  772. options[CulebraOptions.START_ACTIVITY] = a
  773. elif o in ['o', CulebraOptions.OUTPUT]:
  774. options[CulebraOptions.OUTPUT] = a
  775. elif o in ['p', CulebraOptions.PREPEND_TO_SYS_PATH]:
  776. options[CulebraOptions.PREPEND_TO_SYS_PATH] = True
  777. elif o in ['f', CulebraOptions.SAVE_SCREENSHOT]:
  778. options[CulebraOptions.SAVE_SCREENSHOT] = a
  779. elif o in ['W', CulebraOptions.SAVE_VIEW_SCREENSHOTS]:
  780. options[CulebraOptions.SAVE_VIEW_SCREENSHOTS] = a
  781. elif o in ['G', CulebraOptions.GUI]:
  782. options[CulebraOptions.GUI] = True
  783. elif o in ['u', CulebraOptions.DO_NOT_VERIFY_SCREEN_DUMP]:
  784. options[CulebraOptions.DO_NOT_VERIFY_SCREEN_DUMP] = True
  785. elif o in ['P', CulebraOptions.SCALE]:
  786. options[CulebraOptions.SCALE] = float(a)
  787. elif o in ['O', CulebraOptions.ORIENTATION_LOCKED]:
  788. options[CulebraOptions.ORIENTATION_LOCKED] = 'PENDING'
  789. elif o in ['s', CulebraOptions.SERIALNO]:
  790. __devices = a.split()
  791. if len(__devices) > 1:
  792. warnings.warn('List of devices not supported yet. Using first device instead.')
  793. serialno = __devices[0]
  794. elif o in ['m', CulebraOptions.MULTI_DEVICE]:
  795. options[CulebraOptions.MULTI_DEVICE] = True
  796. elif o in ['L', CulebraOptions.LOG_ACTIONS]:
  797. options[CulebraOptions.LOG_ACTIONS] = True
  798. elif o in ['A', CulebraOptions.DEVICE_ART]:
  799. options[CulebraOptions.DEVICE_ART] = a
  800. elif o in ['Z', CulebraOptions.DROP_SHADOW]:
  801. options[CulebraOptions.DROP_SHADOW] = True
  802. elif o in ['B', CulebraOptions.SCREEN_GLARE]:
  803. options[CulebraOptions.SCREEN_GLARE] = True
  804. if not (options[CulebraOptions.FIND_VIEWS_BY_ID] or options[CulebraOptions.FIND_VIEWS_WITH_TEXT] or options[CulebraOptions.FIND_VIEWS_WITH_CONTENT_DESCRIPTION]):
  805. if not options[CulebraOptions.VERBOSE_COMMENTS]:
  806. warnings.warn('All printing options disabled. Output will be empty.')
  807. else:
  808. warnings.warn('Only verbose comments will be printed')
  809. device, serialno = ViewClient.connectToDeviceOrExit(serialno=serialno, **kwargs1)
  810. if options[CulebraOptions.ORIENTATION_LOCKED] == 'PENDING':
  811. options[CulebraOptions.ORIENTATION_LOCKED] = device.display['orientation']
  812. if options[CulebraOptions.START_ACTIVITY]:
  813. device.startActivity(component=options[CulebraOptions.START_ACTIVITY])
  814. vc = ViewClient(device, serialno, **kwargs2)
  815. if options[CulebraOptions.OUTPUT]:
  816. sys.stdout = codecs.open(options[CulebraOptions.OUTPUT], mode='w', encoding='utf-8', errors='replace')
  817. import stat
  818. st = os.stat(options[CulebraOptions.OUTPUT])
  819. os.chmod(options[CulebraOptions.OUTPUT], st.st_mode | stat.S_IEXEC)
  820. if options[CulebraOptions.UNIT_TEST_CLASS] or (not options[CulebraOptions.UNIT_TEST_METHOD]):
  821. printScriptHeader()
  822. if options[CulebraOptions.UNIT_TEST_CLASS]:
  823. printUnittestImport()
  824. if options[CulebraOptions.PREPEND_TO_SYS_PATH]:
  825. printPrependToSysPath()
  826. if options[CulebraOptions.UNIT_TEST_CLASS] or (not options[CulebraOptions.UNIT_TEST_METHOD]):
  827. print '''\
  828. from com.dtmilano.android.viewclient import ViewClient%s
  829. TAG = '%s'
  830. ''' % (', CulebraTestCase' if options[CulebraOptions.UNIT_TEST_CLASS] else '', TAG)
  831. if options[CulebraOptions.UNIT_TEST_CLASS]:
  832. print '''
  833. class CulebraTests(CulebraTestCase):
  834. @classmethod
  835. def setUpClass(cls):
  836. cls.kwargs1 = %s
  837. cls.kwargs2 = %s
  838. cls.options = %s
  839. cls.sleep = 5
  840. ''' % (kwargs1, kwargs2, options),
  841. print '''\
  842. def setUp(self):
  843. super(CulebraTests, self).setUp()
  844. '''
  845. print '''\
  846. def tearDown(self):
  847. super(CulebraTests, self).tearDown()
  848. '''
  849. print '''\
  850. def preconditions(self):
  851. if not super(CulebraTests, self).preconditions():
  852. return False
  853. return True
  854. def %s(self):
  855. if not self.preconditions():
  856. self.fail('Preconditions failed')
  857. ''' % (options[CulebraOptions.UNIT_TEST_METHOD] if options[CulebraOptions.UNIT_TEST_METHOD] else 'testSomething')
  858. printShortcutVariables()
  859. if options[CulebraOptions.SAVE_SCREENSHOT]:
  860. print '''\
  861. self.vc.writeImageToFile('%s')
  862. ''' % options[CulebraOptions.SAVE_SCREENSHOT]
  863. if options[CulebraOptions.USE_DICTIONARY]:
  864. print '''\
  865. self.views = dict()'''
  866. vc.dump(window=options[CulebraOptions.WINDOW])
  867. indent = ' ' * 8
  868. prefix = 'self.'
  869. # if not options[CulebraOptions.DO_NOT_VERIFY_SCREEN_DUMP]:
  870. # print '''\
  871. # self.vc.dump(%s)
  872. # ''' % getWindowOption()
  873. # vc.traverse(transform=transform)
  874. # print
  875. if options[CulebraOptions.GUI]:
  876. runCulebron()
  877. elif not options[CulebraOptions.DO_NOT_VERIFY_SCREEN_DUMP]:
  878. printDump(getWindowOption())
  879. print '''
  880. if __name__ == '__main__':
  881. CulebraTests.main()
  882. '''
  883. else:
  884. # Not a unittest class, still could be a unittest method as we allow to generate methods separately from their classes
  885. if not options[CulebraOptions.UNIT_TEST_METHOD]:
  886. printShortcutVariables()
  887. print '''
  888. kwargs1 = %s
  889. device, serialno = ViewClient.connectToDeviceOrExit(**kwargs1)
  890. ''' % kwargs1,
  891. if options[CulebraOptions.START_ACTIVITY] and not options[CulebraOptions.UNIT_TEST_METHOD]:
  892. print '''\
  893. device.startActivity(component='%s')''' % options[CulebraOptions.START_ACTIVITY]
  894. if not options[CulebraOptions.UNIT_TEST_METHOD]:
  895. print '''\
  896. kwargs2 = %s
  897. vc = ViewClient(device, serialno, **kwargs2)
  898. #vc.dump(window=%s) # FIXME: seems not needed
  899. ''' % (kwargs2, getWindowOption())
  900. if options[CulebraOptions.USE_DICTIONARY]:
  901. print '''views = dict()'''
  902. if options[CulebraOptions.SAVE_SCREENSHOT]:
  903. print '''\
  904. vc.writeImageToFile('%s')
  905. ''' % options[CulebraOptions.SAVE_SCREENSHOT]
  906. vc.dump(window=options[CulebraOptions.WINDOW])
  907. if options[CulebraOptions.UNIT_TEST_METHOD]:
  908. print '''
  909. def %s(self):
  910. \'\'\'
  911. Test method.
  912. \'\'\'
  913. if not self.preconditions():
  914. self.fail('Preconditions failed')
  915. ''' % (options[CulebraOptions.UNIT_TEST_METHOD])
  916. indent = ' ' * 8
  917. prefix = 'self.'
  918. printShortcutVariables()
  919. if options[CulebraOptions.GUI]:
  920. runCulebron()
  921. elif not options[CulebraOptions.DO_NOT_VERIFY_SCREEN_DUMP]:
  922. printDump(getWindowOption())
  923. if options[CulebraOptions.INTERACTIVE]:
  924. import socket
  925. HOST = 'localhost'
  926. PORT = 8900
  927. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  928. s.connect((HOST, PORT))
  929. s.sendall("RECORD EVENTS START\n")
  930. fin = open("/dev/tty")
  931. while True:
  932. print >> sys.stderr, "Reading events..."
  933. data = s.recv(1024)
  934. code = ViewClient.excerpt(data)
  935. exec code
  936. resp = raw_input("Continue recording events? [Y/n]: ")
  937. if resp in ['N', 'n']:
  938. break
  939. s.sendall("RECORD EVENTS STOP\n")
  940. s.close()