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

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

  • 相关阅读:
    Java 8与Runtime.getRuntime().availableProcessors()
    nginx配置
    周末完成工作小结
    CentOS 8 安装MySQL 8.0
    centOS8网络获取不了
    IUAP平台新增菜单存储过程
    centOS8安装Docker
    Mybatis里用到的设计模式
    2020,回顾过往,展望未来
    使用 Apache SSI(Server Side Includes) 制作多语言版静态网页
  • 原文地址:https://www.cnblogs.com/liuhui0308/p/12038303.html
Copyright © 2011-2022 走看看