zoukankan      html  css  js  c++  java
  • appium自动化常用API

    常用函数

    一、获得信息类API

    (1)获取当前页面的activity名,比如: (.ui.login.ViewPage)

     current_activity()

     比如我们需要实现这个登录的功能时,主要思路为如果当前界面为登录页面时,就进行登录行为,否则就跳转到登录页面。其伪代码为:

    1 if driver.current_activity == ".ui.login.ViewPage":
    2     // To login_action
    3 else:
    4     // Trun to loginPage

    (2)获取当前页面的树形结构源代码,与uiautomatorviewer截屏所展示出来的结构是相同的

     page_source()

    例如当我们完成登录流程之后,要判断登录是否成功,则可以判断登录后的页面有没有出现特定的内容(比如:运动圈、发现、运动、商城、我的),其伪代码实现如下:

    复制代码
    driver  
        .page_source.find(u"运动圈") != -1 and 
        .page_source.find(u"发现") != -1 and 
        .page_source.find(u"运动") != -1 and 
        .page_source.find(u"商城") != -1 and
        .page_source.find(u"我的") != -1 and
    复制代码

    page_source()的返回数据类型为str。python中,str的find(context)方法,如果str存在context返回值为context在str的index,如果不存在,则返回值为-1。因此只需要判断以上代码块返回的布尔值是True or False,就可以判断是否登录成功。

    (3)获取到当前窗口的所有context的名称

     contexts()

     在native和html5混合页面测试时,需要在native层和H5层切换,所以首先需要得到context层级的名称

    print driver.contexts
    >>> ['NATIVE_APP', 'WEBVIEW_com.codoon.gps']

    由此可见,我们知道App的H5层名称为"WEBVIEW_com.codoon.gps"后,使用driver.switch_to.context("WEBVIEW_com.codoon.gps")就可以实现NATIVE和H5层的切换了。

    二、获取控件类API

    (1)通过元素id查找当前页面的一个目标元素

     find_element_by_id()

     通过源码注释可以得到find_element_by_id这一类的api主要有两个使用途径:

    driver.find_element_by_id("com.codoon.gps:id/tv_login")  // from webdriver.py

    在driver下通过id查找一个元素,此用法通常适用于当前界面的driver有且仅有一个唯一的id元素标示,通过调用find_element_by_id可以准确到找到目标元素;另一种使用途径主要如下:

    复制代码

    driver_element = driver.find_element_by_xpath("//android.widget.ListView/android.widget.LinearLayout")

    // from webdriverelement.py

    driver_element.find_element_by_id("com.codoon.gps:id/activity_active_state") 

    复制代码

    在driver.find_element_by_xpath返回了driverElement类型,调用find_element_by_id在driverElement下的子元素以id匹配目标元素。

    上图为uiautomatorviewer对id,name,class的图示说明。特别说明:若id、name、xpath等在当前driver或者driverElement查找的目标元素不是唯一元素,此时调用find_element_by_id(namexpath)时,会返回查找匹配到的第一个元素。

    (2)通过元素id查找当前页面的多个目标元素

     find_elements_by_id()

    在driver下通过id查找多个目标元素,其返回值类型为list。此用法通常适用于当前driver下查询listView、LinearLayout、 RelativeLayout等有相同布局结构的Item;同样除了driver之外,在driverElement下页可以跳用find_elements_by_id来匹配listView、LinearLayout、 RelativeLayout。

    driver.find_elements_by_id("com.codoon.gps:id/tv_name")  // from webdriver.py
    
    driver.find_element_by_id("com.codoon.gps:id/webbase_btn_share")  
      .find_elements_by_id("com.codoon.gps:id/ll_layout") // from driverelement.py

    Tips: 带有find_elements关键字的方法函数的返回类型都是list数据类型,只有driver与driverelement的实例化有find_element(s)等一系列方法,list类型是不能用find_element(s)方法定位数据的。在实际的项目中可能会遇到这样的问题,只有遍历list,取出每一个element实例化对象再进行查找定位元素。

    (3) 通过元素name查找当前页面的一个元素

     find_element_by_name()

    使用方式与find_element_by_id相同,只是把匹配条件由id变为name。请参考find_element_by_id的调用方式

    driver.find_element_by_name("foo")
    driver.find_element_by_id("com.codoon.gps:id/tv_name").find_element_by_name("foo")


    >>> return the driverElement(obj)

    (4) 通过元素name查找当前页面的多个目标元素

     find_elements_by_name()

    使用方式与find_elements_by_id相同,只是把匹配条件由id变为name。请参考find_elements_by_id的调用方式,注意其返回数据类型是List,并不是driverElement。

    driver.find_elements_by_name("foo")
    driver.find_element_by_id("com.codoon.gps:id/tv_name").find_elements_by_name("foo")
    
    ###  return the List<driverElement>
    >>> ['driverElement1', 'driverElement2', 'driverElement3', ....]

    (5)通过元素xpath查找当前页面的一个目标元素

     find_element_by_xpath()

    关于find_element_by_xpath的调用方法与通过id、name略有不同,有关Xpath的相关知识点在本章节暂且不表,后续在项目实践中若有需求再另起专题介绍。

    driver.find_element_by_xpath("//android.widget.TextView[contains(@text, '开始')]")
    driver.find_element_by_xpath("//android.widget.LinearLayout/android.widget.TextView")

    在Appium中,xpath所需相关的lib库并没有完全支持,所以使用方法是以上两种(即仅支持在driver下的xpath匹配)。目前的Appium版本无法支持driverelement下的xpath查找,如

    driver.find_element_by_xpath("//android.widget.LinearLayout/android.widget.TextView")  
    .find_element_by_xpath("//android.widget.TextView[contains(@text, '开始')]") // This is the Error!

     按上面的写法Appium就会报错,原因是“.find_element_by_xpath("//android.widget.TextView[contains(@text, '开始')]")”不能在Element下查找子元素。

    (6) 通过元素xpath查找当前页面的多个目标元素

     find_elements_by_xpath()

     参照find_element_by_xpath的调用方式,需注意返回类型为List,用法参考find_elements_by_name()的例子

    (7) 通过元素class name查找当前页面的的一个元素

     find_element_by_class_name()

    在实际项目中,测试app中class name并不能做为界面的唯一标示定位,所以在实际中几乎没有使用class name在driver查看元素,在driverelement下查找子元素用class name才是正确的使用方式。

    (8) 通过元素accessibility_id (content-desc)查找当前页面的一个元素

     find_element_by_accessibility_id()

    在uiautomatorviewer中,content-desc内容即为accessibility_id,在selenium库里可以用find_element_by_name()来匹配content-desc的内容;在Appium库里则用find_element_by_accessibility_id()来匹配content-desc的内容。因为Appium继承了Selenium类,所以如果find_element_by_name无法准确定位时,请试试看find_element_by_accessibility_id。

       常用的获取控件类API就是以上这些。其他的查找和匹配的api还有find_element_by_link_text、find_elements_by_link_text、find_element_by_tag_name、find_elements_by_tag_name、find_element_by_css_selector、find_elements_by_css_selector等,用法都与上述类似。

    三、元素操作类API

       我们在实现PC端浏览器Webdriver自动化时,对于网页上的目标的操作主要有:点击(click)、 双击(double_click)、滚动(scroll)、输入(send_keys),而移动端特有的辅助类api:轻击(tap)--支持多点触控,滑动(swipe),放大元素(pinch),缩小元素(zoom)

    (1)点击事件 

     click()
     tap()

    click和tap都能实现单击的效果。其区别在于click是作用于driverelement的实例化对象,而tap是对屏幕上的坐标位置进行点击。前者对元素的位置变化并不敏感,而后者是针对具体的像素坐标点击,受分辨率和元素位置影响较大。

    (2)输入事件

     send_keys()
     set_text()

     send_keys和set_text也都能满足输入文本内容的操作。其区别在于send_keys会调用设备当前系统输入法键盘,而set_text直接对目标元素设置文本。由此可推,send_keys的输入内容往往和预期内容不一致,而set_text的输入则是直接赋值,并不是键盘事件。

    (3)滑动(翻屏)事件

     swipe() 
     flick()

    swipe和flick都是滑动操作,它们都是从[start_x, start_y]划到[end_x, end_y]的过程,唯一不同的是swipe比flick多了一个duration参数,有了这个参数就可以自定义从start到end动作的作用时间,以达到快速滑动或者慢速滑动的效果。

    (4)缩放事件

     pinch()
     zoom()

    默认会对目标元素进行放大一倍或者缩小一半的操作,此api方法适合于在测试运动地图的缩放时的变化。

    (5)长按事件

     long_press()

    长按方法是在TouchAction类中,所以在使用时需要先import TouchAction。在删除运动历史记录时,在记录列表长按删除,

    action1 = TouchAction(self.driver)
    driver_element = driver.find_element_by_xpath("sport_history_item_xpath")
    
    action1.long_press(driver_element).wait(i * 1000).perform()   // i为长按控件的时间,单位秒

    (6)keyevent事件(android only)

      在Android keyevent事件中,不同的值代表了不同的含义和功能,比如手机的返回键:keyevent(4); 手机的HOME键: keyevent(3)等等,具体keyevent与对应值关系请参考http://blog.csdn.net/yun90/article/details/51036544 

    四、元素事件类API

    (1) reset

     reset()

    用法:driver.reset(),重置应用(类似删除应用数据),如首次登录app时出现的引导页,则可以用reset来实现需求。

    (2) is_app_installed

     is_app_installed()

    检查app是否有安装 返回 True or False。例如:在微信登录时,选择登录方式时会判断是否已安装微信,若未安装则有dialog弹框,已安装则跳转到微信登录页面,

    driver.find_element_by_id("weixin_login_button").click()
    if driver.is_app_installed("weixin.apk"):
        // To do input User, Passwd
    else:
        // show dialog

    (3)install_app

     install_app()

    接上个例子,若未安装微信出现dialog弹框,检查完dialog后再安装微信app。特别说明:例子中的"weixin.apk"是指app_path + package_name,

    复制代码
    driver.find_element_by_id("weixin_login_button").click()
    if driver.is_app_installed("weixin.apk"):
        // To do input User, Passwd
    else:
        check_dialog()
        driver.install_app("weixin.apk") 
    复制代码

    (4) remove_app

     remove_app()

    在测试老版本兼容用例时,用老版本替换新版本时,需要卸载新版本,再安装老版本,所以需要调用到此方法,

    driver.remove_app("new_app.apk")  # 卸载
    driver.install_app("old_app.apk") # 安装

    (5) launch_app

     launch_app()

    打开一个capabilities配置的设备应用。此方法目前并没有使用。待以后用到时再来做更新。

    (6) close_app

     close_app()

     关闭app应用程序。此方法常用在代码末尾,在清理和释放对象时使用。结合unittest框架常见tearDown()里使用,

    复制代码
    import unittest
    
    class demo(unittest.TestCase):
        def setUp(self):
            pass
        
        def tearDown(self):
            driver.close_app()
            driver.quit()
    复制代码

    (7) start_activity

     start_activity()

    此方法适用于测试中需使用两个及以上的app程序。例如,在运动相关的测试时,首先需要打开Gps模拟打点工具,开始打点。然后打开咕咚选择运动类型开始运动,那么可以在启动capabilities配置时打开Gps工具,开启配速打点后再打开咕咚app,

    复制代码
    driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps={'platformName': 'Android',
                            'deviceName': 'Android Mechine',
                            'appPackage': ' Package of GpsTools',
                            'unicodeKeyboard':True,
                            'resetKeyboard':True,
                            'noReset':True,
                            'appActivity': 'activity of GpsTools'})
    
    # TO DO Gps Mock action
    
    driver.start_activity("com.codoon.gps", "ui.login.welcomeActivity")
    复制代码

      

    (8) wait_activity

     wait_activity()

    此方法适属于appium等待方法的一种。不论是webdriver还是appium,等待方法分为三种类型:显式等待、隐式等待,time.sleep;从wait_activity的源码可以看出,是属于隐式等待。有关等待方式以后可以另开专题详细说明,这里不做赘述。

      此方法主要使用在需要网络加载时的等待,比如在用户登录作为前提条件时,wait_activity接受三个参数: 需要等待加载的activity的名称,timeout超时时间(秒),检测间隔时间(秒),

    driver.login_action()
    driver.wait_activity("homepage.activity", 30, 1)
    driver.find_element_by_id("我的").click()

    其含义是,等待加载app的homepage的activity出现,等待最长时间30秒,每隔1秒检测一次当前的activity是否等于homepage的activity。若是,则推出等待,执行点击我的tab的action;若否,则继续等待,30秒后提示超时抛出异常。

    四、其他(此类别下主要对上述没有提到的api方法的补充)

    (1) 截屏

     get_screenshot_as_file()

    用法:driver.get_screenshot_as_file('../screenshot/foo.png'),接受参数为保存的图片路径和名称

    (2)size 和 location

     size()
     location()

    size 和 location是对element位置和尺寸的获取,这两个属性主要运用在有可划动的控件,如完善个人资料页,生日、身高和体重都需要划动。之前我们提到的swipe和flick是针对设备屏幕进行划动,显然在这里不适用。而且没有一个特定的方法,所以需要我们自己针对可划动控件进行划动,

     swipe_control()

    (3)获取控件各种属性

     View Code

    用法: driver.find_element_by_id().get_attribute(name),name即是左侧的标志(class,package,checkable,checked....),返回值为str类型,即便是true or false,但是其实是"true" or "false"

     

    (4)pull_file

     pull_file()

    将设备上的文件pull到本地硬盘上,在手机号注册时需要获取手机验证码,此时的实现方式是用另一个apk提取到验证码存在手机内存中,再用pull_file获取到验证码内容,使得appium可以将正确的验证码填入。

      

      本章节Appium常用的一些API函数,日后有需要会慢慢地进行补充。虽然不能面面俱到,但在实际项目中涉及到的都已经差不多提到了。当我们对某个功能进行测试的时候,首先要对其进行操作,这个时候就要考虑到找到相应的对象元素,调用具体的事件类函数,验证结果的时候,我们要检测操作产生的结果是不是与我们预期的一致?那这就要去考虑相应的Assert函数(即断言)了。所以记住这六字箴言:对象-事件-断言,便可以使你可以着手对任何一个App编写对应的自动化测试用例了。

  • 相关阅读:
    bzoj3505 数三角形 组合计数
    cogs2057 殉国 扩展欧几里得
    cogs333 荒岛野人 扩展欧几里得
    bzoj1123 BLO tarjan求点双连通分量
    poj3352 road construction tarjan求双连通分量
    cogs1804 联合权值 dp
    cogs2478 简单的最近公共祖先 树形dp
    cogs1493 递推关系 矩阵
    cogs2557 天天爱跑步 LCA
    hdu4738 Caocao's Bridge Tarjan求割边
  • 原文地址:https://www.cnblogs.com/dreamhighqiu/p/10989994.html
Copyright © 2011-2022 走看看