appium自动化经常使用API

经常使用函数css

1、得到信息类API

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

  current_activity()

 好比咱们须要实现这个登陆的功能时,主要思路为若是当前界面为登陆页面时,就进行登陆行为,不然就跳转到登陆页面。其伪代码为:html5

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

 

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

  page_source()

例如当咱们完成登陆流程以后,要判断登陆是否成功,则能够判断登陆后的页面有没有出现特定的内容(好比:运动圈、发现、运动、商城、个人),其伪代码实现以下:android

复制代码
复制代码
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,就能够判断是否登陆成功。web

 

(3)获取到当前窗口的全部context的名称api

  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层的切换了。微信

 

2、获取控件类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(name\xpath)时,会返回查找匹配到的第一个元素。

 

(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等,用法都与上述相似。

 

3、元素操做类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 

 

4、元素事件类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秒后提示超时抛出异常。

 

4、其余(此类别下主要对上述没有提到的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编写对应的自动化测试用例了。