51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 1402|回复: 0
打印 上一主题 下一主题

Appium学习路—Android定位元素与操作

[复制链接]
  • TA的每日心情
    郁闷
    2022-8-29 14:43
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]测试小兵

    跳转到指定楼层
    1#
    发表于 2018-2-1 11:23:53 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
           一、常用识别元素的工具
      uiautomator:Android SDK自带的一个工具,在tools目录下
      monitor:Android SDK自带的一个工具,在tools目录下
      Appium Inspector:Appium自带的一个功能,只有mac下可以使用该功能
      下面是用monitor抓取到的页面元素

        下面使用Appium Inspector定位的元素

           二、元素定位
      1.格式:find_element_by_定位方式(value)
      通过id定位
      (取resource-id的值):
      driver.find_element_by_id("com.wuba.zhuanzhuan:id/azo")
      也可以直接用id后面的内容driver.find_element_by_id("azo")
      通过class_name定位
      (取class的内容)
      driver.find_element_by_class_name("android.widget.RelativeLayout")
      通过xpath定位
      (取xpath得内容)
      driver.find_element_by_xpath("//android.widget.LinearLayout[1]/android.widget.XXX")
      通过text定位
      (需要使用uiautomator的定位方式,使用text的内容)
      driver.find_elements_by_android_uiautomator("new UiSelector().text(\"+关注\")")
      使用这里需要注意一下,通过text定位的结果是个list,不能直接click。所以如果要点击需要
    取数组的值,比如下面是点击找到的第一个元素
      driver.find_elements_by_android_uiautomator("new UiSelector().text(\"+关注\")")[0].click()
      通过css_selector定位(webview)
      只适用于webview的html页面,继承自webdriver,与pc版本的UI测试一致
      driver.find_element_by_css_selector()
      通过link_text定位(webview)
      只适用于webview容器中的html页面,继承自webdriver,与pc版本的UI测试一致
      driver.find_element_by_link_text()
      通过name定位
      web view容器中的html页面可以用name定位,native并没有name属性
      driver.find_element_by_name()
      2.定位元素的另一种写法:find_element(by,value)
      find_element_by_方式(value)实际调用的都是find_element(by,value)
      需要导入这个包:from selenium.webdriver.common.by import By
      例如:定位id为ag2的元素
      方式一:driver.find_element_by_id("ag2”)
      方式二:driver.find_element(By.ID,"ag2")
      这个操作的好处是可以直接把操作的by和value放到一个元组里,然后调用通用方法来传参获
    得元素结果
      cateid=(By.ID,"ag2")
      driver.find_element(*cateid).click()
      by的操作可以是:
      By.ID   相当于by_id
      By.CLASS_NAME  相当于by_class_name
      By.XPATH   相当于by_xpath
      By.NAME   相当于by_name
      By.TAG_NAME   相当于by_tag_name
      By.CSS_SELECTOR  相当于by_css_selector
      By.LINK_TEXT  相当于by_link_text
      3.find_elements_by_定位方式(value)返回元素数组
      用法与find_element_by_方式(value)一致,但是返回一个数组。可以通过数组的索引来访问
    具体的某个结果
      例如:通过class_name定位到多个元素,我想点击第一个元素
      driver.find_elements_by_class_name("android.widget.RelativeLayout”)[0].click()
      4.返回元素数组的另一种写法:find_elements(by,value)
      用法与find_element(by,value)一致,但是返回一个数组。可以通过数组的索引来访问具体的
    某个结果
      例如:通过class_name定位到多个元素,我想点击第一个元素
      driver.find_elements(By.CLASS_NAME,"android.widget.RelativeLayout”)[0].click()
      5.通过元素定位元素
      可以先找到某个元素,然后再进一步定位元素
      find_element_by_class_xpath(“xxx”).find_element_by_name(“yyy")
      三、元素操作
      找到元素后可以对元素进行的操作,例如上面讲的进一步定位元素
      1.click()
      //点击操作
      也可以用tab实现点击操作
      driver.find_element_by_id("com.wuba.zhuanzhuan:id/ae8").click()
      2.clear()
      //清空输入框内容
      driver.find_element_by_id("com.wuba.zhuanzhuan:id/ij").clear()
      3.send(xx)
      //输入框内输入内容
      driver.find_element_by_id("com.wuba.zhuanzhuan:id/ij").send_keys("test content")
      4.text
      //获得元素的text内容
      print(driver.find_element_by_xpath(" //android.widget.LinearLayout[1]//xxx").text)
      四、触摸操作
      1.driver.tap([坐标],持续点击时间)
      除了定位到元素的点击外,也可以通过tab实现坐标的点击
      driver.tap(driver.tap([(216,1776)],2))
           2.TouchAction(driver)
      TouchAction对象包含(tab)、press(短按)、move_to(滑动到某个坐标)等方法
      通过TouchAction对象,添加tap、move_to等操作,然后perform()执行,可以实现解锁屏幕等功能
      规范中的可用事件有:
      * 短按 (press)
      * 释放 (release)
      * 移动到 (moveTo)
      * 点击 (tap)
      * 等待 (wait)
      * 长按 (longPress)
      * 取消 (cancel)
      * 执行 (perform)

    例如:一个多次滑屏的例子:
      action=TouchAction(driver)
      action.press(x=220,y=700).move_to(x=840, y=700).move_to(x=220,
    y=1530).move_to(x=840, y=1530).release().perform()
      可以通过wait()等待操作
      3.MultiAction()//多点触控
      通过MultiAction().add()添加多个TouchAction操作,最后调用perform()一起执行这些操

      action0 = TouchAction().tap(el)
      action1 = TouchAction().tap(el)
      MultiAction().add(action0).add(action1).perform()
      4.driver.swipe(x1, y1, x2, y2,duration)
      //从坐标(x1,x2)滑动到坐标(x2,y2),duration非必填项,滑动时间
      (滑动的坐标不能超过屏幕的宽高)
      可以通过【driver.get_window_size()】命令获得窗口高和宽,结果为{'width': 1080,
    'height': 1776}
      一个鼠标向上下左右活动的例子如下:
    1. #获得屏幕大小宽和高
    2. def getSize(driver):
    3. x = driver.get_window_size()['width']
    4. y = driver.get_window_size()['height']
    5. return (x, y)
    6. #屏幕向上滑动
    7. def swipeUp(driver,t=1000):
    8. l = getSize(driver)
    9. x1 = int(l[0] * 0.5)    #x坐标
    10. y1 = int(l[1] * 0.75)   #起始y坐标
    11. y2 = int(l[1] * 0.25)   #终点y坐标
    12. driver.swipe(x1, y1, x1, y2,t)
    13. #屏幕向下滑动
    14. def swipeDown(driver,t=1000):
    15. l = getSize(driver)
    16. x1 = int(l[0] * 0.5)  #x坐标
    17. y1 = int(l[1] * 0.25)   #起始y坐标
    18. y2 = int(l[1] * 0.75)   #终点y坐标
    19. driver.swipe(x1, y1, x1, y2,t)
    20. #屏幕向左滑动
    21. def swipLeft(driver,t):
    22. l=getSize(driver)
    23. x1=int(l[0]*0.75)
    24. y1=int(l[1]*0.5)
    25. x2=int(l[0]*0.05)
    26. driver.swipe(x1,y1,x2,y1,t)
    27. #屏幕向右滑动
    28. def swipRight(driver,t=1000):
    29. l=getSize(driver)
    30. x1=int(l[0]*0.05)
    31. y1=int(l[1]*0.5)
    32. x2=int(l[0]*0.75)
    33. driver.swipe(x1,y1,x2,y1,t)
    34. #调用向下滑动的方法
    35. swipeDown(driver)
    复制代码
    五、系统按键事件
      press_keycode(AndroidKeyCode)//发送按键事件
      例如:点击home键,home键的KeyCode是3
    1. driver.press_keycode(3)
    2. 键名                  描述       键值
    3. KEYCODE_CALL        拨号键     5
    4. KEYCODE_ENDCALL     挂机键     6
    5. KEYCODE_HOME        按键Home      3
    6. KEYCODE_MENU        菜单键     82
    7. KEYCODE_BACK        返回键     4
    8. KEYCODE_SEARCH      搜索键     84
    9. KEYCODE_CAMERA      拍照键     27
    10. KEYCODE_FOCUS       拍照对焦键   80
    11. KEYCODE_POWER       电源键     26
    12. KEYCODE_NOTIFICATION 通知键        83
    13. KEYCODE_MUTE        话筒静音键   91
    14. KEYCODE_VOLUME_MUTE 扬声器静音键  164
    15. KEYCODE_VOLUME_UP   音量增加键   24
    16. KEYCODE_VOLUME_DOWN 音量减小键   25
    复制代码
    六、driver的一些比较重要操作
      1.reset()
      //重置app
      这时候driver会重置,相当于卸载重装应用。所以本地缓存会失效
      driver.reset()
      2.start_activity(包名,activity名)
      //启动app的某一个activity
      例如:driver.start_activity("com.wuba.zhuanzhuan","./presentation.view.activity.LaunchActivity")
      启动一个activity,这个activity必须是AndroidManifest.xml中有intent-filter的activity
    1. <intent-filter>
    2. <action android:name="android.intent.action.MAIN"/>
    3. <category android:name="android.intent.category.LAUNCHER"/>
    4. </intent-filter>
    复制代码
    这种启动activity和driver的reset()不同的是
      3.contexts
      //获得所有contexts
      driver.contexts
      结果如下:
      ['NATIVE_APP', 'WEBVIEW_com.android.browser']
      NATIVE_APP:native的context
      WEBVIEW_com.android.browser:webview的context,存放html的容器
      4.current_context
      //查看当前的context
      driver.current_context
      5.switch_to.context(context名)
      //切换context
      driver.switch_to.context("WEBVIEW_com.wuba.zhuanzhuan")
      NATIVE时不能定位WEBVIEW的内容,在WEBVIEW的context时不能定位NATIVE的内容。
      所以需要切换到对应的context中去进行操作
      6.setNetworkConnection(bitmask掩码)
      //设置网络类型
      例如:设置网络类型为只开wifi
      driver.set_network_connection(2)
      网络的bitmask掩码如下:
      | 值 (别名)           | 数据连接 | Wifi 连接 | 飞行模式 |
      | ------------------ | ---- | ---- | ------------- |
      | 0 (什么都没有)       | 0    | 0    | 0 |
      | 1 (飞行模式)         | 0    | 0    | 1 |
      | 2 (只有Wifi)        | 0    | 1    | 0 |
      | 4 (只有数据连接)     | 1    | 0    | 0 |
      | 6 (开启所有网络)     | 1    | 1    | 0 |
      7.scroll(起始元素,结束元素)
      driver.scroll(origin_el,destination_el)
      8.获得当前页面的所有元素
      driver.page_source
      这可以用来判断元素是否存在,例如(assert "发布成功" in driver.page_source)
      9.补充一些driver启动时可能用到的项
      其实这些在上一篇启动里都有介绍,但是有些可能大家没注意到的点再列一下。这些点也是
    我在测试中实际遇到的点
      autoLaunch :Appium是否要自动启动或安装app,默认true
      desired_caps['autoLaunch'] = 'false'
      有的时候我不想让appium每次都启动app,想自己去启动activity,那这个项这时就可以起
    作用了
      noReset:在会话前是否重置app状态。默认是false
      desired_caps['noReset'] = 'true'
      newCommandTimeout:设置未接收到新命令的超时时间,默认60s
      如果60s内没有接收到新命令,appium会自动断开连接,如果我需要很长时间做driver之外
    的操作,可能延长接收新命令的超时时间
      desired_caps["newCommandTimeout"]=1800



    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?(注-册)加入51Testing

    x
    分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
    收藏收藏1
    回复

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-9-20 23:29 , Processed in 0.077285 second(s), 25 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

    快速回复 返回顶部 返回列表