zoukankan      html  css  js  c++  java
  • Appium(十):元素定位(加强版)

    1. 元素定位

    写完上一篇元素定位的博客,发现实用性基本为零。这几天真的烦死我了,一直在找资料,还去看了一遍appium官网文档。最后结合着selenium的定位方法,测试出几种可行的元素定位方法。

    1.1 层级定位

    什么是层级定位呢?

    在很多的自动化中如果只是靠简单的定位是没有办法完成自动化的。有的元素的id、name、className都是一样的,xpath定位效率低下,并且在appium中,可以使用的属性非常少,这个时候我们就需要使用层级定位了。

    我们可以看到,QQ天气和微视的class都是相同的, 接下来我们用代码试一试。

    # coding:utf-8
    from appium import webdriver
    from time import sleep
    
    # 初始化
    desired_caps = {}
    # 使用哪种移动平台
    desired_caps['platformName'] = 'Android'
    # Android版本
    desired_caps['platformVersion'] = '5.1.1'
    #使用adb devices -l 查询,当有多台设备时,需要声明
    desired_caps['deviceName'] = '127.0.0.1:62001'
    #包名
    desired_caps['appPackage'] = 'com.tencent.mobileqq'
    #界面名
    desired_caps['appActivity'] = '.activity.SplashActivity'
    #不清除数据
    desired_caps['noReset'] = 'True'
    # 启动服务
    driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
    
    driver.find_element_by_id('com.tencent.mobileqq:id/recent_chat_list')
    driver.find_element_by_class_name('android.widget.LinearLayout').click()
    
    #退出driver
    driver.quit()

    运行后,我们会发现代码执行了,也没有报错,但是也不会点击,这是为什么呢。这就牵扯到另外一个定位问题,就是下面要说的List定位。

    1.2 List定位

    list顾名思义就是一个列表。当我们想要获取一个元素,但是却发现符合条件的元素有很多个的时候,我们就可以选择List定位了。因为元素的个数的不确定性,所以我们的方法也需要变成复数,所以这里需要用复数,所以在我们定位时我们不能够接着用find_element_by_class_name等等定位方式了,我们需要用他的复数形式find_elements_by_class_name,所有的定位方式都一样需要采用复数加s。

    driver.find_element_by_id('com.tencent.mobileqq:id/recent_chat_list')
    driver.find_elements_by_class_name('android.widget.LinearLayout')

    上面的代码最后选择的是com.tencent.mobileqq:id/recent_chat_list父节点下所有android.widget.LinearLayout子节点,现在我们如何去操作这些子节点呢,有两种方法:

    1、List是一个集合,这里定位的所有子节点最后就成了个list,如果我们要访问这个list里面的某一个元素我们可以像访问数组中的数据一样通过下标访问。最后的代码就是下面这个样子:

    driver.find_element_by_id('com.tencent.mobileqq:id/recent_chat_list')
    elements = driver.find_elements_by_class_name('android.widget.LinearLayout')
    elements[0].click()
    #让我们更好的观看效果
    sleep(5)

    2、如果你要访问List里面的元素,那么我们是否可以通过for循环语句来依次访问呢?这个在自动化中会经常用到。下面你可以通过这个思路自己去实战一下,看能否达到预期效果。下面看我的代码:

    for element in elements:
        sleep(2)
        element.click()

    看上面的代码,我们通过循环去访问这个list里面的每一个元素,因为每次循环得到的都是其中一个元素,那么我们只需要在这个元素上加上你想要的操作即可,所以我们这里可以直接点击进去。

    但是我们会发现,在进入到第一个标签后,系统就会报错,为什么呢?因为界面跳转到微视里面了,而里面没有android.widget.LinearLayout元素,所以就会因为找不到元素而报错。

    所以这种方法的使用有限制,只能在那种不需要界面跳转的情况下使用。

    1.3 xpath定位(补充)

    xpath定位可以分为两种,绝对定位和相对定位。

    但是我们会发现,绝对定位的路径非常的长,后期代码也比较麻烦,开发中几乎不可能使用。(老大看到了就叼你)

    相对路径就是非常好用的一种了,不断简短,后期维护代码也方便。

    以下就是相对路径的使用了:

    我使用的是taptap软件来进行测试,大家可以换成其他软件。

    (1) 如果当前class内存在唯一text可以定位元素,直接用当前class+text,例如:

    # coding:utf-8
    from appium import webdriver
    from time import sleep
    from appium.webdriver.common.touch_action import TouchAction
    
    # 初始化
    desired_caps = {}
    # 使用哪种移动平台
    desired_caps['platformName'] = 'Android'
    # Android版本
    desired_caps['platformVersion'] = '5.1.1'
    #使用adb devices -l 查询,当有多台设备时,需要声明
    desired_caps['deviceName'] = '127.0.0.1:62001'
    #包名
    desired_caps['appPackage'] = 'com.taptap'
    #界面名
    desired_caps['appActivity'] = 'com.play.taptap.ui.MainAct'
    #不清除数据
    desired_caps['noReset'] = 'True'
    #启动服务
    driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
    
    element = driver.find_element_by_xpath('//android.widget.TextView[@text="排行"]')
    TouchAction(driver).tap(element).perform()
    
    sleep(5)
    
    #退出driver
    driver.quit()

    (2) 如果当前class内,resource-id、text两者能唯一定位元素,直接用当前class+两者并列,例如:

    element1 = driver.find_element_by_xpath('//android.widget.TextView[@text="我的游戏"]')
    TouchAction(driver).tap(element1).perform()
    sleep(2)
    element2 = driver.find_element_by_xpath('//android.widget.TextView[@resource-id="com.taptap:id/app_title" and @text="第五人格T"]')
    TouchAction(driver).tap(element2).perform()
    sleep(5)

    (3) 如果当前class内,text中的文本内容不是完全符合,但能匹配部分内容,可用当前class+模糊定位contains,例如:

    element = driver.find_element_by_xpath('//android.widget.TextView[contains(@text,"我的")]')
    TouchAction(driver).tap(element).perform()
    sleep(2)

    还有很多类似的定位方法,可以查看我找到的一个大佬写的博客:https://blog.csdn.net/Dome_/article/details/80638245

    总体上就这样了,以后如果找到更好的方法,就再更新一章。

  • 相关阅读:
    linux 解压tgz 文件指令
    shell 脚本没有执行权限 报错 bash: ./myshell.sh: Permission denied
    linux 启动solr 报错 Your Max Processes Limit is currently 31202. It should be set to 65000 to avoid operational disruption.
    远程查询批量导入数据
    修改 MZTreeView 赋权节点父节点选中子节点自动选中的问题
    关于乱码的问题解决记录
    我的网站优化之路
    对设计及重构的一点反思
    我的五年岁月
    奔三的路上
  • 原文地址:https://www.cnblogs.com/liuhui0308/p/12038303.html
Copyright © 2011-2022 走看看