Best Python code snippet using fMBT_python
fmbtandroid.py
Source:fmbtandroid.py  
...617    def topApp(self):618        """619        Returns the name of the top application.620        """621        return self._conn.recvTopAppWindow()[0]622    def topWindow(self):623        """624        Returns the name of the top window.625        """626        # the top window may be None during transitions, therefore627        # retry a couple of times if necessary.628        timeout = 0.5629        pollDelay = 0.2630        start = time.time()631        tw = self._conn.recvTopAppWindow()[1]632        while tw == None and (time.time() - start < timeout):633            time.sleep(pollDelay)634            tw = self._conn.recvTopAppWindow()[1]635        return tw636    def verifyText(self, text, partial=False):637        """638        Verify that the last view has at least one item with given639        text.640        Parameters:641          text (string):642                  text to be searched for in items.643          partial (boolean, optional):644                  if True, match items if item text contains given645                  text, otherwise match only if item text is equal to646                  the given text. The default is False (exact match).647        """648        assert self._lastView != None, "View required."649        return self._lastView.findItemsByText(text, partial=partial, count=1) != []650    def view(self):651        """652        Returns the last view (the most recently refreshed view).653        """654        return self._lastView655    def waitText(self, text, partial=False, **waitKwArgs):656        """657        Wait until text appears in any view item.658        Parameters:659          text (string):660                text to be waited for.661          partial (boolean, optional):662                refer to verifyText. The default is False.663          waitTime, pollDelay (float, optional):664                refer to wait.665        Returns True if text appeared within given time limit,666        otherwise False.667        Updates the last view.668        """669        return self.wait(self.refreshView,670                         self.verifyText, (text,), {'partial': partial},671                         **waitKwArgs)672    def wake(self):673        """674        Force the device to wake up.675        """676        return self._conn.sendWake()677    def _loadDeviceAndTestINIs(self, homeDir, deviceName, iniFile):678        if deviceName != None:679            _deviceIniFilename = homeDir + os.sep + "etc" + os.sep + deviceName + ".ini"680            self.loadConfig(_deviceIniFilename, override=True, level="device")681        if iniFile:682            self.loadConfig(iniFile, override=True, level="test")683class Ini:684    """685    Container for device configuration loaded from INI files.686    INI file syntax:687    [section1]688    key1 = value1689    ; commented = out690    # commented = out691    """692    def __init__(self, iniFile=None):693        """694        Initialise the container, optionally with an initial configuration.695        Parameters:696          iniFile (file object, optional):697                  load the initial configuration from iniFile.698                  The default is None: start with empty configuration.699        """700        # _conf is a dictionary:701        # (section, key) -> value702        self._conf = {}703        if iniFile:704            self.addFile(iniFile)705    def addFile(self, iniFile, override=True):706        """707        Add values from a file to the current configuration.708        Parameters:709          iniFile (file object):710                  load values from this file object.711          override (boolean, optional):712                  If True, loaded values override existing values.713                  Otherwise, only currently undefined values are714                  loaded. The default is True.715        """716        for line in iniFile:717            line = line.strip()718            if line.startswith('[') and line.endswith(']'):719                section = line[1:-1].strip()720            elif line.startswith(";") or line.startswith("#"):721                continue722            elif '=' in line:723                key, value = line.split('=', 1)724                if override or (section, key.strip()) not in self._conf:725                    self._conf[(section, key.strip())] = value.strip()726    def sections(self):727        """728        Returns list of sections in the current configuration.729        """730        return list(set([k[0] for k in self._conf.keys()]))731    def keys(self, section):732        """733        Returns list of keys in a section in the current configuration.734        Parameters:735          section (string):736                  the name of the section.737        """738        return [k[1] for k in self._conf.keys() if k[0] == section]739    def dump(self):740        """741        Returns the current configuration as a single string in the742        INI format.743        """744        lines = []745        for section in sorted(self.sections()):746            lines.append("[%s]" % (section,))747            for key in sorted(self.keys(section)):748                lines.append("%-16s = %s" % (key, self._conf[(section, key)]))749            lines.append("")750        return "\n".join(lines)751    def set(self, section, key, value):752        """753        Set new value for a key in a section.754        Parameters:755          section, key (strings):756                  the section, the key.757          value (string):758                  the new value. If not string already, it will be759                  converted to string, and it will be loaded as a760                  string when loaded from file object.761        """762        self._conf[(section, key)] = str(value)763    def value(self, section, key, default=""):764        """765        Returns the value (string) associated with a key in a section.766        Parameters:767          section, key (strings):768                  the section and the key.769          default (string, optional):770                  the default value to be used and stored if there is771                  no value associated to the key in the section. The772                  default is the empty string.773        Reading a value of an undefined key in an undefined section774        adds the key and the section to the configuration with the775        returned (the default) value. This makes all returned values776        visible in dump().777        """778        if not (section, key) in self._conf:779            self._conf[(section, key)] = default780        return self._conf[(section, key)]781# For backward compatibility, someone might be using old _DeviceConf782_DeviceConf = Ini783class ViewItem(fmbtgti.GUIItem):784    """785    ViewItem holds the information of a single GUI element.786    """787    def __init__(self, className, code, indent, properties, parent, rawProps, dumpFilename, displayToScreen):788        self._p = properties789        self._parent = parent790        self._className = className791        self._code = code792        self._indent = indent793        self._children = []794        self._rawProps = ""795        if not "scrolling:mScrollX" in self._p:796            self._p["scrolling:mScrollX"] = 0797            self._p["scrolling:mScrollY"] = 0798        fmbtgti.GUIItem.__init__(self, className, self._calculateBbox(displayToScreen), dumpFilename)799    def addChild(self, child): self._children.append(child)800    def _calculateBbox(self, displayToScreen):801        left = int(self._p["layout:mLeft"])802        top = int(self._p["layout:mTop"])803        parent = self._parent804        while parent:805            pp = parent._p806            left += int(pp["layout:mLeft"]) - int(pp["scrolling:mScrollX"])807            top += int(pp["layout:mTop"]) - int(pp["scrolling:mScrollY"])808            parent = parent._parent809        height = int(self._p["layout:getHeight()"])810        width = int(self._p["layout:getWidth()"])811        screenLeft, screenTop = displayToScreen(left, top)812        screenRight, screenBottom = displayToScreen(left + width, top + height)813        return (screenLeft, screenTop, screenRight, screenBottom)814    def children(self):   return self._children815    def className(self):  return self._className816    def code(self):       return self._code817    def indent(self):     return self._indent818    def id(self):         return self.property("mID")819    def parent(self):     return self._parent820    def properties(self): return self._p821    def property(self, propertyName):822        return self._p.get(propertyName, None)823    def text(self):       return self.property("text:mText")824    def visible(self):825        return self._p.get("getVisibility()", "") == "VISIBLE"826    def dump(self):827        p = self._p828        return ("ViewItem(\n\tchildren = %d\n\tclassName = '%s'\n\tcode = '%s'\n\t" +829                "indent = %d\n\tproperties = {\n\t\t%s\n\t})") % (830            len(self._children), self._className, self._code, self._indent,831            '\n\t\t'.join(['"%s": %s' % (key, p[key]) for key in sorted(p.keys())]))832    def __str__(self):833        return ("ViewItem(className='%s', id=%s, bbox=%s)"  % (834                self._className, self.id(), self.bbox()))835class View(object):836    """837    View provides interface to screen dumps from Android. It parses838    the dump to a hierarchy of ViewItems. find* methods enable searching839    for ViewItems based on their properties.840    """841    def __init__(self, screenshotDir, serialNumber, dump, displayToScreen=None):842        self.screenshotDir = screenshotDir843        self.serialNumber = serialNumber844        self._viewItems = []845        self._errors = []846        self._lineRegEx = re.compile("(?P<indent>\s*)(?P<class>[\w.$]+)@(?P<id>[0-9A-Fa-f]{8} )(?P<properties>.*)")847        self._olderAndroidLineRegEx = re.compile("(?P<indent>\s*)(?P<class>[\w.$]+)@(?P<id>\w)(?P<properties>.*)")848        self._propRegEx = re.compile("(?P<prop>(?P<name>[^=]+)=(?P<len>\d+),)(?P<data>[^\s]* ?)")849        self._dump = dump850        self._rawDumpFilename = self.screenshotDir + os.sep + fmbtgti._filenameTimestamp() + "-" + self.serialNumber + ".view"851        file(self._rawDumpFilename, "w").write(self._dump)852        if displayToScreen == None:853            displayToScreen = lambda x, y: (x, y)854        try: self._parseDump(dump, self._rawDumpFilename, displayToScreen)855        except Exception, e:856            self._errors.append((-1, "", "Parser error"))857    def viewItems(self): return self._viewItems858    def errors(self): return self._errors859    def dumpRaw(self): return self._dump860    def dumpItems(self, itemList = None):861        if itemList == None: itemList = self._viewItems862        l = []863        for i in itemList:864            l.append(self._dumpItem(i))865        return '\n'.join(l)866    def dumpTree(self, rootItem = None):867        l = []868        if rootItem != None:869            l.extend(self._dumpSubTree(rootItem, 0))870        else:871            for i in self._viewItems:872                if i._indent == 0:873                    l.extend(self._dumpSubTree(i, 0))874        return '\n'.join(l)875    def _dumpSubTree(self, viewItem, indent):876        l = []877        i = viewItem878        l.append(" "*indent + self._dumpItem(viewItem))879        for i in viewItem.children():880            l.extend(self._dumpSubTree(i, indent + 4))881        return l882    def _dumpItem(self, viewItem):883        i = viewItem884        if i.text() != None: t = '"%s"' % (i.text(),)885        else: t = None886        return "id=%s cls=%s text=%s bbox=%s" % (887            i.id(), i.className(), t, i.bbox())888    def findItems(self, comparator, count=-1, searchRootItem=None, searchItems=None):889        foundItems = []890        if count == 0: return foundItems891        if searchRootItem != None:892            # find from searchRootItem and its children893            if comparator(searchRootItem):894                foundItems.append(searchRootItem)895            for c in searchRootItem.children():896                foundItems.extend(self.findItems(comparator, count=count-len(foundItems), searchRootItem=c))897        else:898            if searchItems != None:899                # find from listed items only900                searchDomain = searchItems901            else:902                # find from all items903                searchDomain = self._viewItems904            for i in searchDomain:905                if comparator(i):906                    foundItems.append(i)907                    if count > 0 and len(foundItems) >= count:908                        break909        return foundItems910    def findItemsByText(self, text, partial=False, count=-1, searchRootItem=None, searchItems=None):911        """912        Searches the GUI hiearhy for a object with a given text913        """914        if partial:915            c = lambda item: (916                item.properties().get("text:mText", "").find(text) != -1 )917        else:918            c = lambda item: (919                item.properties().get("text:mText", None) == text )920        return self.findItems(c, count=count, searchRootItem=searchRootItem, searchItems=searchItems)921    def findItemsById(self, id, count=-1, searchRootItem=None, searchItems=None):922        c = lambda item: item.properties().get("mID", "") == id923        return self.findItems(c, count=count, searchRootItem=searchRootItem, searchItems=searchItems)924    def findItemsByClass(self, className, partial=True, count=-1, searchRootItem=None, searchItems=None):925        if partial: c = lambda item: item.className().find(className) != -1926        else: c = lambda item: item.className() == className927        return self.findItems(c, count=count, searchRootItem=searchRootItem, searchItems=searchItems)928    def findItemsByIdAndClass(self, id, className, partial=True, count=-1, searchRootItem=None, searchItems=None):929        idOk = self.findItemsById(id, count=-1, searchRootItem=searchRootItem)930        return self.findItemsByClass(className, partial=partial, count=count, searchItems=idOk)931    def findItemsByRawProps(self, s, count=-1, searchRootItem=None, searchItems=None):932        c = lambda item: item._rawProps.find(s) != -1933        return self.findItems(c, count=count, searchRootItem=searchRootItem, searchItems=searchItems)934    def save(self, fileOrDirName):935        shutil.copy(self._rawDumpFilename, fileOrDirName)936    def _parseDump(self, dump, rawDumpFilename, displayToScreen):937        """938        Process the raw dump data and create a tree of ViewItems939        """940        # This code originates from tema-android-adapter-3.2,941        # AndroidAdapter/guireader.py.942        self._viewItems = []943        cellLayout = ""944        parent = None945        previousItem = None946        currentIndent = 0947        visible = True948        self.TOP_PAGED_VIEW = ""949        for lineIndex, line in enumerate(dump.splitlines()):950            if line == "DONE.":951                break952            # separate indent, class and properties for each GUI object953            # TODO: branch here according to self._androidVersion954            matcher = self._lineRegEx.match(line)955            if not matcher:956                # FIXME: this hack falls back to old format,957                # should branch according to self._androidVersion!958                matcher = self._olderAndroidLineRegEx.match(line)959                if not matcher:960                    self._errors.append((lineIndex + 1, line, "Illegal line"))961                    continue # skip this line962            className = matcher.group("class")963            # Indent specifies the hierarchy level of the object964            indent = len(matcher.group("indent"))965            # If the indent is bigger that previous, this object is a966            # child for the previous object967            if indent > currentIndent:968                parent = self._viewItems[-1]969            elif indent < currentIndent:970                for tmp in range(0, currentIndent - indent):971                    parent = parent.parent()972            currentIndent = indent973            propertiesData = matcher.group("properties")974            properties = {}975            index = 0976            x = 0977            y = 0978            # Process the properties of each GUI object979            while index < len(propertiesData):980                # Separate name and value for each property [^=]*=981                propMatch = self._propRegEx.match(propertiesData[index:-1])982                if not propMatch or len(propMatch.group("data")) < int(propMatch.group("len")):983                    if not propMatch.group("data"):984                        self._errors.append((lineIndex, propertiesData[index:-1], "Illegal property"))985                        return None986                    startFrom = index + propertiesData[index:-1].find(propMatch.group("data"))987                    currFixedData = propertiesData[startFrom:(startFrom + int(propMatch.group("len")))]988                    length = int(propMatch.group("len"))989                    # [^=]+=?, == data990                    properties[propMatch.group("name")] = currFixedData[0:length].lstrip()991                else:992                    length = int(propMatch.group("len"))993                    # [^=]+=?, == data994                    properties[propMatch.group("name")] = propMatch.group("data")[0:length].lstrip()995                index += len(propMatch.group("prop")) + length + 1996            self._viewItems.append(ViewItem(matcher.group("class"), matcher.group("id"), indent, properties, parent, matcher.group("properties"), self._rawDumpFilename, displayToScreen))997            if parent:998                parent.addChild(self._viewItems[-1])999        return self._viewItems1000    def __str__(self):1001        return 'View(items=%s, dump="%s")' % (1002            len(self._viewItems), self._rawDumpFilename)1003class _AndroidDeviceConnection:1004    """1005    Connection to the Android Device being tested.1006    """1007    _m_host = 'localhost'1008    _m_port = random.randint(20000, 29999)1009    _w_host = 'localhost'1010    _w_port = _m_port + 11011    def __init__(self, serialNumber, stopOnError=True):1012        self._serialNumber = serialNumber1013        self._stopOnError = stopOnError1014        self._shellSupportsTar = False1015        self.setScreenToDisplayCoords(lambda x, y: (x, y))1016        self.setDisplayToScreenCoords(lambda x, y: (x, y))1017        self._detectFeatures()1018        try:1019            self._resetMonkey()1020            self._resetWindow()1021        finally:1022            # Next _AndroidDeviceConnection instance will use different ports1023            self._w_port = _AndroidDeviceConnection._w_port1024            self._m_port = _AndroidDeviceConnection._m_port1025            _AndroidDeviceConnection._w_port += 1001026            _AndroidDeviceConnection._m_port += 1001027    def __del__(self):1028        try: self._monkeySocket.close()1029        except: pass1030    def target(self):1031        return self._serialNumber1032    def _cat(self, remoteFilename):1033        fd, filename = tempfile.mkstemp("fmbtandroid-cat-")1034        os.close(fd)1035        self._runAdb(["pull", remoteFilename, filename], 0)1036        contents = file(filename).read()1037        os.remove(filename)1038        return contents1039    def _runAdb(self, command, expectedExitStatus=0, timeout=None):1040        if not self._stopOnError:1041            expect = None1042        else:1043            expect = expectedExitStatus1044        if type(command) == list:1045            command = ["adb", "-s", self._serialNumber] + command1046        else:1047            command = ["adb", "-s", self._serialNumber, command]1048        return _run(command, expectedExitStatus=expect, timeout=timeout)1049    def _runSetupCmd(self, cmd, expectedExitStatus = 0):1050        _adapterLog('setting up connections: "%s"' % (cmd,))1051        try:1052            self._runAdb(cmd, expectedExitStatus)1053        except (FMBTAndroidRunError, AndroidDeviceNotFound), e:1054            _adapterLog("connection setup problem: %s" % (e,))1055            return False1056        return True1057    def _detectFeatures(self):1058        # check supported features1059        outputLines = self._runAdb(["shell", "id"])[1].splitlines()1060        if len(outputLines) == 1 and "uid=0" in outputLines[0]:1061            self._shellUid0 = True1062        else:1063            self._shellUid0 = False1064        outputLines = self._runAdb(["shell", "su", "root", "id"])[1].splitlines()1065        if len(outputLines) == 1 and "uid=0" in outputLines[0]:1066            self._shellSupportsSu = True1067        else:1068            self._shellSupportsSu = False1069        outputLines = self._runAdb(["shell", "tar"])[1].splitlines()1070        if len(outputLines) == 1 and "bin" in outputLines[0]:1071            self._shellSupportsTar = False1072        else:1073            self._shellSupportsTar = True1074    def _resetWindow(self):1075        setupCommands = [["shell", "service" , "call", "window", "1", "i32", "4939"],1076                         ["forward", "tcp:"+str(self._w_port), "tcp:4939"]]1077        for c in setupCommands:1078            self._runSetupCmd(c)1079    def _resetMonkey(self, timeout=3, pollDelay=.25):1080        tryKillingMonkeyOnFailure = 11081        failureCountSinceKill = 01082        endTime = time.time() + timeout1083        if self._shellUid0:1084            monkeyLaunch = ["monkey"]1085        elif self._shellSupportsSu:1086            monkeyLaunch = ["su", "root", "monkey"]1087        else:1088            monkeyLaunch = ["monkey"]1089        while time.time() < endTime:1090            if not self._runSetupCmd(["shell"] + monkeyLaunch + ["--port", "1080"], None):1091                time.sleep(pollDelay)1092                failureCountSinceKill += 11093                continue1094            time.sleep(pollDelay)1095            if not self._runSetupCmd(["forward", "tcp:"+str(self._m_port), "tcp:1080"]):1096                time.sleep(pollDelay)1097                failureCountSinceKill += 11098                continue1099            try:1100                self._monkeySocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)1101                self._monkeySocket.connect((self._m_host, self._m_port))1102                self._monkeySocket.setblocking(0)1103                self._monkeySocket.settimeout(1.0)1104                self._platformVersion = self._monkeyCommand("getvar build.version.release", retry=0)[1]1105                if len(self._platformVersion) > 0:1106                    self._monkeySocket.settimeout(5.0)1107                    return True1108            except Exception, e:1109                failureCountSinceKill += 11110            time.sleep(pollDelay)1111            if failureCountSinceKill > 2 and tryKillingMonkeyOnFailure > 0:1112                if self._shellSupportsSu:1113                    self._runSetupCmd(["shell", "su", "root", "pkill", "monkey"])1114                else:1115                    self._runSetupCmd(["shell", "pkill", "monkey"])1116                tryKillingMonkeyOnFailure -= 11117                failureCountSinceKill = 01118                time.sleep(pollDelay)1119        if self._stopOnError:1120            msg = 'Android monkey error: cannot connect to "adb shell monkey --port 1080" to device %s' % (self._serialNumber)1121            _adapterLog(msg)1122            raise AndroidConnectionError(msg)1123        else:1124            return False1125    def _monkeyCommand(self, command, retry=3):1126        try:1127            self._monkeySocket.sendall(command + "\n")1128            data = self._monkeySocket.recv(4096).strip()1129            if len(data) == 0 and retry > 0:1130                return self._monkeyCommand(command, retry-1)1131            if data == "OK":1132                return True, None1133            elif data.startswith("OK:"):1134                return True, data.split("OK:")[1]1135            _adapterLog("monkeyCommand failing... command: '%s' response: '%s'" % (command, data))1136            return False, None1137        except socket.error:1138            try: self._monkeySocket.close()1139            except: pass1140            if retry > 0:1141                self._resetMonkey()1142                return self._monkeyCommand(command, retry=retry-1)1143            else:1144                raise AndroidConnectionError('Android monkey socket connection lost while sending command "%s"' % (command,))1145    def reboot(self, reconnect, firstBootAfterFlashing, timeout):1146        if firstBootAfterFlashing:1147            self._runAdb("root")1148            time.sleep(2)1149            self._runAdb(["shell", "rm", "/data/data/com.android.launcher/shared_prefs/com.android.launcher2.prefs.xml"])1150        self._runAdb("reboot")1151        _adapterLog("rebooting " + self._serialNumber)1152        if reconnect:1153            time.sleep(2)1154            endTime = time.time() + timeout1155            status, _, _ = self._runAdb("wait-for-device", expectedExitStatus=None, timeout=timeout)1156            if status != 0:1157                raise AndroidDeviceNotFound('"timeout %s adb wait-for-device" status %s' % (timeout, status))1158            self._detectFeatures()1159            while time.time() < endTime:1160                try:1161                    if self._resetMonkey(timeout=1, pollDelay=1):1162                        break1163                except AndroidConnectionError:1164                    pass1165                time.sleep(1)1166            else:1167                msg = "reboot: reconnecting to " + self._serialNumber + " failed"1168                _adapterLog(msg)1169                raise AndroidConnectionError(msg)1170            self._resetWindow()1171        return True1172    def recvVariable(self, variableName):1173        ok, value = self._monkeyCommand("getvar " + variableName)1174        if ok: return value1175        else:1176            # LOG: getvar variableName failed1177            return None1178    def recvScreenSize(self):1179        try:1180            height = int(self.recvVariable("display.height"))1181            width = int(self.recvVariable("display.width"))1182        except TypeError:1183            return None, None1184        return width, height1185    def recvTopAppWindow(self):1186        _, output, _ = self._runAdb(["shell", "dumpsys", "window"], 0)1187        if self._platformVersion >= "4.2":1188            s = re.findall("mCurrentFocus=Window\{(#?[0-9A-Fa-f]{8})( [^ ]*)? (?P<winName>[^}]*)\}", output)1189        else:1190            s = re.findall("mCurrentFocus=Window\{(#?[0-9A-Fa-f]{8}) (?P<winName>[^ ]*) [^ ]*\}", output)1191        if s and len(s[-1][-1].strip()) > 1:1192            topWindowName = s[-1][-1]1193            if len(s) > 0:1194                _adapterLog('recvTopAppWindow warning: several mCurrentFocus windows: "%s"'1195                            % ('", "'.join([w[-1] for w in s]),))1196        else: topWindowName = None1197        s = re.findall("mFocusedApp=AppWindowToken.*ActivityRecord\{#?[0-9A-Fa-f]{8}( [^ ]*)? (?P<appName>[^}]*)\}", output)1198        if s and len(s[0][-1].strip()) > 1:1199            topAppName = s[0][-1].strip()...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.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
