def wait_for_match(self, message, obj, prop_name, expected, timeout=10, interval=0.5): '''每隔interval检查obj.prop_name是否和正则表达式expected是否匹配,如果在timeout时间内都不相等,则测试用例失败 :param message: 失败时的输出信息 :param obj: 需要检查的对象 :type prop_name: string :param prop_name: 需要检查的对象的属性名, obj.prop_name返回字符串 :param expected: 需要匹配的正则表达式 :param timeout: 超时秒数 :param interval: 重试间隔秒数 :return: True or False ''' tout = Timeout(timeout, interval) try: tout.waitObjectProperty(obj, prop_name, expected, regularMatch=True) return True except TimeoutError: self.__record_assert_failed(message, getattr(obj, prop_name), expected) return False
def start_simulator(self, udid=None): #检查模拟器是否启动成功 def check_started(): for s in self.get_simulators(): if s["state"] == "Booted" and (s["udid"] == udid or udid is None): return True return False if check_started(): return True simulator = "Simulator" if self.compare_xcode_version("7.0") < 0: simulator = "iOS Simulator" if udid: cmd = [self.fbsimctl, udid, 'boot'] if self.compare_xcode_version("9.0") >= 0: cmd = ['xcrun', 'simctl', 'boot', udid] else: cmd = "open -a \"%s\"" % simulator if self.compare_xcode_version("9.3") >=0: ret = subprocess.call(cmd, close_fds=True) if ret != 0: result = False else: result = Timeout(20, 0.05).check(check_started, True) else: with Flock(): self._modify_wi_port(udid) ret = subprocess.call(cmd, close_fds=True) if ret != 0: result = False else: result = Timeout(20, 0.05).check(check_started, True) return result
def waitForQuit(self, timeout=10, interval=0.5): """在指定的时间内等待退出 :return: 如果在指定的时间内退出,返回True;否则返回False """ if not self.Live: return True try: Timeout(timeout, interval).waitObjectProperty(self, "Live", False) except TimeoutError: return False return True
def waitForValue(self, prop_name, prop_value, timeout=10, interval=0.5, regularMatch=False): """等待控件属性值出现, 如果属性为字符串类型,则使用正则匹配 :param prop_name: 属性名字 :param prop_value: 等待出现的属性值 :param timeout: 超时秒数, 默认为10 :param interval: 等待间隔,默认为0.5 :param regularMatch: 参数 property_name和waited_value是否采用正则表达式的比较。默认为不采用(False)正则,而是采用恒等比较。 """ Timeout(timeout, interval).waitObjectProperty(self, prop_name, prop_value, regularMatch)
def __init__(self, timeout=1.8, interval=0.005): BaseTimeout.__init__(self, timeout, interval) self.timeout = float(timeout) self.interval = float(interval)
class Control(object): ''' 控件基类 ''' _timeout = Timeout(5, 0.5) #控件查找timeout时间 def __init__(self): pass @property def Children(self): '''返回此控件的子控件。需要在子类中实现。 ''' raise NotImplementedError("请在%s类中实Children属性" % type(self)) # @staticmethod # def exist(locator, root=None, timeout=10, interval=0.5): # '''在timeout时间内检查控件,返回找到的控件个数。 # # :type locator: QPath # :param locator: 查找方式 # :param root: 开始查找的父控件 # :param timeout: 控件查找超时时间 # :param interval: 查找间隔 # :return: 找到的控件个数 # ''' # # import util # ctrls = [] # try: # ctrls = util.Timeout(timeout, interval).retry(locator.search, (root,), (), lambda x: len(x) != 0) # except TimeoutError: # pass # return len(ctrls) # # @classmethod # def exist2(cls, *args, **kwargs): # '''在timeout时间内检查控件是否存在,返回True or False # # :param kwargs: 可变参数。代表控件类实例化所需的参数,比如说通过MainPanel类调用该函数,则参数传入qqapp实例 # :param args: 可变参数。代表控件类实例化所需的参数,比如说通过MainPanel类调用该函数,则参数传入qqapp实例 # :return: 该类型控件是否存在,True or False # :attention: 如果通过某个类的QPATH能找到多个符合条件的控件,会抛出ControlAmbiguousError, # 这表明该控件类的QPATH定义是不准确的 # ''' # return cls(*args, **kwargs).exist() def _click(self, mouseFlag, clickType, xOffset, yOffset): '''点击控件 :type mouseFlag: qt4c.mouse.MouseFlag :param mouseFlag: 鼠标按钮 :type clickType: qt4c.mouse.MouseClickType :param clickType: 鼠标动作 :type xOffset: int :param xOffset: 距离控件区域左上角的偏移。 默认值为None,代表控件区域x轴上的中点; 如果为负值,代表距离控件区域右边的绝对值偏移; :type yOffset: int :param yOffset: 距离控件区域左上角的偏移。 默认值为None,代表控件区域y轴上的中点; 如果为负值,代表距离控件区域上边的绝对值偏移; ''' if not self.BoundingRect: return (l, t, r, b) = self.BoundingRect.All if xOffset is None: x = (l + r) // 2 else: if xOffset < 0: x = r + xOffset else: x = l + xOffset if yOffset is None: y = (t + b) // 2 else: if yOffset < 0: y = b + yOffset else: y = t + yOffset Mouse.click(x, y, mouseFlag, clickType) def click(self, mouseFlag=MouseFlag.LeftButton, clickType=MouseClickType.SingleClick, xOffset=None, yOffset=None): '''点击控件 :type mouseFlag: qt4c.mouse.MouseFlag :param mouseFlag: 鼠标按钮 :type clickType: qt4c.mouse.MouseClickType :param clickType: 鼠标动作 :type xOffset: int :param xOffset: 距离控件区域左上角的偏移。默认值为None,代表控件区域x轴上的中点。 如果为负值,代表距离控件区域右上角的x轴上的绝对值偏移。 :type yOffset: int :param yOffset: 距离控件区域左上角的偏移。 默认值为None,代表控件区域y轴上的中点。如果为负值,代表距离控件区域右上角的y轴上的绝对值偏移。 ''' self.hover() x, y = self._getClickXY(xOffset, yOffset) Mouse.click(x, y, mouseFlag, clickType) def _getClickXY(self, xOffset, yOffset): '''通过指定的偏移值确定具体要点击的x,y坐标 ''' if not self.BoundingRect: return (l, t, r, b) = self.BoundingRect.All if xOffset is None: x = (l + r) // 2 else: if xOffset < 0: x = r + xOffset else: x = l + xOffset if yOffset is None: y = (t + b) // 2 else: if yOffset < 0: y = b + yOffset else: y = t + yOffset return x, y def doubleClick(self, xOffset=None, yOffset=None): """左键双击,参数参考click函数 """ self.click(MouseFlag.LeftButton, MouseClickType.DoubleClick, xOffset, yOffset) def hover(self): """鼠标移动到该控件上 """ if not self.BoundingRect: return # (l, t, r, b) = (self.BoundingRect.Left, # self.BoundingRect.Top, # self.BoundingRect.Right, # self.BoundingRect.Bottom # ) x, y = self.BoundingRect.Center.All Mouse.move(x, y) def rightClick(self, xOffset=None, yOffset=None): """右键双击,参数参考click函数 """ self.click(MouseFlag.RightButton, xOffset=xOffset, yOffset=yOffset) # def leftClick(self): # self.click(MouseFlag.LeftButton) def drag(self, toX, toY): '''拖拽控件到指定位置 ''' if not self.BoundingRect: return (l, t, r, b) = (self.BoundingRect.Left, self.BoundingRect.Top, self.BoundingRect.Right, self.BoundingRect.Bottom) x, y = (l + r) // 2, (t + b) // 2 Mouse.drag(x, y, toX, toY) def scroll(self, backward=True): '''发送鼠标滚动命令 ''' self.hover() Mouse.scroll(backward) def sendKeys(self, keys): '''发送按键命令 ''' self.setFocus() Keyboard.inputKeys(keys) def setFocus(self): '''设控件为焦点 ''' raise NotImplementedError('please implement in sub class') def waitForValue(self, prop_name, prop_value, timeout=10, interval=0.5, regularMatch=False): """等待控件属性值出现, 如果属性为字符串类型,则使用正则匹配 :param prop_name: 属性名字 :param prop_value: 等待出现的属性值 :param timeout: 超时秒数, 默认为10 :param interval: 等待间隔,默认为0.5 :param regularMatch: 参数 property_name和waited_value是否采用正则表达式的比较。默认为不采用(False)正则,而是采用恒等比较。 """ Timeout(timeout, interval).waitObjectProperty(self, prop_name, prop_value, regularMatch) @property def BoundingRect(self): """返回窗口大小。未实现! """ raise NotImplementedError("please implement in sub class") def equal(self, other): '''判断两个对象是否相同。未实现! :type other: Control :param other: 本对象实例 ''' raise NotImplementedError("please implement in sub class") def __eq__(self, other): """重载对象恒等操作符(==) """ return self.equal(other) def __ne__(self, other): """重载对象不等操作符(!=) """ return (not self.equal(other)) def get_metis_view(self): '''返回MetisView ''' return MetisView(self)
def wait_for_value(self, timeout, interval, attrname, attrval): '''wait for control attribute value ''' Timeout(timeout, interval).retry(lambda: getattr(self, attrname), (), None, lambda x: x == attrval)
def wait_for_exist(self, timeout, interval): '''wait for control existence ''' Timeout(timeout, interval).retry(self.exist, (), None, lambda x: x == True)