How to use setBitmapPath method in fMBT

Best Python code snippet using fMBT_python

fmbtgti.py

Source:fmbtgti.py Github

copy

Full Screen

...61bitmapPixelSize = 362bitmapPixelSize = 363After that, device B can be tested without taking new screenshot.64d = fmbtandroid.Device()65d.setBitmapPath("bitmaps/android-4.2/device-B")66"""67import cgi68import ctypes69import datetime70import distutils.sysconfig71import gc72import inspect73import math74import os75import shutil76import subprocess77import sys78import time79import traceback80import types81import fmbt82import eyenfinger83# See imagemagick convert parameters.84_OCRPREPROCESS = [85 ''86]87# See tesseract -pagesegmode.88_OCRPAGESEGMODES = [3]89_g_defaultOcrEngine = None # optical character recognition engine90_g_defaultOirEngine = None # optical image recognition engine91_g_ocrEngines = []92_g_oirEngines = []93def _fmbtLog(msg):94 fmbt.fmbtlog("fmbtgti: %s" % (msg,))95def _filenameTimestamp(t=None):96 if t == None:97 t = datetime.datetime.now()98 return t.strftime("%Y%m%d-%H%M%S-%f")99def _takeDragArgs(d):100 return _takeArgs(("startPos", "delayBeforeMoves", "delayBetweenMoves",101 "delayAfterMoves", "movePoints"), d)102def _takeTapArgs(d):103 return _takeArgs(("tapPos", "long", "hold", "count", "delayBetweenTaps", "button"), d)104def _takeWaitArgs(d):105 return _takeArgs(("waitTime", "pollDelay"), d)106def _takeOirArgs(screenshotOrOirEngine, d, thatsAll=False):107 if isinstance(screenshotOrOirEngine, Screenshot):108 oirEngine = screenshotOrOirEngine.oirEngine()109 else:110 oirEngine = screenshotOrOirEngine111 return _takeArgs(oirEngine._findBitmapArgNames(), d, thatsAll)112def _takeOcrArgs(screenshotOrOcrEngine, d, thatsAll=False):113 if isinstance(screenshotOrOcrEngine, Screenshot):114 ocrEngine = screenshotOrOcrEngine.ocrEngine()115 else:116 ocrEngine = screenshotOrOcrEngine117 return _takeArgs(ocrEngine._findTextArgNames(), d, thatsAll)118def _takeArgs(argNames, d, thatsAll=False):119 """120 Returns pair:121 (dict of items where key in argNames,122 dict of items that were left in d)123 If thatsAll is True, require that all arguments have been124 consumed.125 """126 retval = {}127 for a in argNames:128 if a in d:129 retval[a] = d.pop(a, None)130 if thatsAll and len(d) > 0:131 raise TypeError('Unknown argument(s): "%s"' %132 ('", "'.join(sorted(d.keys()))))133 return retval, d134def _intCoords((x, y), (width, height)):135 if 0 <= x <= 1 and type(x) == float: x = x * width136 if 0 <= y <= 1 and type(y) == float: y = y * height137 return (int(round(x)), int(round(y)))138def _edgeDistanceInDirection((x, y), (width, height), direction):139 x, y = _intCoords((x, y), (width, height))140 direction = direction % 360 # -90 => 270, 765 => 45141 dirRad = math.radians(direction)142 if 0 < direction < 180:143 distTopBottom = y / math.sin(dirRad)144 elif 180 < direction < 360:145 distTopBottom = -(height - y) / math.sin(dirRad)146 else:147 distTopBottom = float('inf')148 if 90 < direction < 270:149 distLeftRight = -x / math.cos(dirRad)150 elif 270 < direction <= 360 or 0 <= direction < 90:151 distLeftRight = (width - x) / math.cos(dirRad)152 else:153 distLeftRight = float('inf')154 return min(distTopBottom, distLeftRight)155### Binding to eye4graphics.so156_libpath = ["", ".", distutils.sysconfig.get_python_lib(plat_specific=1)]157_suffix = ".so"158if sys.platform == "win32":159 _suffix = ".dll"160for _dirname in _libpath:161 try:162 eye4graphics = ctypes.CDLL(os.path.join(_dirname , "eye4graphics"+_suffix))163 break164 except: pass165else:166 raise ImportError("%s cannot load eye4graphics.so" % (__file__,))167class _Bbox(ctypes.Structure):168 _fields_ = [("left", ctypes.c_int32),169 ("top", ctypes.c_int32),170 ("right", ctypes.c_int32),171 ("bottom", ctypes.c_int32),172 ("error", ctypes.c_int32)]173### end of binding to eye4graphics.so174def _e4gImageDimensions(e4gImage):175 struct_bbox = _Bbox(0, 0, 0, 0, 0)176 eye4graphics.openedImageDimensions(ctypes.byref(struct_bbox), e4gImage)177 return (struct_bbox.right, struct_bbox.bottom)178def _e4gImageIsBlank(filename):179 e4gImage = eye4graphics.openImage(filename)180 rv = (eye4graphics.openedImageIsBlank(e4gImage) == 1)181 eye4graphics.closeImage(e4gImage)182 return rv183class GUITestConnection(object):184 """185 Implements GUI testing primitives needed by GUITestInterface.186 All send* and recv* methods return187 - True on success188 - False on user error (unknown keyName, coordinates out of range)189 - raise Exception on framework error (connection lost, missing190 dependencies).191 """192 def sendPress(self, keyName):193 raise NotImplementedError('sendPress("%s") needed but not implemented.' % (keyName,))194 def sendKeyDown(self, keyName):195 raise NotImplementedError('sendKeyDown("%s") needed but not implemented.' % (keyName,))196 def sendKeyUp(self, keyName):197 raise NotImplementedError('sendKeyUp("%s") needed but not implemented.' % (keyName,))198 def sendTap(self, x, y):199 raise NotImplementedError('sendTap(%d, %d) needed but not implemented.' % (x, y))200 def sendTouchDown(self, x, y):201 raise NotImplementedError('sendTouchDown(%d, %d) needed but not implemented.' % (x, y))202 def sendTouchMove(self, x, y):203 raise NotImplementedError('sendTouchMove(%d, %d) needed but not implemented.' % (x, y))204 def sendTouchUp(self, x, y):205 raise NotImplementedError('sendTouchUp(%d, %d) needed but not implemented.' % (x, y))206 def sendType(self, text):207 raise NotImplementedError('sendType("%s") needed but not implemented.' % (text,))208 def recvScreenshot(self, filename):209 """210 Saves screenshot from the GUI under test to given filename.211 """212 raise NotImplementedError('recvScreenshot("%s") needed but not implemented.' % (filename,))213 def target(self):214 """215 Returns a string that is unique to each test target. For216 instance, Android device serial number.217 """218 return "GUITestConnectionTarget"219class OrEngine(object):220 """221 Optical recognition engine. Base class for OCR and OIR engines,222 enables registering engine instances.223 """224 def __init__(self, *args, **kwargs):225 pass226 def register(self, defaultOcr=False, defaultOir=False):227 """228 Register this engine instance to the list of OCR and/or OIR229 engines.230 Parameters:231 defaultOcr (optional, boolean):232 if True, use this OCR engine by default in all new233 GUITestInterface instances. The default is False.234 defaultOir (optional, boolean):235 if True, use this OIR engine by default in all new236 GUITestInterface instances. The default is False.237 Returns the index with which the engine was registered to the238 list of OCR or OIR engines. If this instance implements both239 OCR and OIR engines, returns pair (OCR index, OIR index).240 """241 # Allow a single engine implement both OCR and OIR engine242 # interfaces. Therefore, it must be possible to call243 # e.register(defaultOcr=True, defaultOir=True).244 #245 global _g_defaultOcrEngine, _g_defaultOirEngine246 global _g_ocrEngines, _g_oirEngines247 engineIndexes = []248 if isinstance(self, OcrEngine):249 if not self in _g_ocrEngines:250 _g_ocrEngines.append(self)251 engineIndexes.append(_g_ocrEngines.index(self))252 if defaultOcr:253 _g_defaultOcrEngine = self254 if isinstance(self, OirEngine):255 if not self in _g_oirEngines:256 _g_oirEngines.append(self)257 engineIndexes.append(_g_oirEngines.index(self))258 if defaultOir:259 _g_defaultOirEngine = self260 if len(engineIndexes) == 1:261 return engineIndexes[0]262 else:263 return engineIndexes264class OcrEngine(OrEngine):265 """266 This is an abstract interface for OCR engines that can be plugged267 into fmbtgti.GUITestInterface instances and Screenshots.268 To implement an OCR engine, you need to override _findText() at269 minimum. See _findText documentation in this class for270 requirements.271 If possible in your OCR engine, you can provide _dumpOcr() to272 reveal what is recognized in screenshots.273 For efficient caching of results and freeing cached results, you274 can override _addScreenshot() and _removeScreenshot(). Every275 screenshot is added before findText() or dumpOcr().276 A typical usage of OcrEngine instance:277 - oe.addScreenshot(ss)278 - oe.findText(ss, text1, <engine/screenshot/find-specific-args>)279 - oe.findText(ss, text2, <engine/screenshot/find-specific-args>)280 - oe.removeScreenshot(ss)281 Note that there may be several screenshots added before they are282 removed.283 """284 def __init__(self, *args, **kwargs):285 super(OcrEngine, self).__init__(*args, **kwargs)286 self._ssFindTextDefaults = {}287 self._findTextDefaults = {}288 ocrFindArgs, _ = _takeOcrArgs(self, kwargs)289 self._setFindTextDefaults(ocrFindArgs)290 def dumpOcr(self, screenshot, **kwargs):291 """292 Returns what is recognized in the screenshot. For debugging293 purposes.294 """295 ocrArgs = self.__ocrArgs(screenshot, **kwargs)296 return self._dumpOcr(screenshot, **ocrArgs)297 def _dumpOcr(self, screenshot, **kwargs):298 return None299 def addScreenshot(self, screenshot, **findTextDefaults):300 """301 Prepare for finding text from the screenshot.302 Parameters:303 screenshot (fmbtgti.Screenshot)304 screenshot object to be searched from.305 other parameters (optional)306 findText defaults for this screenshot.307 Notice that there may be many screenshots simultaneously.308 Do not keep reference to the screenshot object.309 """310 self.setScreenshotFindTextDefaults(screenshot, **findTextDefaults)311 return self._addScreenshot(screenshot, **findTextDefaults)312 def _addScreenshot(self, screenshot, **findTextDefaults):313 pass314 def removeScreenshot(self, screenshot):315 """316 OCR queries on the screenshot will not be made anymore.317 """318 self._removeScreenshot(screenshot)319 try:320 del self._ssFindTextDefaults[id(screenshot)]321 except KeyError:322 raise KeyError('screenshot "%s" does not have findTextDefaults. '323 'If OcrEngine.addScreenshot() is overridden, it '324 '*must* call parent\'s addScreenshot.' % (screenshot.filename(),))325 def _removeScreenshot(self, screenshot):326 pass327 def setFindTextDefaults(self, **findTextDefaults):328 return self._setFindTextDefaults(findTextDefaults, screenshot=None)329 def setScreenshotFindTextDefaults(self, screenshot, **findTextDefaults):330 return self._setFindTextDefaults(findTextDefaults, screenshot=screenshot)331 def _setFindTextDefaults(self, defaults, screenshot=None):332 """333 Set default values for optional arguments for findText().334 Parameters:335 defaults (dictionary)336 Default keyword arguments and their values.337 screenshot (optional, fmbtgti.Screenshot instance)338 Use the defaults for findText on this screenshot. If339 the defaults are None, make them default for all340 screenshots. Screenshot-specific defaults override341 engine default.342 """343 if screenshot == None:344 self._findTextDefaults.update(defaults)345 else:346 ssid = id(screenshot)347 if not ssid in self._ssFindTextDefaults:348 self._ssFindTextDefaults[ssid] = self._findTextDefaults.copy()349 self._ssFindTextDefaults[ssid].update(defaults)350 def findTextDefaults(self, screenshot=None):351 if screenshot == None:352 return self._findTextDefaults353 elif id(screenshot) in self._ssFindTextDefaults:354 return self._ssFindTextDefaults[id(screenshot)]355 else:356 return None357 def _findTextArgNames(self):358 """359 Returns names of optional findText arguments.360 """361 return inspect.getargspec(self._findText).args[3:]362 def __ocrArgs(self, screenshot, **priorityArgs):363 ocrArgs = {}364 ocrArgs.update(self._findTextDefaults)365 ssId = id(screenshot)366 if ssId in self._ssFindTextDefaults:367 ocrArgs.update(self._ssFindTextDefaults[ssId])368 ocrArgs.update(priorityArgs)369 return ocrArgs370 def findText(self, screenshot, text, **kwargs):371 """372 Return list of fmbtgti.GUIItems that match to text.373 """374 ocrArgs = self.__ocrArgs(screenshot, **kwargs)375 return self._findText(screenshot, text, **ocrArgs)376 def _findText(self, screenshot, text, **kwargs):377 """378 Find appearances of text from the screenshot.379 Parameters:380 screenshot (fmbtgti.Screenshot)381 Screenshot from which text is to be searched382 for. Use Screenshot.filename() to get the filename.383 text (string)384 text to be searched for.385 other arguments (engine specific)386 kwargs contain keyword arguments given to387 findText(screenshot, text, ...), already extended388 first with screenshot-specific findTextDefaults, then389 with engine-specific findTextDefaults.390 _findText *must* define all engine parameters as391 explicit keyword arguments:392 def _findText(self, screenshot, text, engArg1=42):393 ...394 Return list of fmbtgti.GUIItems.395 """396 raise NotImplementedError("_findText needed but not implemented.")397class _EyenfingerOcrEngine(OcrEngine):398 """399 OCR engine parameters that can be used in all400 ...OcrText() methods (swipeOcrText, tapOcrText, findItemsByOcrText, ...):401 match (float, optional):402 minimum match score in range [0.0, 1.0]. The default is403 1.0 (exact match).404 area ((left, top, right, bottom), optional):405 search from the given area only. Left, top, right and406 bottom are either absolute coordinates (integers) or407 floats in range [0.0, 1.0]. In the latter case they are408 scaled to screenshot dimensions. The default is (0.0,409 0.0, 1.0, 1.0), that is, search everywhere in the410 screenshot.411 pagesegmodes (list of integers, optional):412 try all integers as tesseract -pagesegmode413 arguments. The default is [3], another good option could414 be [3, 6].415 preprocess (string, optional):416 preprocess filter to be used in OCR for better417 result. Refer to eyenfinger.autoconfigure to search for418 a good one.419 """420 class _OcrResults(object):421 __slots__ = ("filename", "screenSize", "pagesegmodes", "preprocess", "area", "words")422 def __init__(self, filename, screenSize):423 self.filename = filename424 self.screenSize = screenSize425 self.pagesegmodes = None426 self.preprocess = None427 self.area = None428 self.words = None429 def __init__(self, *args, **engineDefaults):430 engineDefaults["area"] = engineDefaults.get("area", (0.0, 0.0, 1.0, 1.0))431 engineDefaults["match"] = engineDefaults.get("match", 1.0)432 engineDefaults["pagesegmodes"] = engineDefaults.get("pagesegmodes", _OCRPAGESEGMODES)433 engineDefaults["preprocess"] = engineDefaults.get("preprocess", _OCRPREPROCESS)434 super(_EyenfingerOcrEngine, self).__init__(*args, **engineDefaults)435 self._ss = {} # OCR results for screenshots436 def _addScreenshot(self, screenshot, **findTextDefaults):437 ssId = id(screenshot)438 self._ss[ssId] = _EyenfingerOcrEngine._OcrResults(screenshot.filename(), screenshot.size())439 def _removeScreenshot(self, screenshot):440 ssId = id(screenshot)441 if ssId in self._ss:442 del self._ss[ssId]443 def _findText(self, screenshot, text, match=None, preprocess=None, area=None, pagesegmodes=None):444 ssId = id(screenshot)445 self._assumeOcrResults(screenshot, preprocess, area, pagesegmodes)446 for ppfilter in self._ss[ssId].words.keys():447 try:448 score_text_bbox_list = eyenfinger.findText(449 text, self._ss[ssId].words[ppfilter], match=match)450 if not score_text_bbox_list:451 continue452 else:453 break454 except eyenfinger.BadMatch:455 continue456 else:457 return []458 retval = [GUIItem("OCR text (match %.2f)" % (score,),459 bbox, self._ss[ssId].filename,460 ocrFind=text, ocrFound=matching_text)461 for score, matching_text, bbox in score_text_bbox_list]462 return retval463 def _dumpOcr(self, screenshot, match=None, preprocess=None, area=None, pagesegmodes=None):464 ssId = id(screenshot)465 if self._ss[ssId].words == None:466 self._assumeOcrResults(screenshot, preprocess, area, pagesegmodes)467 w = []468 for ppfilter in self._ss[ssId].preprocess:469 for word in self._ss[ssId].words[ppfilter]:470 for appearance, (wid, middle, bbox) in enumerate(self._ss[ssId].words[ppfilter][word]):471 (x1, y1, x2, y2) = bbox472 w.append((word, (x1, y1, x2, y2)))473 return sorted(set(w), key=lambda i:(i[1][1]/8, i[1][0]))474 def _assumeOcrResults(self, screenshot, preprocess, area, pagesegmodes):475 ssId = id(screenshot)476 if not type(preprocess) in (list, tuple):477 preprocess = [preprocess]478 if self._ss[ssId].words == None or self._ss[ssId].preprocess != preprocess or self._ss[ssId].area != area:479 self._ss[ssId].words = {}480 self._ss[ssId].preprocess = preprocess481 self._ss[ssId].area = area482 for ppfilter in preprocess:483 pp = ppfilter % { "zoom": "-resize %sx" % (self._ss[ssId].screenSize[0] * 2) }484 eyenfinger.iRead(source=self._ss[ssId].filename, ocr=True, preprocess=pp, ocrArea=area, ocrPageSegModes=pagesegmodes)485 self._ss[ssId].words[ppfilter] = eyenfinger._g_words486def _defaultOcrEngine():487 if _g_defaultOcrEngine:488 return _g_defaultOcrEngine489 else:490 _EyenfingerOcrEngine().register(defaultOcr=True)491 return _g_defaultOcrEngine492class OirEngine(OrEngine):493 """494 This is an abstract interface for OIR (optical image recognition)495 engines that can be plugged into fmbtgti.GUITestInterface496 instances and Screenshots.497 To implement an OIR engine, you need to override _findBitmap() at498 minimum. See _findBitmap documentation in this class for499 requirements.500 This base class provides full set of OIR parameters to501 _findBitmap. The parameters are combined from502 - OirEngine find defaults, specified when OirEngine is503 instantiated.504 - Screenshot instance find defaults.505 - bitmap / bitmap directory find defaults (read from the506 .fmbtoirrc that is in the same directory as the bitmap).507 - ...Bitmap() method parameters.508 The latter in the list override the former.509 For efficient caching of results and freeing cached results, you510 can override _addScreenshot() and _removeScreenshot(). Every511 screenshot is added before findBitmap().512 A typical usage of OirEngine instance:513 - oe.addScreenshot(ss)514 - oe.findBitmap(ss, bmpFilename1, <engine/screenshot/find-specific-args>)515 - oe.findBitmap(ss, bmpFilename2, <engine/screenshot/find-specific-args>)516 - oe.removeScreenshot(ss)517 Note that there may be several screenshots added before they are518 removed. ss is a Screenshot instance. Do not keep references to519 Screenshot intances, otherwise garbage collector will not remove520 them.521 """522 def __init__(self, *args, **kwargs):523 super(OirEngine, self).__init__(*args, **kwargs)524 self._ssFindBitmapDefaults = {}525 self._findBitmapDefaults = {}526 oirArgs, _ = _takeOirArgs(self, kwargs)527 self._setFindBitmapDefaults(oirArgs)528 def addScreenshot(self, screenshot, **findBitmapDefaults):529 """530 Prepare for finding bitmap from the screenshot.531 Parameters:532 screenshot (fmbtgti.Screenshot)533 screenshot object to be searched from.534 other parameters (optional)535 findBitmap defaults for this screenshot.536 Notice that there may be many screenshots simultaneously.537 Do not keep reference to the screenshot object.538 """539 self.setScreenshotFindBitmapDefaults(screenshot, **findBitmapDefaults)540 return self._addScreenshot(screenshot, **findBitmapDefaults)541 def _addScreenshot(self, screenshot, **findBitmapDefaults):542 pass543 def removeScreenshot(self, screenshot):544 """545 OIR queries on the screenshot will not be made anymore.546 """547 self._removeScreenshot(screenshot)548 try:549 del self._ssFindBitmapDefaults[id(screenshot)]550 except KeyError:551 raise KeyError('screenshot "%s" does not have findBitmapDefaults. '552 'If OirEngine.addScreenshot() is overridden, it '553 '*must* call parent\'s addScreenshot.' % (screenshot.filename(),))554 def _removeScreenshot(self, screenshot):555 pass556 def setFindBitmapDefaults(self, **findBitmapDefaults):557 return self._setFindBitmapDefaults(findBitmapDefaults, screenshot=None)558 def setScreenshotFindBitmapDefaults(self, screenshot, **findBitmapDefaults):559 return self._setFindBitmapDefaults(findBitmapDefaults, screenshot=screenshot)560 def _setFindBitmapDefaults(self, defaults, screenshot=None):561 """562 Set default values for optional arguments for findBitmap().563 Parameters:564 defaults (dictionary)565 Default keyword arguments and their values.566 screenshot (optional, fmbtgti.Screenshot instance)567 Use the defaults for findBitmap on this screenshot. If568 the defaults are None, make them default for all569 screenshots. Screenshot-specific defaults override570 engine default.571 """572 if screenshot == None:573 self._findBitmapDefaults.update(defaults)574 else:575 ssid = id(screenshot)576 if not ssid in self._ssFindBitmapDefaults:577 self._ssFindBitmapDefaults[ssid] = self._findBitmapDefaults.copy()578 self._ssFindBitmapDefaults[ssid].update(defaults)579 def findBitmapDefaults(self, screenshot=None):580 if screenshot == None:581 return self._findBitmapDefaults582 elif id(screenshot) in self._ssFindBitmapDefaults:583 return self._ssFindBitmapDefaults[id(screenshot)]584 else:585 return None586 def _findBitmapArgNames(self):587 """588 Returns names of optional findBitmap arguments.589 """590 return inspect.getargspec(self._findBitmap).args[3:]591 def __oirArgs(self, screenshot, bitmap, **priorityArgs):592 oirArgs = {}593 oirArgs.update(self._findBitmapDefaults)594 ssId = id(screenshot)595 if ssId in self._ssFindBitmapDefaults:596 oirArgs.update(self._ssFindBitmapDefaults[ssId])597 oirArgs.update(priorityArgs)598 return oirArgs599 def findBitmap(self, screenshot, bitmap, **kwargs):600 """601 Return list of fmbtgti.GUIItems that match to bitmap.602 """603 oirArgs = self.__oirArgs(screenshot, bitmap, **kwargs)604 return self._findBitmap(screenshot, bitmap, **oirArgs)605 def _findBitmap(self, screenshot, bitmap, **kwargs):606 """607 Find appearances of bitmap from the screenshot.608 Parameters:609 screenshot (fmbtgti.Screenshot)610 Screenshot from which bitmap is to be searched611 for. Use Screenshot.filename() to get the filename.612 bitmap (string)613 bitmap to be searched for.614 other arguments (engine specific)615 kwargs contain keyword arguments given to616 findBitmap(screenshot, bitmap, ...), already extended617 first with screenshot-specific findBitmapDefaults, then618 with engine-specific findBitmapDefaults.619 _findBitmap *must* define all engine parameters as620 explicit keyword arguments:621 def _findBitmap(self, screenshot, bitmap, engArg1=42):622 ...623 Returns list of fmbtgti.GUIItems.624 """625 raise NotImplementedError("_findBitmap needed but not implemented.")626class _Eye4GraphicsOirEngine(OirEngine):627 """OIR engine parameters that can be used in all628 ...Bitmap() methods (swipeBitmap, tapBitmap, findItemsByBitmap, ...):629 colorMatch (float, optional):630 required color matching accuracy. The default is 1.0631 (exact match). For instance, 0.75 requires that every632 pixel's every RGB component value on the bitmap is at633 least 75 % match with the value of corresponding pixel's634 RGB component in the screenshot.635 opacityLimit (float, optional):636 threshold for comparing pixels with non-zero alpha637 channel. Pixels less opaque than the given threshold are638 skipped in match comparison. The default is 0, that is,639 alpha channel is ignored.640 area ((left, top, right, bottom), optional):641 search bitmap from the given area only. Left, top right642 and bottom are either absolute coordinates (integers) or643 floats in range [0.0, 1.0]. In the latter case they are644 scaled to screenshot dimensions. The default is (0.0,645 0.0, 1.0, 1.0), that is, search everywhere in the646 screenshot.647 limit (integer, optional):648 number of returned matches is limited to the limit. The649 default is -1: all matches are returned. Applicable in650 findItemsByBitmap.651 allowOverlap (boolean, optional):652 allow returned icons to overlap. If False, returned list653 contains only non-overlapping bounding boxes. The654 default is False.655 scale (float or pair of floats, optional):656 scale to be applied to the bitmap before657 matching. Single float is a factor for both X and Y658 axis, pair of floats is (xScale, yScale). The default is659 1.0.660 bitmapPixelSize (integer, optional):661 size of pixel rectangle on bitmap for which there must662 be same color on corresponding screenshot rectangle. If663 scale is 1.0, default is 1 (rectangle is 1x1). If scale664 != 1.0, the default is 2 (rectangle is 2x2).665 screenshotPixelSize (integer, optional):666 size of pixel rectangle on screenshot in which there667 must be a same color pixel as in the corresponding668 rectangle on bitmap. The default is scale *669 bitmapPixelSize.670 If unsure about parameters, but you have a bitmap that should be671 detected in a screenshot, try obj.oirEngine().adjustParameters().672 Example:673 d.enableVisualLog("params.html")674 screenshot = d.refreshScreenshot()675 results = d.oirEngine().adjustParameters(screenshot, "mybitmap.png")676 if results:677 item, params = results[0]678 print "found %s with parameters:" % (item,)679 print "\n".join(sorted([" %s = %s" % (k, params[k]) for k in params]))680 print "verify:", d.verifyBitmap("mybitmap.png", **params)681 Notice, that you can force refreshScreenshot to load old screenshot:682 d.refreshScreenshot("old.png")683 """684 def __init__(self, *args, **engineDefaults):685 engineDefaults["colorMatch"] = engineDefaults.get("colorMatch", 1.0)686 engineDefaults["opacityLimit"] = engineDefaults.get("opacityLimit", 0.0)687 engineDefaults["area"] = engineDefaults.get("area", (0.0, 0.0, 1.0, 1.0))688 engineDefaults["limit"] = engineDefaults.get("limit", -1)689 engineDefaults["allowOverlap"] = engineDefaults.get("allowOverlap", False)690 engineDefaults["scale"] = engineDefaults.get("scale", 1.0)691 engineDefaults["bitmapPixelSize"] = engineDefaults.get("bitmapPixelSize", 0)692 engineDefaults["screenshotPixelSize"] = engineDefaults.get("screenshotPixelSize", 0)693 OirEngine.__init__(self, *args, **engineDefaults)694 self._openedImages = {}695 self._findBitmapCache = {}696 def _addScreenshot(self, screenshot, **findBitmapDefaults):697 filename = screenshot.filename()698 self._openedImages[filename] = eye4graphics.openImage(filename)699 # make sure size() is available, this can save an extra700 # opening of the screenshot file.701 if screenshot.size(allowReadingFile=False) == None:702 screenshot.setSize(_e4gImageDimensions(self._openedImages[filename]))703 self._findBitmapCache[filename] = {}704 def _removeScreenshot(self, screenshot):705 filename = screenshot.filename()706 eye4graphics.closeImage(self._openedImages[filename])707 del self._openedImages[filename]708 del self._findBitmapCache[filename]709 def adjustParameters(self, screenshot, bitmap,710 scaleRange = [p/100.0 for p in range(110,210,10)],711 colorMatchRange = [p/100.0 for p in range(100,60,-10)],712 pixelSizeRange = range(2,5),713 resultCount = 1,714 **oirArgs):715 """716 Search for scale, colorMatch, bitmapPixelSize and717 screenshotPixelSize parameters that find the bitmap in the718 screenshot.719 Parameters:720 screenshot (Screenshot instance):721 screenshot that contains the bitmap.722 bitmap (string):723 bitmap filename.724 scaleRange (list of floats, optional):725 scales to go through.726 The default is: 1.1, 1.2, ... 2.0.727 colorMatchRange (list of floats, optional):728 colorMatches to try out.729 The default is: 1.0, 0.9, ... 0.7.730 pixelSizeRange (list of integers, optional):731 values for bitmapPixelSize and screenshotPixelSize.732 The default is: [2, 3]733 resultCount (integer, optional):734 number of parameter combinations to be found.735 The default is 1. 0 is unlimited.736 other OIR parameters: as usual, refer to engine documentation.737 Returns list of pairs: (GUIItem, findParams), where738 GUIItem is the detected item (GUIItem.bbox() is the box around it),739 and findParams is a dictionary containing the parameters.740 """741 if not screenshot.filename() in self._findBitmapCache:742 self.addScreenshot(screenshot)743 ssAdded = True744 else:745 ssAdded = False746 retval = []747 for colorMatch in colorMatchRange:748 for pixelSize in pixelSizeRange:749 for scale in scaleRange:750 findParams = oirArgs.copy()751 findParams.update({"colorMatch": colorMatch,752 "limit": 1,753 "scale": scale,754 "bitmapPixelSize": pixelSize,755 "screenshotPixelSize": pixelSize})756 results = self.findBitmap(screenshot, bitmap,757 **findParams)758 if results:759 retval.append((results[0], findParams))760 if len(retval) == resultCount:761 return retval762 if ssAdded:763 self.removeScreenshot(screenshot)764 return retval765 def _findBitmap(self, screenshot, bitmap, colorMatch=None,766 opacityLimit=None, area=None, limit=None,767 allowOverlap=None, scale=None,768 bitmapPixelSize=None, screenshotPixelSize=None):769 """770 Find items on the screenshot that match to bitmap.771 """772 ssFilename = screenshot.filename()773 ssSize = screenshot.size()774 cacheKey = (bitmap, colorMatch, opacityLimit, area, limit,775 scale, bitmapPixelSize, screenshotPixelSize)776 if cacheKey in self._findBitmapCache[ssFilename]:777 return self._findBitmapCache[ssFilename][cacheKey]778 self._findBitmapCache[ssFilename][cacheKey] = []779 e4gIcon = eye4graphics.openImage(bitmap)780 if e4gIcon == 0:781 raise IOError('Cannot open bitmap "%s".' % (bitmap,))782 matchCount = 0783 leftTopRightBottomZero = (_intCoords((area[0], area[1]), ssSize) +784 _intCoords((area[2], area[3]), ssSize) +785 (0,))786 struct_area_bbox = _Bbox(*leftTopRightBottomZero)787 struct_bbox = _Bbox(0, 0, 0, 0, 0)788 contOpts = 0 # search for the first hit789 try:790 xscale, yscale = scale791 except TypeError:792 xscale = yscale = float(scale)793 while True:794 if matchCount == limit: break795 result = eye4graphics.findNextIcon(796 ctypes.byref(struct_bbox),797 ctypes.c_void_p(self._openedImages[ssFilename]),798 ctypes.c_void_p(e4gIcon),799 0, # no fuzzy matching800 ctypes.c_double(colorMatch),801 ctypes.c_double(opacityLimit),802 ctypes.byref(struct_area_bbox),803 ctypes.c_int(contOpts),804 ctypes.c_float(xscale),805 ctypes.c_float(yscale),806 ctypes.c_int(bitmapPixelSize),807 ctypes.c_int(screenshotPixelSize))808 contOpts = 1 # search for the next hit809 if result < 0: break810 bbox = (int(struct_bbox.left), int(struct_bbox.top),811 int(struct_bbox.right), int(struct_bbox.bottom))812 addToFoundItems = True813 if allowOverlap == False:814 for guiItem in self._findBitmapCache[ssFilename][cacheKey]:815 itemLeft, itemTop, itemRight, itemBottom = guiItem.bbox()816 if ((itemLeft <= bbox[0] <= itemRight or itemLeft <= bbox[2] <= itemRight) and817 (itemTop <= bbox[1] <= itemBottom or itemTop <= bbox[3] <= itemBottom)):818 if ((itemLeft < bbox[0] < itemRight or itemLeft < bbox[2] < itemRight) or819 (itemTop < bbox[1] < itemBottom or itemTop < bbox[3] < itemBottom)):820 addToFoundItems = False821 break822 if addToFoundItems:823 self._findBitmapCache[ssFilename][cacheKey].append(824 GUIItem("bitmap", bbox, ssFilename, bitmap=bitmap))825 matchCount += 1826 eye4graphics.closeImage(e4gIcon)827 return self._findBitmapCache[ssFilename][cacheKey]828def _defaultOirEngine():829 if _g_defaultOirEngine:830 return _g_defaultOirEngine831 else:832 _Eye4GraphicsOirEngine().register(defaultOir=True)833 return _g_defaultOirEngine834class _OirRc(object):835 """Optical image recognition settings for a directory.836 Currently loaded from file .fmbtoirc in the directory.837 There is once _OirRc instance per directory.838 """839 _filename = ".fmbtoirrc"840 _cache = {}841 @classmethod842 def load(cls, directory):843 if directory in cls._cache:844 pass845 elif os.access(os.path.join(directory, cls._filename), os.R_OK):846 cls._cache[directory] = cls(directory)847 else:848 cls._cache[directory] = None849 return cls._cache[directory]850 def __init__(self, directory):851 self._key2value = {}852 curdir = "."853 self._dir2oirArgsList = {curdir: [{}]}854 for line in file(os.path.join(directory, _OirRc._filename)):855 line = line.strip()856 if line == "" or line[0] in "#;":857 continue858 elif line == "alternative":859 self._dir2oirArgsList[curdir].append({}) # new set of args860 self._key2value = {}861 elif "=" in line:862 key, value_str = line.split("=", 1)863 value_str = value_str.strip()864 if key.strip().lower() == "includedir":865 curdir = value_str866 self._dir2oirArgsList[curdir] = [{}]867 else:868 try: value = int(value_str)869 except ValueError:870 try: value = float(value_str)871 except ValueError:872 if value_str[0] in "([\"'": # tuple, list, string873 value = eval(value_str)874 else:875 value = value_str876 self._dir2oirArgsList[curdir][-1][key.strip()] = value877 def searchDirs(self):878 return self._dir2oirArgsList.keys()879 def oirArgsList(self, searchDir):880 return self._dir2oirArgsList[searchDir]881class _Paths(object):882 def __init__(self, bitmapPath, relativeRoot):883 self.bitmapPath = bitmapPath884 self.relativeRoot = relativeRoot885 self._oirAL = {} # OIR parameters for bitmaps886 self._abspath = {} # bitmap to abspath887 def abspath(self, bitmap, checkReadable=True):888 if bitmap in self._abspath:889 return self._abspath[bitmap]890 if bitmap.startswith("/"):891 path = [os.path.dirname(bitmap)]892 bitmap = os.path.basename(bitmap)893 else:894 path = []895 for singleDir in self.bitmapPath.split(":"):896 if not singleDir.startswith("/"):897 path.append(os.path.join(self.relativeRoot, singleDir))898 else:899 path.append(singleDir)900 for singleDir in path:901 retval = os.path.join(singleDir, bitmap)902 if not checkReadable or os.access(retval, os.R_OK):903 oirRc = _OirRc.load(singleDir)904 if oirRc:905 self._oirAL[retval] = oirRc.oirArgsList(".")906 else:907 self._oirAL[retval] = [{}]908 self._oirAL[bitmap] = self._oirAL[retval]909 break910 else:911 # bitmap is not in singleDir, but there might be .fmbtoirrc912 oirRc = _OirRc.load(singleDir)913 if oirRc:914 for d in oirRc.searchDirs():915 if d.startswith("/"):916 candidate = os.path.join(d, bitmap)917 else:918 candidate = os.path.join(singleDir, d, bitmap)919 if os.access(candidate, os.R_OK):920 self._oirAL[candidate] = oirRc.oirArgsList(d)921 self._oirAL[bitmap] = self._oirAL[candidate]922 retval = candidate923 break924 if checkReadable and not os.access(retval, os.R_OK):925 raise ValueError('Bitmap "%s" not readable in bitmapPath %s' % (bitmap, ':'.join(path)))926 self._abspath[bitmap] = retval927 return retval928 def oirArgsList(self, bitmap):929 """Returns list of alternative OIR parameters associated to the bitmap930 by appropriate .fmbtoirrc file931 """932 if bitmap in self._oirAL:933 return self._oirAL[bitmap]934 else:935 absBitmap = self.abspath(bitmap)936 if absBitmap in self._oirAL:937 return self._oirAL[absBitmap]938 else:939 return None940class GUITestInterface(object):941 def __init__(self, ocrEngine=None, oirEngine=None, rotateScreenshot=None):942 self._paths = _Paths("", "")943 self._conn = None944 self._lastScreenshot = None945 self._longPressHoldTime = 2.0946 self._longTapHoldTime = 2.0947 self._ocrEngine = None948 self._oirEngine = None949 self._rotateScreenshot = rotateScreenshot950 self._screenshotLimit = None951 self._screenshotRefCount = {} # filename -> Screenshot object ref count952 self._screenshotArchiveMethod = "resize"953 if ocrEngine == None:954 self.setOcrEngine(_defaultOcrEngine())955 else:956 if type(ocrEngine) == int:957 self.setOcrEngine(_g_ocrEngines[ocrEngine])958 else:959 self.setOcrEngine(ocrEngine)960 if oirEngine == None:961 self.setOirEngine(_defaultOirEngine())962 else:963 if type(oirEngine) == int:964 self.setOirEngine(_g_oirEngines[oirEngine])965 else:966 self.setOirEngine(oirEngine)967 self._screenshotDir = None968 self._screenshotDirDefault = "screenshots"969 self._screenshotSubdir = None970 self._screenshotSubdirDefault = ""971 self._screenSize = None972 self._visualLog = None973 self._visualLogFileObj = None974 self._visualLogFilenames = set()975 def bitmapPath(self):976 """977 Returns bitmapPath from which bitmaps are searched for.978 """979 return self._paths.bitmapPath980 def bitmapPathRoot(self):981 """982 Returns the path that prefixes all relative directories in983 bitmapPath.984 """985 return self._paths.relativeRoot986 def close(self):987 self._lastScreenshot = None988 if self._visualLog:989 if hasattr(self._visualLog._outFileObj, "name"):990 self._visualLogFilenames.remove(self._visualLog._outFileObj.name)991 self._visualLog.close()992 if self._visualLogFileObj:993 self._visualLogFileObj.close()994 self._visualLog = None995 def connection(self):996 """997 Returns GUITestConnection instance.998 """999 return self._conn1000 def drag(self, (x1, y1), (x2, y2), delayBetweenMoves=0.01, delayBeforeMoves=0, delayAfterMoves=0, movePoints=20):1001 """1002 Touch the screen on coordinates (x1, y1), drag along straight1003 line to coordinates (x2, y2), and raise fingertip.1004 coordinates (floats in range [0.0, 1.0] or integers):1005 floating point coordinates in range [0.0, 1.0] are1006 scaled to full screen width and height, others are1007 handled as absolute coordinate values.1008 delayBeforeMoves (float, optional):1009 seconds to wait after touching and before dragging.1010 If negative, starting touch event is not sent.1011 delayBetweenMoves (float, optional):1012 seconds to wait when moving between points when1013 dragging.1014 delayAfterMoves (float, optional):1015 seconds to wait after dragging, before raising1016 fingertip.1017 If negative, fingertip is not raised.1018 movePoints (integer, optional):1019 the number of intermediate move points between end1020 points of the line.1021 Returns True on success, False if sending input failed.1022 """1023 x1, y1 = self.intCoords((x1, y1))1024 x2, y2 = self.intCoords((x2, y2))1025 if delayBeforeMoves >= 0:1026 if not self._conn.sendTouchDown(x1, y1):1027 return False1028 if delayBeforeMoves > 0:1029 time.sleep(delayBeforeMoves)1030 else:1031 time.sleep(delayBetweenMoves)1032 for i in xrange(0, movePoints):1033 nx = x1 + int(round(((x2 - x1) / float(movePoints+1)) * (i+1)))1034 ny = y1 + int(round(((y2 - y1) / float(movePoints+1)) * (i+1)))1035 if not self._conn.sendTouchMove(nx, ny): return False1036 time.sleep(delayBetweenMoves)1037 if delayAfterMoves > 0:1038 self._conn.sendTouchMove(x2, y2)1039 time.sleep(delayAfterMoves)1040 if delayAfterMoves >= 0:1041 if self._conn.sendTouchUp(x2, y2):1042 return True1043 else:1044 return False1045 else:1046 return True1047 def enableVisualLog(self, filenameOrObj,1048 screenshotWidth="240", thumbnailWidth="",1049 timeFormat="%s.%f", delayedDrawing=False,1050 copyBitmapsToScreenshotDir=False):1051 """1052 Start writing visual HTML log on this device object.1053 Parameters:1054 filenameOrObj (string or a file object)1055 The file to which the log is written.1056 screenshotWidth (string, optional)1057 Width of screenshot images in HTML.1058 The default is "240".1059 thumbnailWidth (string, optional)1060 Width of thumbnail images in HTML.1061 The default is "", that is, original size.1062 timeFormat (string, optional)1063 Timestamp format. The default is "%s.%f".1064 Refer to strftime documentation.1065 delayedDrawing (boolean, optional)1066 If True, screenshots with highlighted icons, words1067 and gestures are not created during the1068 test. Instead, only shell commands are stored for1069 later execution. The value True can significantly1070 save test execution time and disk space. The default1071 is False.1072 copyBitmapsToScreenshotDir (boolean, optional)1073 If True, every logged bitmap file will be copied to1074 bitmaps directory in screenshotDir. The default is1075 False.1076 """1077 if type(filenameOrObj) == str:1078 try:1079 outFileObj = file(filenameOrObj, "w")1080 self._visualLogFileObj = outFileObj1081 except Exception, e:1082 _fmbtLog('Failed to open file "%s" for logging.' % (filenameOrObj,))1083 raise1084 else:1085 outFileObj = filenameOrObj1086 # someone else opened the file => someone else will close it1087 self._visualLogFileObj = None1088 if hasattr(outFileObj, "name"):1089 if outFileObj.name in self._visualLogFilenames:1090 raise ValueError('Visual logging on file "%s" is already enabled' % (outFileObj.name,))1091 else:1092 self._visualLogFilenames.add(outFileObj.name)1093 self._visualLog = _VisualLog(self, outFileObj, screenshotWidth,1094 thumbnailWidth, timeFormat, delayedDrawing,1095 copyBitmapsToScreenshotDir)1096 def visualLog(self, *args):1097 """Writes parameters to the visual log, given that visual logging is1098 enabled.1099 """1100 pass1101 def intCoords(self, (x, y)):1102 """1103 Convert floating point coordinate values in range [0.0, 1.0] to1104 screen coordinates.1105 """1106 width, height = self.screenSize()1107 return _intCoords((x, y), (width, height))1108 def ocrEngine(self):1109 """1110 Returns the OCR engine that is used by default for new1111 screenshots.1112 """1113 return self._ocrEngine1114 def oirEngine(self):1115 """1116 Returns the OIR engine that is used by default for new1117 screenshots.1118 """1119 return self._oirEngine1120 def pressKey(self, keyName, long=False, hold=0.0):1121 """1122 Press a key.1123 Parameters:1124 keyName (string):1125 the name of the key, like KEYCODE_HOME.1126 long (boolean, optional):1127 if True, press the key for long time.1128 hold (float, optional):1129 time in seconds to hold the key down.1130 """1131 if long and hold == 0.0:1132 hold = self._longPressHoldTime1133 if hold > 0.0:1134 try:1135 assert self._conn.sendKeyDown(keyName)1136 time.sleep(hold)1137 assert self._conn.sendKeyUp(keyName)1138 except AssertionError:1139 return False1140 return True1141 return self._conn.sendPress(keyName)1142 def _newScreenshotFilepath(self):1143 """1144 Returns path and filename for next screenshot file.1145 Makes sure the file can be written (necessary directory1146 structure exists).1147 """1148 t = datetime.datetime.now()1149 filename = _filenameTimestamp(t) + "-" + self._conn.target() + ".png"1150 filepath = os.path.join(self.screenshotDir(),1151 t.strftime(self.screenshotSubdir()),1152 filename)1153 necessaryDirs = os.path.dirname(filepath)1154 if necessaryDirs and not os.path.isdir(necessaryDirs):1155 try:1156 os.makedirs(necessaryDirs)1157 except Exception, e:1158 _fmbtLog('creating directory "%s" for screenshots failed: %s' %1159 (necessaryDirs, e))1160 raise1161 return filepath1162 def _archiveScreenshot(self, filepath):1163 if self._screenshotArchiveMethod == "remove":1164 try:1165 os.remove(filepath)1166 except IOError:1167 pass1168 elif self._screenshotArchiveMethod.startswith("resize"):1169 if self._screenshotArchiveMethod == "resize":1170 convertArgs = ["-resize",1171 "%sx" % (int(self.screenSize()[0]) / 4,)]1172 else:1173 widthHeight = self._screenshotArchiveMethod.split()[1]1174 convertArgs = ["-resize", widthHeight]1175 subprocess.call(["convert", filepath] + convertArgs + [filepath])1176 def _archiveScreenshots(self):1177 """1178 Archive screenshot files if screenshotLimit has been exceeded.1179 """1180 freeScreenshots = [filename1181 for (filename, refCount) in self._screenshotRefCount.iteritems()1182 if refCount == 0]1183 archiveCount = len(freeScreenshots) - self._screenshotLimit1184 if archiveCount > 0:1185 freeScreenshots.sort(reverse=True) # archive oldest1186 while archiveCount > 0:1187 toBeArchived = freeScreenshots.pop()1188 try:1189 self._archiveScreenshot(toBeArchived)1190 except IOError:1191 pass1192 del self._screenshotRefCount[toBeArchived]1193 archiveCount -= 11194 def refreshScreenshot(self, forcedScreenshot=None, rotate=None):1195 """1196 Takes new screenshot and updates the latest screenshot object.1197 Parameters:1198 forcedScreenshot (Screenshot or string, optional):1199 use given screenshot object or image file, do not1200 take new screenshot.1201 rotate (integer, optional):1202 rotate screenshot by given number of degrees. This1203 overrides constructor rotateScreenshot parameter1204 value. The default is None (no override).1205 Returns Screenshot object, and makes the same object "the1206 latest screenshot" that is used by all *Bitmap and *OcrText1207 methods.1208 """1209 if forcedScreenshot != None:1210 if type(forcedScreenshot) == str:1211 self._lastScreenshot = Screenshot(1212 screenshotFile=forcedScreenshot,1213 paths = self._paths,1214 ocrEngine=self._ocrEngine,1215 oirEngine=self._oirEngine,1216 screenshotRefCount=self._screenshotRefCount)1217 else:1218 self._lastScreenshot = forcedScreenshot1219 else:1220 if self.screenshotDir() == None:1221 self.setScreenshotDir(self._screenshotDirDefault)1222 if self.screenshotSubdir() == None:1223 self.setScreenshotSubdir(self._screenshotSubdirDefault)1224 screenshotFile = self._newScreenshotFilepath()1225 if self._conn.recvScreenshot(screenshotFile):1226 # New screenshot successfully received from device1227 if rotate == None:1228 rotate = self._rotateScreenshot1229 if rotate != None and rotate != 0:1230 subprocess.call(["convert", screenshotFile, "-rotate", str(rotate), screenshotFile])1231 self._lastScreenshot = Screenshot(1232 screenshotFile=screenshotFile,1233 paths = self._paths,1234 ocrEngine=self._ocrEngine,1235 oirEngine=self._oirEngine,1236 screenshotRefCount=self._screenshotRefCount)1237 else:1238 self._lastScreenshot = None1239 # Make sure unreachable Screenshot instances are released from1240 # memory.1241 gc.collect()1242 for obj in gc.garbage:1243 if isinstance(obj, Screenshot):1244 if hasattr(obj, "_logCallReturnValue"):1245 # Some methods have been wrapped by visual1246 # log. Break reference cycles to let gc collect1247 # them.1248 del obj.findItemsByBitmap1249 del obj.findItemsByOcr1250 del gc.garbage[:]1251 gc.collect()1252 # If screenshotLimit has been set, archive old screenshot1253 # stored on the disk.1254 if self._screenshotLimit != None and self._screenshotLimit >= 0:1255 self._archiveScreenshots()1256 return self._lastScreenshot1257 def screenshot(self):1258 """1259 Returns the latest Screenshot object.1260 Use refreshScreenshot() to get a new screenshot.1261 """1262 return self._lastScreenshot1263 def screenshotArchiveMethod(self):1264 """1265 Returns how screenshots exceeding screenshotLimit are archived.1266 """1267 return self._screenshotArchiveMethod1268 def screenshotDir(self):1269 """1270 Returns the directory under which new screenshots are saved.1271 """1272 return self._screenshotDir1273 def screenshotLimit(self):1274 """1275 Returns the limit after which unused screenshots are archived.1276 """1277 return self._screenshotLimit1278 def screenshotSubdir(self):1279 """1280 Returns the subdirectory in screenshotDir under which new1281 screenshots are stored.1282 """1283 return self._screenshotSubdir1284 def screenSize(self):1285 """1286 Returns screen size in pixels in tuple (width, height).1287 """1288 if self._screenSize == None:1289 if self._lastScreenshot == None:1290 self.refreshScreenshot()1291 self._screenSize = self._lastScreenshot.size()1292 self._lastScreenshot = None1293 else:1294 self._screenSize = self._lastScreenshot.size()1295 return self._screenSize1296 def setBitmapPath(self, bitmapPath, rootForRelativePaths=None):1297 """1298 Set new path for finding bitmaps.1299 Parameters:1300 bitmapPath (string)1301 colon-separated list of directories from which1302 bitmap methods look for bitmap files.1303 rootForRelativePaths (string, optional)1304 path that will prefix all relative paths in1305 bitmapPath.1306 Example:1307 gui.setBitmapPath("bitmaps:icons:/tmp", "/home/X")1308 gui.tapBitmap("start.png")1309 will look for /home/X/bitmaps/start.png,1310 /home/X/icons/start.png and /tmp/start.png, in this order.1311 """1312 self._paths.bitmapPath = bitmapPath1313 if rootForRelativePaths != None:1314 self._paths.relativeRoot = rootForRelativePaths1315 def setConnection(self, conn):1316 """1317 Set the connection object that performs actions on real target.1318 Parameters:1319 conn (GUITestConnection instance):1320 The connection to be used.1321 """...

Full Screen

Full Screen

ivi_apps.py

Source:ivi_apps.py Github

copy

Full Screen

...60 self.dev_display = "%sx%s" % (self.maxX, self.maxY)61 bitmap_path = "/usr/lib/ivi-tests_pics/" + self.dev_display +"/" + ivi_args.ui + "/"62 print "++ using bitmap path: " + bitmap_path63 #self.enableVisualLog("ivi_apps.html", copyBitmapsToScreenshotDir=True)64 self.setBitmapPath(bitmap_path)65 def eventPlayback(self, ev_script, wait_time=1):66 cmd = "ev_playback /usr/lib/event_scripts/%s/%s" \67 % (self.dev_display, ev_script)68 print "++ run device cmd: " + cmd69 (ret, so, se) = self.shellSOE(cmd)70 if ret != 0:71 print "++ fail to playback event"72 print "++ standard output: " + so 73 print "++ standard error:" + se74 time.sleep(wait_time)75 return ret76 def swipeToEast(self, wait_time=1):77 print "++ swipe to the east"78 ret = self.swipe((0.5,0.5), direction="e")...

Full Screen

Full Screen

pages.py

Source:pages.py Github

copy

Full Screen

...6OPNRO = ":246248" # Käsiteltävän Xephyr näytön tunnus, muuta tähän omasi7DELAY = 1 # Komennon jälkeen odotettava aika sekunneissa8# luodaan olio jonka läpi voidaan käsitellä testikohdetta näytöllä9s = fmbtx11.Screen(OPNRO)10s.setBitmapPath('kuvat')11class PagesTest(unittest.TestCase):12 def setUp(self):13 s.refreshScreenshot()14 def tearDown(self):15 s.tapBitmap("seur.png", colorMatch=0.5)16 sleep(DELAY)17 s.refreshScreenshot()18 def test_moveToPage2(self):19 s.tapBitmap("input-username.png", colorMatch=0.9)20 sleep(DELAY)21 s.refreshScreenshot()22 found = s.verifyBitmap("kuvas6.png", colorMatch=0.9)23 self.assertTrue(found, "Header2 not found")24if __name__ == '__main__':...

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run fMBT automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful