Best Python code snippet using uiautomator
FTTAutomator.py
Source:FTTAutomator.py
1# -*- coding: UTF-8 -*-2'''3Created on 20170315 by leochechen4@Summary: ftt-automator åºäºuiautomatorçäºæ¬¡å°è£
5'''6import os7import re8import time9import itertools10import threading11from functools import wraps12from time import sleep13from libs import yaml14from UiAutomator import point, rect, param_to_property, DEVICE_PORT, next_local_port15from UiAutomator import Adb, AutomatorServer, AutomatorDevice16try:17 import urllib218except ImportError:19 import urllib.request as urllib220try:21 from httplib import HTTPException22except:23 from http.client import HTTPException24try:25 if os.name == 'nt':26 from libs import urllib327except: # to fix python setup error on Windows.28 pass29class FTTJob(threading.Thread):30 def __init__(self, group=None, target=None, name=None,31 args=(), kwargs={}, verbose=None, interval=1, times=-1):32 super(FTTJob, self).__init__(name=name)33 self.__name = name34 self.__target = target35 self.__args = args36 self.__kwargs = kwargs37 self.__interval = interval38 self.__times = times39 # ç¨äºæå线ç¨çæ è¯40 self.__flag = threading.Event()41 # 设置为True42 self.__flag.set()43 # ç¨äºåæ¢çº¿ç¨çæ è¯44 self.__running = threading.Event()45 # å°running设置为True46 self.__running.set()47 def _control(self):48 if self.__target and self.__times > 0:49 self.__target(*self.__args, **self.__kwargs)50 self.__times -= 151 if self.__times == 0:52 self.stop()53 elif self.__target and self.__times == -1:54 # print "invoke {}".format(self.name)55 self.__target(*self.__args, **self.__kwargs)56 else:57 raise EnvironmentError("target and times doesn't meet the conditions")58 time.sleep(self.__interval)59 def run(self):60 while self.__running.isSet():61 self.__flag.wait()62 self._control()63 def pause(self):64 self.__flag.clear()65 def resume(self):66 self.__flag.set()67 def stop(self):68 self.__flag.set()69 self.__running.clear()70 def __str__(self):71 return "<FTTJob-{} interval={} times={}>".format(self.__name, self.__interval, self.__times)72 def __repr__(self):73 return self.__str__()74class FTTTestCase(object):75 '''76 @FttTestCase77 class TestCase(object):78 def __init__(self):79 pass80 def setup(self):81 pass82 def tearDown(self):83 pass84 '''85 @property86 def cls_name(self):87 return self.cls.__name__88 @staticmethod89 def super(ftttestcase_cls, instance):90 '''91 è¿åç¶ç±»å¯¹è±¡92 :param ftttestcase_cls: 被FTTTestCase修饰çç±»93 :param instance: self94 :return:95 '''96 if hasattr(ftttestcase_cls, 'cls'):97 return super(ftttestcase_cls.cls, instance)98 else:99 raise TypeError("{} hasn't cls property".format(ftttestcase_cls))100 @staticmethod101 def inherit(ftttestcase_cls):102 '''103 ä»ftttestcaseå®ä¾ä¸æåç±»å®ä¾104 :param ftttestcase_cls: 被FTTTestCase修饰çç±»105 :return: åå§ç±»106 '''107 if type(ftttestcase_cls) is not FTTTestCase:108 raise EnvironmentError("åªæ¥å@FTTTestCase修饰è¿çç±»")109 return ftttestcase_cls.cls110 def __init__(self, cls):111 self.cls = cls112 def __call__(self, custom_module=None):113 ins = self.cls()114 if hasattr(ins, 'setup'):115 ins.setup()116 else:117 raise EnvironmentError("ftt testcase class hasn't setup method...")118 if hasattr(ins, 'cleanup'):119 ins.cleanup()120 else:121 raise EnvironmentError("ftt testcase class hasn't cleanup method...")122 def __getattr__(self, item):123 return getattr(self.cls, item)124 def __str__(self):125 return "<{0} instance-{1}>".format(self.__class__.__name__, self.cls.__name__)126 def __repr__(self):127 return self.__str__()128class FTTUISelector(object):129 # å°yamlæ ¼å¼è¯æ³æ°æ®æååºæ¥ï¼å½¢æAutomatorDeviceObject130 __fields = (131 'text',132 'textContains',133 'textMatches',134 'textStartsWith',135 'className',136 'classNameMatches',137 'description',138 'descriptionContains',139 'descriptionMatches',140 'descriptionStartsWith',141 'checkable',142 'checked',143 'clickable',144 'longClickable',145 'scrollable',146 'enabled',147 'focusable',148 'focused',149 'selected',150 'packageName',151 'packageNameMatches',152 'resourceId',153 'resourceIdMatches',154 'index',155 'instance'156 )157 def __init__(self, device):158 self.ftt_device = device159 self._steams = {}160 self._path = None161 self._steam = None162 @property163 def path(self):164 return self._path.encode('utf-8') if type(self._path) is unicode else self._path165 @property166 def steam(self):167 return self._steam168 def load(self, path):169 self._steam = self._steams[path] if path in self._steams else yaml.load(open(path))170 self._path = path171 def _get_selector(self, name):172 '''173 æ ¹æ®yamlæ°æ®æ件ä¸çnameå
³é®åæè
selector174 :param name: å
³é®å175 :return:176 '''177 try:178 return self._get_selector_instance(None, self._steam[name])179 except TypeError:180 raise EnvironmentError("é
ç½®Selector UIç页é¢è·¯å¾")181 def _get_selector_instance(self, instance, data):182 '''183 è·åselectorå®ä¾184 :param instance: å½åçselectorå®ä¾185 :param data: ç¨ä¾å®ä½çæ°æ®186 :return:187 '''188 selector = dict([(item, data[item]) for item in data.keys() if item in self.__fields])189 if 'method' not in data:190 crt_instance = self.ftt_device(**selector)191 elif data['method'] == 'child_by_text':192 '''193 method: child_by_text194 txt: your child text195 ui selecotor196 '''197 crt_instance = instance.child_by_text(data['txt'], **selector)198 elif data['method'] == 'child_by_instance':199 '''200 method: child_by_instance201 instance: your instance202 ui selecotor203 '''204 crt_instance = instance.child_by_instance(int(data['instance']), **selector)205 elif data['method'] == 'child_by_description':206 '''207 method: child_by_description208 txt: your child text209 ui selecotor210 '''211 crt_instance = instance.child_by_instance(int(data['txt']), **selector)212 else:213 crt_instance = eval('.'.join(['instance', data['method']]))(**selector)214 if 'extand' not in data:215 return crt_instance216 else:217 return self._get_selector_instance(crt_instance, data['extand'])218 def __call__(self, name):219 return self._get_selector(name)220class FTTAdb(Adb):221 def __init__(self, serial=None, adb_server_host=None, adb_server_port=None):222 super(FTTAdb, self).__init__(serial=serial, adb_server_host=adb_server_host, adb_server_port=adb_server_port)223 self.__adb_cmd = None224 def adb(self):225 if self.__adb_cmd is None:226 '''227 if "ANDROID_HOME" in os.environ:228 filename = "adb.exe" if os.name == 'nt' else "adb"229 adb_cmd = os.path.join(os.environ["ANDROID_HOME"], "platform-tools", filename)230 if not os.path.exists(adb_cmd):231 raise EnvironmentError(232 "Adb not found in $ANDROID_HOME path: %s." % os.environ["ANDROID_HOME"])233 else:234 import distutils235 if "spawn" not in dir(distutils):236 import distutils.spawn237 adb_cmd = distutils.spawn.find_executable("adb")238 if adb_cmd:239 adb_cmd = os.path.realpath(adb_cmd)240 else:241 raise EnvironmentError("$ANDROID_HOME environment not set.")242 self.__adb_cmd = adb_cmd243 '''244 # @Modified by leochechen on 20171221.245 # use the specified adb on nt system246 filename = "adb.exe" if os.name == 'nt' else "adb"247 self.__adb_cmd = os.path.join(os.path.dirname(__file__), "../adb", filename)248 return self.__adb_cmd249class FTTAutomatorServer(AutomatorServer):250 __jar_files = {251 "bundle.jar": "libs/bundle.jar",252 "uiautomator-stub.jar": "libs/uiautomator-stub.jar"253 }254 __apk_files = ["libs/app-uiautomator.apk", "libs/app-uiautomator-test.apk"]255 __sdk = 0256 def __init__(self, serial=None, local_port=None, device_port=None, adb_server_host=None, adb_server_port=None):257 self.uiautomator_process = None258 self.adb = FTTAdb(serial=serial, adb_server_host=adb_server_host, adb_server_port=adb_server_port)259 self.device_port = int(device_port) if device_port else DEVICE_PORT260 if local_port:261 self.local_port = local_port262 else:263 try: # first we will try to use the local port already adb forwarded264 for s, lp, rp in self.adb.forward_list():265 if s == self.adb.device_serial() and rp == 'tcp:%d' % self.device_port:266 self.local_port = int(lp[4:])267 break268 else:269 self.local_port = next_local_port(adb_server_host)270 except:271 self.local_port = next_local_port(adb_server_host)272 def push(self):273 base_dir = os.path.dirname(__file__)274 for jar, url in self.__jar_files.items():275 filename = os.path.join(base_dir, "..", url)276 self.adb.cmd("push", filename, "/data/local/tmp/").wait()277 return list(self.__jar_files.keys())278 def install(self):279 base_dir = os.path.dirname(__file__)280 for apk in self.__apk_files:281 self.adb.cmd("install", "-r -t", os.path.join(base_dir, "..", apk)).wait()282 def start(self, timeout=5):283 # print "in FTTAutomatorServer start"284 if self.sdk_version() < 18:285 files = self.push()286 cmd = list(itertools.chain(287 ["shell", "uiautomator", "runtest"],288 files,289 ["-c", "com.github.uiautomatorstub.Stub"]290 ))291 else:292 self.install()293 cmd = ["shell", "am", "instrument", "-w",294 "com.github.uiautomator.test/android.support.test.runner.AndroidJUnitRunner"]295 self.uiautomator_process = self.adb.cmd(*cmd)296 self.adb.forward(self.local_port, self.device_port)297 while not self.alive and timeout > 0:298 time.sleep(0.1)299 timeout -= 0.1300 if not self.alive:301 raise IOError("RPC server not started!")302 def stop(self):303 # print "in FTTAutomatorServer stop"304 if self.uiautomator_process and self.uiautomator_process.poll() is None:305 res = None306 try:307 res = urllib2.urlopen(self.stop_uri)308 self.uiautomator_process.wait()309 except:310 self.uiautomator_process.kill()311 finally:312 if res is not None:313 res.close()314 self.uiautomator_process = None315 try:316 self.adb.cmd("shell", "am", "force-stop", "com.github.uiautomator").communicate()[0].decode("utf-8").strip().splitlines()317 except Exception, ex:318 pass319class FTTAutomatorDevice(AutomatorDevice):320 def __init__(self, serial=None, local_port=None, adb_server_host=None, adb_server_port=None):321 self.server = FTTAutomatorServer(322 serial=serial,323 local_port=local_port,324 adb_server_host=adb_server_host,325 adb_server_port=adb_server_port326 )327 self.adb = self.server.adb328 self.fttSelector = FTTUISelector(self)329 self.fttJobs = []330 @property331 def source(self):332 return self.fttSelector333 @source.setter334 def source(self, _path):335 self.fttSelector.load(_path)336 def wait_for_times(self, count, interval, error):337 '''338 æ¯éè§å®æ¶é´çå¾
ç®åæ¹æ³æ§è¡ä¸æ¬¡339 :param count: éè¯ç次æ°340 :param interval: æ¯ä¸æ¬¡éè¯çæ¶é´é´é341 :param error: è¶
æ¶ä¹åçé误æ示342 :return: ä¸ä¸ªç®æ å½æ°çè£
饰å¨343 '''344 def decorator(func):345 @wraps(func)346 def wrap_function(*args, **kwargs):347 retry = count348 try:349 start_time = time.time()350 if retry == -1:351 while True:352 result = func(*args, **kwargs)353 if result:354 return result355 while retry > 0:356 # print "try to invoke {}".format(func)357 result = func(*args, **kwargs)358 if result:359 return result360 else:361 retry -= 1362 sleep(interval)363 else:364 raise EnvironmentError(error)365 finally:366 self.total_wait_time = time.time() - start_time367 return wrap_function368 return decorator369 def click_selector(self, name, count=20, interval=0.5):370 '''371 ç¹å»ä¸ä¸ªnavtiveæ§ä»¶372 :param name: ftt-ui-selectorå®ä½ç»æçåå373 :param count: 循ç¯æ¬¡æ°374 :param interval: ä¸æ¬¡çæ¶é´é´é375 :return:376 '''377 return self.fttSelector(name).click() \378 if self.wait_exists_and_enabled(name=name, count=count, interval=interval) else None379 def wait_exists_and_enabled(self, name, count=20, interval=0.5):380 '''381 å¤ænativeæ§ä»¶æ¯å¦åå¨å¹¶ä¸ææ382 :param name: ftt-ui-selectorå®ä½ç»æçåå383 :param count: 循ç¯æ¬¡æ°384 :param interval: ä¸æ¬¡çæ¶é´é´é385 :return:386 '''387 ui_selector = self.fttSelector(name)388 @self.wait_for_times(count=count, interval=interval,389 error="å¨{0}så
ï¼ã{1}ãã{2}ã没ææ¾å°å¹¶çæ".format(count*interval, self.fttSelector.path, name))390 def is_exists():391 return ui_selector.exists and ui_selector.info['enabled'] is True392 return is_exists()393 def text(self, name):394 '''395 è·åftt-ui-selectorçææ¬å
容396 :param name: ftt-ui-selectorå®ä½ç»æçå
³é®å397 :return:398 '''399 return self.fttSelector(name).info['text'].encode('utf-8')400 def wait_exists(self, name, timeout=5000):401 '''402 å¨ä¸å®æ¶é´å
çå¾
æ§ä»¶åºç°403 :param name: ftt-ui-selectorå®ä½ç»æçå
³é®å404 :param timeout: è¶
æ¶æ¶é´405 :return:406 '''407 self.fttSelector(name).wait.exists(timeout=timeout)408 def wait_gone(self, name, timeout=5000):409 '''410 å¨ä¸å®æ¶é´å
çå¾
æ§ä»¶æ¶å¤±411 :param name: ftt-ui-selectorå®ä½ç»æçå
³é®å412 :param timeout: è¶
æ¶æ¶é´413 :return:414 '''415 self.fttSelector(name).wait.gone(timeout=timeout)416 def get_centre(self, name):417 '''418 è·åftt ui selectorè·åä¸å¿ç¹çåæ 419 :param name: ftt ui selector420 :return:421 '''422 # Bounds (left,top) (right,bottom)423 bounds = self.fttSelector(name).info['visibleBounds']424 return point((bounds['right'] - bounds['left'])/2 + bounds['left'],425 (bounds['bottom'] - bounds['top'])/2 + bounds['top'])426 def get_rect(self, name):427 '''428 è·åftt ui selectorçç©éµå¤§å°429 :param name: ftt ui selector430 :return: {"top": top, "left": left, "bottom": bottom, "right": right}431 '''432 bounds = self.fttSelector(name).info['visibleBounds']433 return rect(**bounds)434 def screen_size(self):435 '''436 è¿åå±å¹å°ºå¯¸437 :return:438 '''439 return {"width": self.info['displayWidth'],440 "height": self.info['displayHeight']}441 def swipe_to(self, _from, _to, steps=50):442 '''443 ä»ftt ui selectorç_fromç®æ æ»å¨å°_toç®æ ,以stps为æ¥é¿444 :param _from: ftt ui selector445 :param _to: ftt ui selector446 :param steps: æ¥é¿447 :return:448 '''449 my_to = self.get_centre(_to)450 my_from = self.get_centre(_from)451 self.swipe(my_from['x'], my_from['y'], my_to['x'], my_to['y'], steps=steps)452 @property453 def swipe_until(self):454 '''455 :Usage:456 >>> # ä»experience_device_firstéæ©ä¸ä¸ªæ¹åæ»å¨å°my_unknow_deviceåå¨ä¸ºæ¢457 >>> swipe_until.up('_from', '_to')458 >>> swipe_until('up', '_from', '_to')459 >>> swipe_until.down('_from', '_to')460 >>> swipe_until('down', '_from', '_to')461 >>> swipe_until.left('_from', '_to')462 >>> swipe_until('left', '_from', '_to')463 >>> swipe_until.right('_from', '_to')464 >>> swipe_until('right', '_from', '_to')465 :return:466 '''467 @param_to_property(orientation=['right', 'left', 'up', 'down'])468 def _swipe_until(orientation, _from, _to, steps=100, count=10, interval=0.1):469 '''470 ä»_fromå¼å§æ»å¨ç´å° _toåå¨ä¸ºæ¢471 :param orientation: æ»å¨æ¹å472 :param _from: ftt ui selector473 :param _to: ftt ui selector474 :param stepsï¼ æ»å¨æ¥é¿475 :param count: æ»å¨æ¬¡æ°476 :param interval: æ»å¨é´é477 '''478 obj = self479 class SwipeHandler(object):480 def __init__(self, name):481 self.start = obj.get_centre(name)482 @obj.wait_for_times(count=count, interval=interval,483 error="ææ¹å-{0}æ»å¨{1}次åï¼æ²¡æåç°{2}".format(orientation,count,_to))484 def until(self):485 if orientation == 'up':486 end = point(self.start['x'], self.start['y'] - steps)487 elif orientation == 'down':488 end = point(self.start['x'], self.start['y'] + steps)489 elif orientation == 'left':490 end = point(self.start['x'] - steps, self.start['y'])491 elif orientation == 'right':492 end = point(self.start['x'] + steps, self.start['y'])493 else:494 raise EnvironmentError("ä¸æ¯æçæ»å¨æ¹å-{}".format(orientation))495 obj.swipe(self.start['x'], self.start['y'], end['x'], end['y'], steps=10)496 return obj.fttSelector(_to).exists497 SwipeHandler(_from).until()498 return _swipe_until499 def watcher(self, name):500 obj = self501 class Watcher(object):502 def __init__(self):503 self.ftt_selectors = []504 @property505 def matched(self):506 @param_to_property(method=['click', 'press'])507 def _matched(method, args=(), kwargs={}):508 for selector in self.ftt_selectors:509 if not obj(**selector).exists:510 return False511 if method == 'click':512 if obj(**kwargs).exists:513 obj(**kwargs).click()514 elif method == 'press':515 for arg in args:516 obj.press(arg)517 return _matched518 def when(self, **kwargs):519 self.ftt_selectors.append(kwargs)520 return self521 def click(self, **kwargs):522 obj.fttJobs.append(FTTJob(name=name, target=lambda: self.matched.click(kwargs=kwargs), interval=1))523 @property524 def press(self):525 @param_to_property(526 "home", "back", "left", "right", "up", "down", "center",527 "search", "enter", "delete", "del", "recent", "volume_up",528 "menu", "volume_down", "volume_mute", "camera", "power")529 def _press(*args):530 obj.fttJobs.append(FTTJob(name=name, target=lambda: self.matched.press(args=args), interval=1))531 return _press532 return Watcher()533 @property534 def watchers(self):535 obj = self536 class Watchers(list):537 def __init__(self):538 pass539 def find(self, name):540 for job in obj.fttJobs:541 if job.name == name:542 return job543 raise EnvironmentError("没ææ¾å°task-{}".format(name))544 def pause(self, name):545 self.find(name).pause()546 def resume(self, name):547 self.find(name).resume()548 def run(self, name):549 return self.find(name).start()550 def remove(self, name):551 job = self.find(name)552 job.stop()553 obj.fttJobs.remove(job)554 @property555 def all(self):556 return obj.fttJobs557 return Watchers()558def get_device(serial=None, local_port=None):559 '''560 åä¾æ¨¡å¼ï¼è·åå建设å¤è¿æ¥561 :param serial: 设å¤serial562 :param local_port: æ¬å°è¿æ¥uiautomatorç端å£563 :return:564 '''565 if get_device.instance:566 return get_device.instance567 else:568 get_device.instance = FTTAutomatorDevice(serial=serial, local_port=local_port)569 return get_device.instance570get_device.instance = None571if __name__ == "__main__":572 FTTDevice = get_device()573 print FTTDevice.info574 FTTDevice.source = u"D:\workspace\IDDAutomation\workspace\layout\\ui\æç´¢.yaml"...
longclick.py
Source:longclick.py
...89 d.wait.update()90@step(u'é¿æå¯æ»å¨æ¡æ¶ã%sãå
çç¹å¾æè¿°ã%sã页é¢å
ç´ $' % (mode_pvs, mode_text))91def click_child_by_desc(step, scrollcond, trait):92 scroll = get_dict_from_cond(scrollcond)93 d(**scroll).child_by_description(trait,allow_scroll_search=True,descriptionContains=trait).long_click()94 d.wait.update()95@step(u'é¿æå¯æ»å¨æ¡æ¶ã%sãå
çç¹å¾åºå·ã%sã页é¢å
ç´ $' % (mode_pvs, mode_int))96def click_child_by_inst(step, framecond, trait):97 frame = get_dict_from_cond(framecond)98 d(**frame).child_by_instance(trait,instance=trait).long_click()99 d.wait.update()100# å®å¤åæ³101@step(u'é¿æå¯æ»å¨æ¡æ¶ã%sãå
ç页é¢å
ç´ ã%sãä¸å
¶ååç»ç¹å«textå¼ã%sã$' % (mode_pvs, mode_pvs, mode_text))102def long_click_child_by_text(step, scrollcond, cond, text):103 scroll = get_dict_from_cond(scrollcond)104 my = get_dict_from_cond(cond)105 d(**scroll).child_by_text(text,allow_scroll_search=True,**my).long_click()106 d.wait.update()107@step(u'é¿æå¯æ»å¨æ¡æ¶ã%sãå
ç页é¢å
ç´ ã%sãä¸å
¶ååç»ç¹å«descriptionå¼ã%sã$' % (mode_pvs, mode_pvs, mode_text))108def long_click_child_by_desc(step, scrollcond, cond, desc):109 scroll = get_dict_from_cond(scrollcond)110 my = get_dict_from_cond(cond)111 d(**scroll).child_by_description(desc,allow_scroll_search=True,**my).long_click()112 d.wait.update()113#æªæä¾é¿æå·¦ä¸è§æå³ä¸è§åè½è¯å¥114@step(u'å¨æ¡æ¶ã%sãå
ï¼é¿æ页é¢å
ç´ ã%sãä¸ååç»ç¹å«instanceåºå·ã%sã$' % (mode_pvs, mode_pvs, mode_int))115def long_click_child_by_inst(step, framecond, cond, inst):116 frame = get_dict_from_cond(framecond)117 my = get_dict_from_cond(cond)118 d(**frame).child_by_instance(inst,**my).long_click()119 d.wait.update()120# *-* å·¦ä¸è§ *-*121@step(u'é¿æ页é¢å
ç´ å·¦ä¸è§ã%sã$' % (mode_pvs))122def long_click_tl(step, condition):123 dict = get_dict_from_cond(condition)124 d(**dict).long_click.topleft()125 d.wait.update()...
click.py
Source:click.py
...90 d(**scroll).child_by_text(trait,allow_scroll_search=True,textContains=trait).click.wait()91@step(u'ç¹å»å¯æ»å¨æ¡æ¶ã%sãå
çç¹å¾æè¿°ã%sã页é¢å
ç´ $' % (mode_pvs, mode_text))92def click_child_by_desc(step, scrollcond, trait):93 scroll = get_dict_from_cond(scrollcond)94 d(**scroll).child_by_description(trait,allow_scroll_search=True,descriptionContains=trait).click.wait()95@step(u'ç¹å»å¯æ»å¨æ¡æ¶ã%sãå
çç¹å¾åºå·ã%sã页é¢å
ç´ $' % (mode_pvs, mode_int))96def click_child_by_inst(step, framecond, trait):97 frame = get_dict_from_cond(framecond)98 d(**frame).child_by_instance(trait,instance=trait).click.wait()99# å®å¤åæ³100@step(u'ç¹å»å¯æ»å¨æ¡æ¶ã%sãå
ç页é¢å
ç´ ã%sãä¸å
¶ååç»ç¹å«textå¼ã%sã$' % (mode_pvs, mode_pvs, mode_text))101def click_child_by_text(step, scrollcond, cond, text):102 print cond103 print text104 scroll = get_dict_from_cond(scrollcond)105 my = get_dict_from_cond(cond)106 d(**scroll).child_by_text(text,allow_scroll_search=True,**my).click.wait()107@step(u'ç¹å»å¯æ»å¨æ¡æ¶ã%sãå
ç页é¢å
ç´ ã%sãä¸å
¶ååç»ç¹å«descriptionå¼ã%sã$' % (mode_pvs, mode_pvs, mode_text))108def click_child_by_desc(step, scrollcond, cond, desc):109 scroll = get_dict_from_cond(scrollcond)110 my = get_dict_from_cond(cond)111 d(**scroll).child_by_description(desc,allow_scroll_search=True,**my).click.wait()112@step(u'ç¹å»å¯æ»å¨æ¡æ¶ã%sãå
ç页é¢å
ç´ ã%sãä¸å
¶ååç»ç¹å«instanceåºå·ã%sã$' % (mode_pvs, mode_pvs, mode_int))113def click_child_by_inst(step, framecond, cond, inst):114 frame = get_dict_from_cond(framecond)115 my = get_dict_from_cond(cond)116 d(**frame).child_by_instance(inst,**my).click.wait()117# *-* å·¦ä¸è§ *-*118@step(u'ç¹å»é¡µé¢å
ç´ å·¦ä¸è§ã%sã$' % (mode_pvs))119def click_tl(step, condition):120 dict = get_dict_from_cond(condition)121 d(**dict).click.topleft()122 d.wait.update()123@step(u'ç¹å»é¡µé¢å
ç´ å·¦ä¸è§ï¼ç¶ã%sãèªã%sã$' % (mode_pvs, mode_pvs))124def click_child_tl(step, cond, childcond):125 father = get_dict_from_cond(cond)...
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!!