美文网首页Appium知识点汇总
Appium 选择 APP 界面元素

Appium 选择 APP 界面元素

作者: 自如_ | 来源:发表于2019-07-02 14:21 被阅读0次

    4.1 查看工具

    Web 自动化开发的时候,要找到元素,我们是通过浏览器的开发者工具栏来查看元素的特性,根据这些特性,比如:id、classname、tagname,或者 cssxpath 选择到元素。那么安卓的移动 app 我们怎么查看元素呢?安卓查看页面元素,最常用的就是 Android SDK 中的 uiautomateviewer,我的目录在 .\tools\tools\bin 下面。

    image.png

    双击打开,然后手机打开要查看app的界面,然后点击

    image.png

    它就会到当前连接手机的设备上去获取,当前界面的信息。


    image.png

    然后我们就可以去查看了。uiautomatorviewer 查看的是手机当前界面的元素,我们可以点击手机的界面,进入到不同的界面,查看我们要查看界面的元素。进入到一个新界面的时候,需要再次点击按钮。和 web 不同,它不能自动刷新,需要我们手动点击重新获取当前界面。我们要查找某个元素,可以把鼠标移动到某个元素上,某个元素就有虚线红框子,同时右边会高亮当前的元素,如果确定了要查看的元素,就点击一下该元素,虚线变成实线,就是确定了查看这个元素的信息。同时,右边下面就显示出该元素的具体的属性信息,这时候再异动鼠标就不会根据经过的元素而变化了。它认为已经确定了要看的元素了。如果我们想再次查看别的元素,就需要随便点击一下界面某个地方,实线又变成虚线。就可以再次移动选择别的元素,确定下来就点击它。

    可能还有人看到了整个按钮。


    image.png

    它也可以获取当前界面的信息,它获取的相对来说是一个精简的目录数,它把中间一些没有具体信息的层次会去掉。比如:


    image.png

    它就比刚才精简了好多,去掉一些没有包含实际信息的层次的信息,通常还是用前面方法的多。

    下面介绍一些元素的属性:

    • index: 就是该元素是其父元素的第几个子节点(从0开始)。
    • text: 就是如果该元素对应的界面上有文本内容,就是其文本内容的字符串值。显然这是我们将来非常关心的属性,因为可能要分析内容,判断是否与预期相等。
    • resource-id: 是该元素的资源 id,一般来说唯一的决定了一个元素,有点像 webid
    • class: 就是该元素的类型,类似 htmltag
    • package: 就是所在 app 的包名。
    • content-desc: 这个属性用来描述该元素的用途,特性等。
    • bounds: 就是这个元素在界面上的位置,左下角和右小角的坐标。这个属性也很重要,以后如果我们黔驴技穷,是在选择不到元素的时候,就根据这个属性直接去根据坐标操作元素了。

    对于 bounds 看下面截图,一目了然

    image.png

    注意:是像素

    4.2 选择元素的代码

    选择元素的代码也和 Selenium 本相同,可以通过:

    • find_element_by_XXX 符合条件的第一个元素,找不到这样的元素,会抛出异常。
    • find_elements_by_XXX 符合条件的所有元素的列表,找不到会返回空列表。
    • 通过 WebDriver 对象调用这样的方法。查找范围是整个界面树形结构。
    • 通过 WebElement 对象调用这样的方法,查找范围是该元素的子节点。

    4.3 选择元素的方式

    4.3.1 ID

    我们在学习 Web 自动化的时候就说过,能根据 id 最好根据 id,因为是唯一的,效率高、表达式又简单,在安卓应用自动化的时候,同样可以根据 id 查找,但是这个 id 其实安卓应用元素的 resource id 属性,比如上个章节代码中的:

    # 根据id找到元素,并点击
    driver.find_element_by_id("io.manong.developerdaily:id/tab_bar_plus").click()
    
    image.png

    注意这里io.manong.developerdaily:id/tab_bar_plus这里的 id 可以写全,也可以 :id/ 后面的内容就是 driver.find_element_by_id("tab_bar_plus").click() 。光有 id 去选择元素是远远不够的,有很多元素没有 id,也有很多 id 根据规范是唯一的,但是它不唯一,比如我们看一下开发者头条消息id

    image.png

    我们再看发现id

    image.png

    是不是也叫 tv_tab_title ,点击我的它的 id 也是一样的。所以下面四个id 都是一样的。由于开发人员的疏忽。如果有这种错误的话,我们就不能通过 id 定位了。就要通过一些其它的方式。有的人会问我们怎么知道 id 是不是唯一的,以前做 web 自动化的时候我们可以按 F12 然后 Ctrl + F 一系列操作可以验证。我们在这里面要怎么验证呢?很遗憾它这里面就没有查询框了。一种方式就是根据名字来判断,通常 id 跟它的名字如果形成了一种直接的对应关系,通常就是唯一的,可以根据一种直觉,比如这个 idtv_tab_titletabtitile 名,但是你想想下面几个元素全是 tab 。这个时候就要小心了。这个只是一种猜测法还有一种唯一确认的方法,就是把整个界面对应的 xml 文档全部导出来查看一下,怎么导出呢,看截图

    image.png

    选择保存路径。


    image.png

    然后去路径里查看,会发现有两个文件。


    image.png

    第一个 dump 是它所对应的图片,整个不关心,我们关心的是第二个我们可以用 Notepad++ 打开。之后把要查找的 id 复制按 Ctrl + F 点击计数。

    image.png

    这里显示4次匹配,怀疑它不是唯一的。可以通过这种方式来确定是不是唯一,有些麻烦。

    4.3.2 Class Name

    class 属性决定了界面元素的类型。 通常 class 就是类似 web 里面 tagname, 所以通常不是唯一的。所以大部分情况,我们根据 classname 是要选择多个而不是一个。如果你确定,我们要查找的是某种类型的界面元素,而且这种类型的界面元素在当前界面中只有一个,就可以根据它来查找写法是:

    driver.find_element_by_class_name('XXX')
    

    大家看一个例子:开发者头条里面的 底部的大加号 android.widget.ImageButton ,这个在当前界面上就是一个唯一的,我们可以根据它查找。

    image.png

    代码是:

    driver.find_element_by_class_name("android.widget.ImageButton").click()
    

    有的时候,我们需要根据 classname 查找所有匹配的元素,这时候可以用:

    driver.find_elements_by_class_name("XXX")
    

    比如我们要获取界面上所有的 TextView 里面的文本内容,就可以写出如下代码:

    tvs = driver.find_elements_by_class_name("android.widget.TextView")
    for tv in tvs:
        print(tv.text)
    

    4.3.3 content-desc

    content-desc 属性时用来描述该元素的作用的。 要查询的界面元素的 content-desc 属性在当前界面中唯一我们可以通过它来定位。

    image.png

    它的 content-desc 有个 unique name 的,唯一的姓名,如果它有值,并且这个值它在当前这个 content-desc 属性里面它是唯一的,就可以根据这个值来选择,根据 content-desc 来选择的写法如下。

    driver.find_element_by_accessibility_id('xxx')
    

    不幸的是,基本上开发人员都不喜欢填写它。


    1. 到如下网址下载 多多计算器
    http://android.myapp.com/myapp/detail.htm?apkName=com.ibox.calculators&ADTAG=mobile

    2.aapt.exe 命令查看 apk 包的 appPackage 信息和主 Activity 信息
    3.UIAutomator Viewer 查看应用界面元素信息
    4. 编写 python 程序,完成一个 计算 3+9 ,结果 再乘以 5 的自动化功能. 最后判断计算结果是否为 60,如果是,测试通过;否则测试不通过

    示例代码:

    from appium import webdriver
    import time,traceback
    
    desired_caps = {}
    desired_caps['platformName'] = 'Android'
    desired_caps['platformVersion'] = '7'
    desired_caps['deviceName'] = 'test'
    desired_caps['app'] = r'E:\tools\com.ibox.calculators_3.0.5_1305.apk'
    desired_caps['appPackage'] = 'com.ibox.calculators'
    desired_caps['appActivity'] = 'com.ibox.calculators.SplashActivity'
    #desired_caps['unicodeKeyboard']  = True
    desired_caps['noReset'] = True
    desired_caps['newCommandTimeout'] = 6000
    #启动Remote RPC
    driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
    driver.implicitly_wait(10)
    
    try:
        # -----------------
    
    
        num3 = driver.find_element_by_id("com.ibox.calculators:id/digit3")
        num5 = driver.find_element_by_id("com.ibox.calculators:id/digit5")
        num9 = driver.find_element_by_id("com.ibox.calculators:id/digit9")
        plus = driver.find_element_by_id("com.ibox.calculators:id/plus")
        mul = driver.find_element_by_id("com.ibox.calculators:id/mul")
        equal = driver.find_element_by_id("com.ibox.calculators:id/equal")
    
        num3.click()
        plus.click()
        num9.click()
        equal.click()
        mul.click()
        num5.click()
        equal.click()
    
    
        # 检查结果,需要我们去找结果对应的界面元素,发现是下面这个TextView
        # 研究发现没有特点,大家想想我们该怎么办
        # 可以看看父节点有没有唯一标识,发现 父节点是有id的,
        # 就可以怎么样?
        # 先查找父节点,
        # 再根据父节点元素 调用 find element 就是在父节点的范围内 查找
        retLayout = driver.find_element_by_id('com.ibox.calculators:id/cv')
        retTvs = retLayout.find_elements_by_class_name('android.widget.TextView')
        retStr = retTvs[1].text
        print(retStr)
    
        if retStr == '60':
            print('pass')
        else:
            print('fail')
    
    
            # -----------------
    
    except:
        print(traceback.format_exc())
    
    input('**** Press to quit..')
    driver.quit()
    

    相关文章

      网友评论

        本文标题:Appium 选择 APP 界面元素

        本文链接:https://www.haomeiwen.com/subject/vfijcctx.html