转载:Appium 简明教程:http://www.testclass.net/appium
https://www.cnblogs.com/fnng/p/4540731.html
Appium 官网:http://appium.io/
Github 地址:https://github.com/appium/appium
主要包括以下几部分:
- appium新手入门(1) —— appium介绍
- appium新手入门(2) —— 安装 Android SDK
- appium新手入门(3) —— 安装 appium Server
- appium新手入门(4) —— java-client安装与测试
- appium新手入门(5) —— python-client安装与测试
- appium新手入门(6) —— appium-desktop
- appium新手入门(7) —— Desired Capabilities
- appium新手入门(8) —— 定位控件
- appium新手入门(9) —— appium API 之应用操作
- appium新手入门(10)—— appium API 之上下文操作
- appium新手入门(11)—— appium API 之键盘操作
- appium新手入门(12)—— appium API 之 TouchAction 操作
- appium新手入门(13)—— appium API 之其他操作
1. appium 介绍
什么是 appium?
下面这段介绍来自于 appium 的官网。
Appium is an open-source tool you can use to automate mobile native, mobile web, and mobile hybrid applications on iOS and Android platforms. “Mobile native apps” are those written using the iOS or Android SDKs. “Mobile web apps” are web apps accessed using a mobile browser (Appium supports Safari on iOS and Chrome on Android). “Mobile hybrid apps” have a native wrapper around a “webview” – a native control that enables interaction with web content. Projects like Phonegap, for example, make it easy to build apps using web technologies that are then bundled into a native wrapper – these are hybrid apps.
Importantly, Appium is “cross-platform”: it allows you to write tests against multiple platforms (iOS, Android), using the same API. This enables a large or total amount of code reuse between iOS and Android testsuites.
我们可以从上面的介绍里获得这样的一些信息:
- 1,appium 是开源的移动端自动化测试框架;
- 2,appium 可以测试原生的、混合的、以及移动端的 web 项目;
- 3,appium 可以测试 ios,android 应用(当然了,还有 firefox os);
- 4,appium 是跨平台的,可以用在 osx,windows 以及 linux 桌面系统上;
appium 的哲学
Appium was designed to meet mobile automation needs according to a certain philosophy. The key points of this philosophy can be stated as 4 requirements:
You shouldn’t have to recompile your app or modify it in any way in order to automate it. You shouldn’t be locked into a specific language or framework to write and run your tests. A mobile automation framework shouldn’t reinvent the wheel when it comes to automation APIs. A mobile automation framework should be open source, in spirit and practice as well as in name!
appium 的设计哲学是这样的:
- 1,不需要为了自动化而且重新编译或修改测试app;
- 2,不应该让移动端自动化测试限定在某种语言和某个具体的框架;也就是说任何人都可以使用自己最熟悉最顺手的语言以及框架来做移动端自动化测试;
- 3,不要为了移动端的自动化测试而重新发明轮子,重新写一套惊天动地的 api;也就是说 webdriver 协议里的 api 已经够好了,拿来改进一下就可以了;
- 4,移动端自动化测试应该是开源的;
appium 的技术架构
- iOS: Apple’s UIAutomation
- Android 4.2+: Google’s UiAutomator
- Android 2.3+: Google’s Instrumentation. (Instrumentation support is provided by bundling a separate project, Selendroid)
appium 的设计思想
We meet requirement #2 by wrapping the vendor-provided frameworks in one API, theWebDriver API. WebDriver (aka “Selenium WebDriver”) specifies a client-server protocol (known as the JSON Wire Protocol). Given this client-server architecture, a client written in any language can be used to send the appropriate HTTP requests to the server. There are already clients written in every popular programming language. This also means that you’re free to use whatever test runner and test framework you want; the client libraries are simply HTTP clients and can be mixed into your code any way you please. In other words, Appium & WebDriver clients are not technically “test frameworks” – they are “automation libraries”. You can manage your test environment any way you like!
We meet requirement #3 in the same way: WebDriver has become the de facto standard for automating web browsers, and is a W3C Working Draft. Why do something totally different for mobile? Instead we have extended the protocol with extra API methods useful for mobile automation.
It should be obvious that requirement #4 is a given – you’re reading this because Appium is open source.
首先,为了能够实现哲学里描述的第2条,也就是不应该让移动端自动化测试限定在某种语言和某个具体的框架;也就是说任何人都可以使用自己最熟悉最顺手的语言以及框架来做移动端自动化测试;appium选择了client-server的设计模式。只要client能够发送http请求给server,那么的话client用什么语言来实现都是可以的,这就是appium及webdriver如何做到支持多语言的;
其次,为了能够实现不要为了移动端的自动化测试而重新发明轮子,重新写一套惊天动地的api;也就是说webdriver协议里的api已经够好了,拿来改进一下就可以了;这个思想,appium扩展了webdriver的协议,没有自己重新去实现一套。这样的好处是以前的webdriver api能够直接被继承过来,以前的webdriver各种语言的binding都可以拿来就用,省去了为每种语言开发一个client的工作量;
最后 appium 当然是开源的,这也实现了哲学思想里的最后一点。
1、特点
appium 是一个自动化测试开源工具,支持 iOS 平台和 Android 平台上的原生应用,web应用和混合应用。
-
“移动原生应用”是指那些用iOS或者 Android SDK 写的应用(Application简称app)。
-
“移动web应用”是指使用移动浏览器访问的应用(appium支持iOS上的Safari和Android上的 Chrome)。
-
“混合应用”是指原生代码封装网页视图——原生代码和 web 内容交互。比如,像 Phonegap,可以帮助开发者使用网页技术开发应用,然后用原生代码封装,这些就是混合应用。
重要的是,appium是一个跨平台的工具:它允许测试人员在不同的平台(iOS,Android)使用同一套API来写自动化测试脚本,这样大大增加了iOS和Android测试套件间代码的复用性。
2、appium 与 Selenium
appium类库封装了标准Selenium客户端类库,为用户提供所有常见的JSON格式selenium命令以及额外的移动设备控制相关的命令,如多点触控手势和屏幕朝向。
appium客户端类库实现了Mobile JSON Wire Protocol(一个标准协议的官方扩展草稿)和W3C WebDriver spec(一个传输不可预知的自动化协议,该协议定义了MultiAction 接口)的元素。
appium服务端定义了官方协议的扩展,为appium 用户提供了方便的接口来执行各种设备动作,例如在测试过程中安装/卸载App。这就是为什么我们需要appium特定的客户端,而不是通用的Selenium 客户端。当然,appium 客户端类库只是增加了一些功能,而实际上这些功能就是简单的扩展了Selenium 客户端,所以他们仍然可以用来运行通用的Selenium会话。
3、支持多平台、多语言
appium 是跨平台的,可以用在OSX,Windows以及Linux桌面系统上运行。
appium选择了Client/Server的设计模式。只要client能够发送http请求给server,那么的话client用什么语言来实现都是可以的,这就是appium及Selenium(WebDriver)如何做到支持多语言的原因;
appium 扩展了 WebDriver 的协议,没有自己重新去实现一套。这样的好处是以前的 WebDriver API 能够直接被继承过来,以前的 Selenium(WebDriver)各种语言的 binding 都可以拿来就用,省去了为每种语言开发一个 client 的工作量;
语言/框架 | Github地址 |
---|---|
Ruby | https://github.com/appium/ruby_lib |
Python | https://github.com/appium/python-client |
Java | https://github.com/appium/java-client |
JavaScript (Node.js) | https://github.com/admc/wd |
Objective C | https://github.com/appium/selenium-objective-c |
PHP | https://github.com/appium/php-client |
C# (.NET) | https://github.com/appium/appium-dotnet-driver |
RobotFramework | https://github.com/jollychang/robotframework-appiumlibrary |
4、appium 工作原理
在安装和介绍 appium 之前,非常有必要介绍一下appium是如何工作的。
通过上面一张图简单展示了 appium 的工具原理。
- 首先,appium 支持多语言,因为它针对流的几种语言分别开发的相应的 appium 库。好处就是我们可以选择自己熟悉的语言编写 appium 脚本。
- 其次,appium 支持多平台,包括 MAC 和 Windows。它针对这两大平台开发了 appium-Server。
- 最后,appium 又同时支持 Android 和 iOS 两个操作系统。这就使得 appium 变得非常灵活。
当我在 MAC 平台上,通过 Python(python-client )编写了一个appium自动化脚本并执行,请求会首先到 appium.dum (MAC下的 appium-Server),appium-Server 通过解析,驱动 iOS 设备来执行 appium 自动化脚本。
或者,我在 Windows 平台上,通过 Java( java-client )编写了一个 appium 自动化脚本并执行,请求会首先到 appiumForWindow.zip(Window下的appium-Server),appium-Server通过解析,驱动Android虚拟机或真机来执行appium脚本。
所以,你会看到 appium 的强大之处就在于此。
5、你都需要安装什么?
这才是你最关心的问题,使用 appium 都需要安装些什么?其实,从 appium 工作原理你就应该知道需要装什么了。
编程语言
- 想用 Python 的同学,点这里 :http://www.testclass.net/selenium_python/install-selenium/
- 想用 Java 的同学,点这里 :http://www.testclass.net/selenium_java/install-java/
appium client
- 参考 3、支持多平台、多语言 的列表,根据你选择的语言来选择对应的 appium-client。
appium Server
- 参考 4、appium工作原理 的介绍,根据你的系统平台选择 对应的 appium-server。
测试运行环境
- 你需要一个 Android 模拟器,或 一个 Android 手机,或 一台 iPhone 手机。
appium 的基本概念
Client / Server Architecture
appium 的核心其实是一个暴露了一系列REST API的server。
这个server的功能其实很简单:监听一个端口,然后接收由client发送来的command。翻译这些command,把这些command转成移动设备可以理解的形式发送给移动设备,然后移动设备执行完这些command后把执行结果返回给appium server,appium server再把执行结果返回给client。
在这里client其实就是发起command的设备,一般来说就是我们代码执行的机器,执行appium测试代码的机器。狭义点理解,可以把client理解成是代码,这些代码可以是java/ruby/python/js的,只要它实现了webdriver标准协议就可以。
这样的设计思想带来了一些好处:
- 1,可以带来多语言的支持;
- 2,可以把server放在任意机器上,哪怕是云服务器都可以;(是的,appium和webdriver天生适合云测试)
Session
session就是一个会话,在webdriver/appium,你的所有工作永远都是在session start后才可以进行的。一般来说,通过POST /session这个URL,然后传入Desired Capabilities就可以开启session了。
开启session后,会返回一个全局唯一的session id,以后几乎所有的请求都必须带上这个session id,因为这个seesion id代表了你所打开的浏览器或者是移动设备的模拟器。
进一步思考一下,由于session id是全局唯一,那么在同一台机器上启动多个session就变成了可能,这也就是selenium gird所依赖的具体理论根据。
Desired Capabilities
Desired Capabilities携带了一些配置信息。从本质上讲,这个东东是key-value形式的对象。你可以理解成是java里的map,python里的字典,ruby里的hash以及js里的json对象。实际上Desired Capabilities在传输时就是json对象。
Desired Capabilities最重要的作用是告诉server本次测试的上下文。这次是要进行浏览器测试还是移动端测试?如果是移动端测试的话是测试android还是ios,如果测试android的话那么我们要测试哪个app? server的这些疑问Desired Capabilities都必须给予解答,否则server不买账,自然就无法完成移动app或者是浏览器的启动。
具体例子如下:
For example, we might set the platformName capability to iOS to tell Appium that we want an iOS session, rather than an Android one. Or we might set the safariAllowPopupscapability to true in order to ensure that, during a Safari automation session, we’re allowed to use JavaScript to open up new windows. See the capabilities doc for the complete list of capabilities available for Appium
Appium Server
这就是每次我们在命令行用 appium 命令打开的东西。
Appium Clients
由于原生的 webdriver api 是为 web 端设计的,因此在移动端用起来会有点不伦不类。appium 官方提供了一套 appium client,涵盖多种语言 ruby/java/python,在我看来 ruby client 是实现最好的。在测试的时候,一般要使用这些 client 库去替换原生的webdriver 库。这实际上不是替换,算是 client 对原生 webdriver 进行了一些移动端的扩展,加入了一些方便的方法,比如 swipe之类,appium client 让我们可以更方便的写出可读性更好的测试用例。
Appium.app、Appium.exe
appium server 的 GUI 版本,前者用在 osx 上,后者是 windows 上。可视化、不需要装 node,可以看 app 的 UI 结构是这个东东的卖点。
2. 安装 Android SDK
Android SDK(Software Development Kit,软件开发工具包)提供了 Android API 库和开发工具构建,测试和调试应用程序。简单来讲,Android SDK 可以看做用于开发和运行 Android 应用的一个软件。
1、下载 Android SDK
我在官网上没有找到单独 Android SDK 的下载链接,官方推荐下载包含 Android SDK 的 Android Studio。
Android Studio & Android SDK 下载地址:https://developer.android.google.cn/studio/
一方面是包含 Android SDK 的 Android Studio 的安装包很大。另一方面它们二者也不是强关联的。因为 Appium 也会用到 Android SDK,而 Android Studio 也可以调用真机来运行 Android 程序。
所以,Android SDK 下载地址(才是我们想要的):http://tools.android-studio.org/index.php/sdk
你可以通过别的网站进行下载,身为IT从业人员,如何利用搜索工具和科学上网工具是你的必备技能。
将下载的 Android SDK 解压,将得到如下目录。
图 Android SDK目录
2、设置 Android 环境变量
下面设置 Android 环境变量,方法与Java环境变量类似。我本机的目录结果为:
D:\android\android-sdk-windows
下面设置环境变量:
“我的电脑” 右键菜单 ---> 属性 ---> 高级 ---> 环境变量 ---> 系统变量 ---> 新建...
变量名 | 变量值 |
---|---|
ANDROID_HOME | D:\android\Android\sdk |
找到 path 变量名—> “编辑” 添加:
变量名 | 变量值 |
---|---|
PATH | ;%ANDROID_HOME%\platform-tools;%ANDROID_HOME%\tools; |
3、安装 Android 版本
双击 SDK Manage.exe 启动 SDK 管理器。
你需要科学上网,或者查找到国内的 Android 镜像,安装一个版本的 Android 虚拟机。你可以根据自己的喜好选择安装 Android 5.0 /5.1 /6.0 /7.0 版本。
这里推荐一个网站:http://www.androiddevtools.cn/
4、创建 Android 虚拟机
双击 AVD Manage.exe 启动AVD管理器。
点击 “Create...” 按钮,创建Android虚拟机。
不要选择超过电脑屏幕分辨率的 Device,其它选项参考上图。点击 “OK” 创建完成。在 AVD Manage 工具中选中创建的Android虚拟机,点击 “Start...” 按钮启动。
Android 模拟器已经启动。
3. 安装 appium Server
windows 依赖:
-
安装 nodejs 通过官方的安装程序来安装。
-
安装 android 的 sdk 包,(http://developer.android.com/sdk/index.html),运行依赖sdk中的'android'工具。并确保你安装了Level17或以上的版本api。设置 ANDROID_HOME 系统变量为你的 Android SDK 路径,并把 tools platform-tools 两个目录加入到系统的 Path 路径里。因为这里面包含有一些执行命令
-
安装 java 的 JDK,并设置 JAVA_HOME 变量为你的 JDK 目录。
appium 官网下载:http://appium.io/downloads.html
下载 Appium-windows-1.18-1.zip 解压即可
可以创建 Appium.exe 的快捷方式放到桌面上,双击启动,appium server 界面如下。
点击 Start Server,
Appium-Server 已经可以打开了。至于 Appium 的使用我们放到后面的章节进行介绍。
4. appium client 的安装
appium client 是对 webdriver 原生 api 的一些扩展和封装。它可以帮助我们更容易的写出用例,写出更好懂的用例。
appium client 是配合原生的 webdriver 来使用的,因此二者必须配合使用缺一不可。
内容将涵盖3个语言,ruby/python/java。
安装 appium client
ruby 篇(一定要在线安装)
ruby 的 appium client 叫做 appium lib,为什么是这样就不解释了,总之是历史原因。
首先 update rubygem 和 bundler (说老实话,真的不需要,但官方文档上这么写)
gem update --system ;\
gem update bundler
然后使用gem安装
gem uninstall -aIx appium_lib ;\(这个也不是必须的)
gem install --no-rdoc --no-ri appium_lib
python篇(尽量在线安装)
推荐使用 pip 安装
pip install Appium-Python-Client
当然了也可以在 Pipy 上下载源码安装
tar -xvf Appium-Python-Client-X.X.tar.gz(windows上用7zip可以解压)
cd Appium-Python-Client-X.X
python setup.py install
最后,也可以通过 github 安装(要 git 客户端)
git clone git@github.com:appium/python-client.git
cd python-client
python setup.py install
运行第一个 Appium 测试
第一步,启动 Android 模拟器。
第二步,启动 Appium Server。Appium 在启动时默认占用本机的 4723 端口,即:127.0.0.1:4723
第三步,编写 appnium 测试脚本。
#coding=utf-8
from appium import webdriverdesired_caps = {}
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '6.0'
desired_caps['deviceName'] = 'Android Emulator'
desired_caps['appPackage'] = 'com.android.calculator2'
desired_caps['appActivity'] = '.Calculator'driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)driver.find_element_by_name("1").click()driver.find_element_by_name("5").click()driver.find_element_by_name("9").click()driver.find_element_by_name("delete").click()driver.find_element_by_name("9").click()driver.find_element_by_name("5").click()driver.find_element_by_name("+").click()driver.find_element_by_name("6").click()driver.find_element_by_name("=").click()driver.quit()
运行上面的脚本,你将会看到 Android 模拟器如下运行界面:
java 篇(在线安装)
java-client 安装与测试:http://www.testclass.net/appium/appium-base-java/
java 的话用 maven 安装就可以了
<dependency><groupId>io.appium</groupId><artifactId>java-client</artifactId><version>1.3.0</version>
</dependency>
当然了,也可以自己下载jar包,请自行选择最新版本。
5. appium client 方法一览
appium client 扩展了原生的 webdriver client 方法
下面以 java 代码为例,简单过一下 appium client 提供的适合移动端使用的新方法
resetApp()
getAppString()
sendKeyEvent()
currentActivity()
pullFile()
pushFile()
pullFolder()
hideKeyboard()
runAppInBackground()
performTouchAction()
performMultiTouchAction()
tap()
swipe()
pinch()
zoom()
getNamedTextField()
isAppInstalled()
installApp()
removeApp()
launchApp()
closeApp()
endTestCoverage()
lockScreen()
shake()
complexFind()
scrollTo()
scrollToExact()
openNotifications()
Context Switching: .context(), .getContextHandles(), getContext())
新增的 locator
findElementByAccessibilityId()
findElementsByAccessibilityId()
findElementByIosUIAutomation()
findElementsByIosUIAutomation()
findElementByAndroidUIAutomator()
findElementsByAndroidUIAutomator()
这些方法主要覆盖了3大类:
- driver 扩展:比如增加了resetApp等操作 app 的方法
- action 扩展:增加一些移动端的特有的 action(怎么描述呢,相当于是移动端 特有的操作),比如 swipe,shake (嗯,有了这个方法就可以让代码帮你摇一摇了) 等;
- locator 扩展:增加了一些移动端专属的定位策略
6. appium-desktop 和 appium
appium-desktop 和 appium 这两个只要有一个安装好就可以,区别是:
- appium-desktop 是带 GUI 界面
- appium 是命令行,不带 GUI 界面
appium-desktop
什么是 Appium-desktop?
项目地址:https://github.com/appium/appium-desktop
项目描述:
Appium Server and Inspector in Desktop GUIs for Mac, Windows, and Linux。
Appium 移动测试中有个很重新的组件 Appium-Server,它主要用来监听我们的移动设备(真机或模拟器),然将不同编程语言编写的 appium 测试脚本进行解析,然后,驱动移动设备来运行测试。
但Appium-Server有一两年没有更新了。Windows版在 2015 年底止步于的 AppiumForWindows_1_4_16_1.zip
于是,新的工具 Appium-desktop 来了! 它来继续 Appium-Server的使命,当然, Appium-Server当前仍然是可用的。
下载与安装
appium-desktop 下载地址:这里
根据自己的平台选择相关的包进行下载。本文以 Windows 为例,所以选择 appium-desktop-Setup-1.2.4.exe 文件进行下载。
安装过程太简单了,双击 exe 文件,然后,等待安装完就好了,中间都不需要你设置任何选项。所以,这里就不贴图了。
启动运行
安装完成桌面会生成一个紫色的 appium 图标,双击打开。
默认显示监控的 host 和 port ,这和 Appium-Server中是一致的。点击 “Start Server V 1.7.1” 按钮启动服务。
现在启动 启动你的移动设备(真机或模拟器),编写 Appium 自动化测试脚本,可以通过 Appium-desktop 来运行测试了。
至于 Appium-Server , 你可以把它卸载了!
appium
启动 appium 及 android 模拟器
一般情况下,我们都从命令行启动 appium。
windows下,dos 命令窗口输入
appium
如果该命令报错,那么请重装 appium
npm install -g appium
如果安装出错,请使用淘宝源。
淘宝源地址:http://npm.taobao.org/
然后请打开 android 的模拟器,如果没有请新建一个虚拟设备。请自行解除设备锁定(手动把屏幕解锁了),以防万一。
下面的代码以启动android原生的计算器程序为例
ruby篇
require 'appium_lib'caps = { caps: { platformName: 'Android', appActivity: '.Calculator', appPackage: 'com.android.calculator2' },appium_lib: { sauce_username: nil, sauce_access_key: nil } }
driver = Appium::Driver.new(caps).start_driver
讨论:可以看出ruby lib里面的Appium::Driver类实际上就是原生的webdriver类的子类,当然了,由于ruby语法灵活,也可以使用monkey patch来实现类似功能。
python篇
from appium import webdriver
desired_caps = {}
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '4.2'
desired_caps['deviceName'] = 'Android Emulator'
desired_caps['appPackage'] = 'com.android.calculator2'
desired_caps['appActivity'] = '.Calculator'driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
讨论:webdriver.Remote实际上就是原生webdriver的子类,另外Remote()构造函数的第一个参数中需要显示指定appium server监听的端口
java篇
新建 java 项目时候,请注意将 selenium-webdriver 以及 appium client 的 jar 包导入
import io.appium.java_client.AppiumDriver;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability(CapabilityType.BROWSER_NAME, "");//这句不是必须的
capabilities.setCapability("deviceName","Android Emulator");
capabilities.setCapability("platformVersion", "4.4");
capabilities.setCapability("platformName","Android");
capabilities.setCapability("appPackage", "com.android.calculator2");
capabilities.setCapability("appActivity", ".Calculator");
AppiumDriver driver = new AppiumDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
讨论:AppiumDrvier 是原生 webdriver 的子类。
在这里我们可以看到,新建driver的时候必须要指定一个DesiredCapabilities 对象,该对象究竟是何方神圣,下面会仔细讲解。
7. Desired Capabilities
Desired Capabilities 是在启动 session 的时候是必须提供的。
Desired Capabilities 本质上是以 key value 字典的方式存放,客户端将这些键值对发给服务端,告诉服务端我们想要怎么测试。它告诉 appium Server 这样一些事情:
- 本次测试是 启动浏览器 还是 启动移动设备。
- 是启动 Andorid 还是启动iOS。
- 启动Android时,app的package是什么。
- 启动Android时,app的activity是什么。
- ...
Desired Capabilities 配置
Appium 的 Desired Capabilities 基本配置如下:
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("deviceName", "Android Emulator");
capabilities.setCapability("automationName", "Appium");
capabilities.setCapability("platformName", "Android");
capabilities.setCapability("platformVersion", "5.1");
capabilities.setCapability("appPackage", "com.android.calculator2");
capabilities.setCapability("appActivity", ".Calculator");WebDriver driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
参数说明:
- deviceName:启动哪种设备,是真机还是模拟器?iPhone Simulator,iPad Simulator,iPhone Retina 4-inch,Android Emulator,Galaxy S4...
- automationName:使用哪种自动化引擎。appium(默认)还是Selendroid。
- platformName:使用哪种移动平台。iOS, Android, orFirefoxOS。
- platformVersion:指定平台的系统版本。例如指的Android平台,版本为5.1。
- appActivity:待测试的app的Activity名字。比如MainActivity、.Settings。注意,原生app的话要在activity前加个"."。
- appPackage:待测试的app的Java package。比如com.example.android.myApp, com.android.settings。
更多的参数配置 ,参考 这里:https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/caps.md
8. 定位控件
辅助工具
定位控件首先需要使用一些辅助工具,对于appium实战android来说,下面的这些工具(以windows系统为例)是必须熟练使用的。
- monitor.bat(hierarchyviewer.bat 已经不赞成继续使用了):该文件位于 your_andriod_sdk_path\tools 下面(我本机路径是:D:\SoftWare\AndroidSDK\tools)。该工具可以帮我们找到 android 控件的 content-description,为以后的 find_element_by_accessibility_id 定位方法做参数使用。关于什么是 content-description,可以参考官方文档。
- uiautomatorviewer.bat:该文件位于 your_andriod_sdk_path\tools下面( 我本机路径:D:\SoftWare\AndroidSDK\tools\bin )。该工具主要用来查看控件的属性,比如 resource id,class name 等。该工具也可查看被测 app 的 appPackage( Desired Capabilities 中使用 )。
如何获取 android app 的 Activity
获取 appPackage 和 appActivity:https://blog.csdn.net/mtbaby/article/details/78676477
- linux/mac:adb dumpsys activity activities | grep mFocusedActivity
- for windows: adb dumpsys activity activities | findstr mFocusedActivity
控件定位基础
控件的特征就是控件的属性,可以通过 uiautomatorviewer 去获取。
在 appium 的定位世界里,下面这些方法是可以为我们使用的。也就是说,我们通过下面几个约定好的方式,按照webdriver和appium的DSL(自行搜索并理解)进行控件特征的描述和定位。
继承自webdriver的方法,也就是通过这3个特征可以定位控件
- find by "class" (i.e., ui component type,andorid上可以是android.widget.TextView)
- find by "xpath" (i.e., an abstract representation of a path to an element, with certain constraints,由于appium的xpath库不完备的原因,这个不太推荐)
- find by "id"(android上是控件的resource id)
由Mobile JSON Wire Protocol 协议中定义的方法,更适合移动设备上的控件定位
- -ios uiautomation: a string corresponding to a recursive element search using the UIAutomation library (iOS-only)
- -android uiautomator: a string corresponding to a recursive element search using the UiAutomator Api (Android-only)
- accessibility id: a string corresponding to a recursive element search using the Id/Name that the native Accessibility options utilize.
在 appium 的 client 对 Mobile JSON Wire Protocol 中定义的方法进行了封装,使其调用起来更加方便
ruby篇
find_element :accessibility_id, 'Animation'
find_elements :accessibility_id, 'Animation'
find_element :uiautomator, 'new UiSelector().clickable(true)'
find_elements :uiautomator, 'new UiSelector().clickable(true)'
当然了,你也可以使用原生的webdriver方法
find_element id: 'resource_id'
另外,ruby lib里提供了一些非常好用的简便方法来进行控件的定位,好写,好读。
- text(value_or_index) :Find the first TextView that contains value or by index. If int then the TextView at that index is returned.
- button(value_or_index):Find the first button that contains value or by index. If int then the button at that index is returned
更多请看 这里
python篇
el = self.driver.find_element_by_android_uiautomator('new UiSelector().description("Animation")')
self.assertIsNotNone(el)
els = self.driver.find_elements_by_android_uiautomator('new UiSelector().clickable(true)')
self.assertIsInstance(els, list)el = self.driver.find_element_by_accessibility_id('Animation')
self.assertIsNotNone(el)
els = self.driver.find_elements_by_accessibility_id('Animation')
self.assertIsInstance(els, list)
总的来说就是在 driver 里增加了
- find_element_by_accessibility_id
- find_elements_by_accessibility_id
- find_element_by_android_uiautomator
- find_elements_by_android_uiautomator
等方法
java篇
前面也讲过了,新增了这些方法
findElementByAccessibilityId()
findElementsByAccessibilityId()
findElementByIosUIAutomation()
findElementsByIosUIAutomation()
findElementByAndroidUIAutomator()
findElementsByAndroidUIAutomator()
讨论:从上面可以看出来,python 和 java client对移动端控件定位的封装是比较初级的。ruby lib中封装了很多方便和简洁的方法,因此可以看出,使用ruby lib是优于python和java的选择。当然,如果忽略性能的话。
控件定位
appium 通过 uiautomatorviewer.bat 工具来查看控件的属性。该工具位于 Android SDK 的 /tools/bin/ 目录下。
id 定位
通过 uiautomatorviewer.bat 工具可以查看对象的 id 属性。
如果目标设备的 API Level 低于18则 UIAutomatorViewer 不能获得对应的 Resource ID,只有等于大于18的时候才能使用。
打开 uiautomatorviewer.bat 工具:
resource-id 就是我们理解的 id 属性了。
使用方法:
driver.findElement(By.id("com.android.calculator2:id/formula"))
name 定位
打开 uiautomatorviewer.bat 工具:
text 就是我们要查找的 name 了,为什么在命名上毫无关联啊!
使用方法:
driver.findElement(By.name("9"))
class name 定位
计算器界面上的的 class 属性是:android.widget.Button。 使用方法:
WebElement button = driver.findElement(By.className("android.widget.Button"));
使用 Class Name 一般获得的 view 都不止一个,所以应该需要遍历一遍得到的 views,然后缩小搜索条件来获得目标控件。
XPath 定位
在 WebDriver 上 XPath 定位是功能强大的一种定位方式。我个人惯用于此方法来定位Web页面上的元素。下面看看在 Android 上 XPath 定位的用法。
用 class 的属性来替代做标签的名字。
使用方法:
driver.findElement(By.xpath("//android.view.ViewGroup/android.widget.Button")) //7
当果如果出现 class 相同的情况下可以用控件的属性值进行区分。
java driver.findElement(By.xpath("//android.widget.Button[contains(@text,'7')]")).click(); //7
driver.findElement(By.xpath("//android.widget.Button[contains(@content-desc,'times')]")).click(); //*
driver.findElement(By.xpath("//android.widget.Button[contains(@text,'7')]")).click(); //7
driver.findElement(By.xpath("//android.widget.Button[contains(@content-desc,'equals')]")).click(); //=
XPath 在 Appium 上的用法依然很强大,有时需要写更臭更长的定位语法,因为APP上元素的class命令本来就长,再加上多层级,结果可想而知。
Accessibility ID 定位
这个方法属于 Appium 扩展的定位方法。
其实,我们的核心是要找到元素的 contentDescription 属性。它就是元素的 content-desc 。
使用方法:
java driver.findElementByAccessibilityId("plus").click();
android uiautomator 定位
这个方法也属于 Appium(Android)扩展的定位方法。同样使用 UIAutomatorViewer.bat 工具直接查看。
也就是说一个元素的任意属性都可以通过 android uiautomator 方法来进行定位,但要保证这种定位方式的唯一性。
使用方法:
driver.findElementByAndroidUIAutomator("new UiSelector().text(\"clr\")").click();
driver.findElementByAndroidUIAutomator("new UiSelector().text(\"8\")").click();
driver.findElementByAndroidUIAutomator("new UiSelector().description(\"plus\")").click();
driver.findElementByAndroidUIAutomator("new UiSelector().text(\"5\")").click();
driver.findElementByAndroidUIAutomator("new UiSelector().description(\"equals\")").click();
需要注意的是 description() 方法用的是 content-desc 属性。
9. appium API 之应用操作
罗列的方法主要针对应用的操作,如应用的安装、卸载、关闭、启动等。
1、安装应用
方法:installApp()
安装应用到设备中去。需要 apk 包的路径。
driver.installApp("path/to/my.apk");
driver.installApp("D:\\android\\apk\\ContactManager.apk");
2、卸载应用
方法:removeApp()
从设备中删除一个应用。
// java
driver.removeApp("com.example.android.apis");
3、关闭应用
方法:closeApp()
关闭打开的应用,默认关闭当前打开的应用,所以不需要入参。这个方法并非真正的关闭应用,相当于按 home 键将应用置于后台,可以通过 launchApp() 再次启动。
4、启动应用
方法:launchApp()
启动应用。你一定很迷惑,不是在初始化的配置信息已经指定了应用,脚本运行的时候就需要启动应用,为什么还要有这个方法去启动应用呢?重新启动应用也是一个测试点,该方法需要配合closeApp()使用的。
// java
driver.closeApp();
driver.launchApp();
5、检查应用是否安装
方法:isAppInstalled()
检查应用是否已经安装。需要传参应用包的名字。返回结果为Ture或False。
// java
driver.isAppInstalled('com.example.android.apis');
6、将应用置于后台
方法:runAppInBackground()
将当前活跃的应用程序发送到后台。这个方法需要入参,需要指定应用置于后台的时长。
driver.runAppInBackground(2);
7、应用重置
方法:resetApp()
重置当前被测程序到出始化状态。该方法不需要入参。
// java
driver.resetApp();
10. appium API 之上下文操作
其实上下文的操作主要针对于混合应用。
啥是混合应用,简单来说就是APP用里面嵌入网页。Android上的浏览器就属于混合应用。
1、获取当前上下文
方法:getContext()
获取当前所有的可用的上下文。该方法不需要入参。 ```java String ct = driver.getContext(); System.out.println(ct);
-----------计算器应用的打印结果----------------------- NATIVE_APP ```
2、当前所有上下文句柄
方法:getContextHandles()
获取当前所有可用的上下文。该方法不需要入参。
3、切换上下文
方法:context()
切换到特定的上下文中。需要指定上下文的名称。 java driver.context('NATIVE_APP') driver.context('WEBVIEW_1')
11. appium API 之键盘操作
模拟键盘输入也是非常重要的操作。这一小节来介绍那些关于键盘的操作。
1、sendKeys() 方法
方法:sendKeys()
用法:
driver.findElements(By.name("Name")).sendKeys("jack");
2、pressKeyCode() 方法
除此之外,appium扩展提供了pressKeyCode()方法。该方法 Android 特有。
方法:pressKeyCode()
发送一个键码的操作。需要一个入参。
driver.pressKeyCode(29); // 字母“a”
如果想点击 Android 的 HOME 键应该怎么实现的呢?如下 java driver.pressKeyCode(AndroidKeyCode.HOME);
下面提供Android keycode参考表:
电话键
KEYCODE_CALL 拨号键 5
KEYCODE_ENDCALL 挂机键 6
KEYCODE_HOME 按键Home 3
KEYCODE_MENU 菜单键 82
KEYCODE_BACK 返回键 4
KEYCODE_SEARCH 搜索键 84
KEYCODE_CAMERA 拍照键 27
KEYCODE_FOCUS 拍照对焦键 80
KEYCODE_POWER 电源键 26
KEYCODE_NOTIFICATION 通知键 83
KEYCODE_MUTE 话筒静音键 91
KEYCODE_VOLUME_MUTE 扬声器静音键 164
KEYCODE_VOLUME_UP 音量增加键 24
KEYCODE_VOLUME_DOWN 音量减小键 25控制键
KEYCODE_ENTER 回车键 66
KEYCODE_ESCAPE ESC键 111
KEYCODE_DPAD_CENTER 导航键 确定键 23
KEYCODE_DPAD_UP 导航键 向上 19
KEYCODE_DPAD_DOWN 导航键 向下 20
KEYCODE_DPAD_LEFT 导航键 向左 21
KEYCODE_DPAD_RIGHT 导航键 向右 22
KEYCODE_MOVE_HOME 光标移动到开始键 122
KEYCODE_MOVE_END 光标移动到末尾键 123
KEYCODE_PAGE_UP 向上翻页键 92
KEYCODE_PAGE_DOWN 向下翻页键 93
KEYCODE_DEL 退格键 67
KEYCODE_FORWARD_DEL 删除键 112
KEYCODE_INSERT 插入键 124
KEYCODE_TAB Tab键 61
KEYCODE_NUM_LOCK 小键盘锁 143
KEYCODE_CAPS_LOCK 大写锁定键 115
KEYCODE_BREAK Break/Pause键 121
KEYCODE_SCROLL_LOCK 滚动锁定键 116
KEYCODE_ZOOM_IN 放大键 168
KEYCODE_ZOOM_OUT 缩小键 169组合键
KEYCODE_ALT_LEFT Alt+Left
KEYCODE_ALT_RIGHT Alt+Right
KEYCODE_CTRL_LEFT Control+Left
KEYCODE_CTRL_RIGHT Control+Right
KEYCODE_SHIFT_LEFT Shift+Left
KEYCODE_SHIFT_RIGHT Shift+Right基本
KEYCODE_0 按键'0' 7
KEYCODE_1 按键'1' 8
KEYCODE_2 按键'2' 9
KEYCODE_3 按键'3' 10
KEYCODE_4 按键'4' 11
KEYCODE_5 按键'5' 12
KEYCODE_6 按键'6' 13
KEYCODE_7 按键'7' 14
KEYCODE_8 按键'8' 15
KEYCODE_9 按键'9' 16
KEYCODE_A 按键'A' 29
KEYCODE_B 按键'B' 30
KEYCODE_C 按键'C' 31
KEYCODE_D 按键'D' 32
KEYCODE_E 按键'E' 33
KEYCODE_F 按键'F' 34
KEYCODE_G 按键'G' 35
KEYCODE_H 按键'H' 36
KEYCODE_I 按键'I' 37
KEYCODE_J 按键'J' 38
KEYCODE_K 按键'K' 39
KEYCODE_L 按键'L' 40
KEYCODE_M 按键'M' 41
KEYCODE_N 按键'N' 42
KEYCODE_O 按键'O' 43
KEYCODE_P 按键'P' 44
KEYCODE_Q 按键'Q' 45
KEYCODE_R 按键'R' 46
KEYCODE_S 按键'S' 47
KEYCODE_T 按键'T' 48
KEYCODE_U 按键'U' 49
KEYCODE_V 按键'V' 50
KEYCODE_W 按键'W' 51
KEYCODE_X 按键'X' 52
KEYCODE_Y 按键'Y' 53
KEYCODE_Z 按键'Z' 54
12. appium API 之 TouchAction 操作
Appium 的辅助类,主要针对手势操作,比如滑动、长按、拖动等。
1、按压控件
方法:press()
开始按压一个元素或坐标点(x,y)。通过手指按压手机屏幕的某个位置。
press(WebElement el, int x, int y)
press 也可以接收屏幕的坐标(x,y)。
例:
TouchAction(driver).press(x=0,y=308).release().perform()
除了press()方法之外,本例中还用到了别外两个新方法。
-
release() 结束的行动取消屏幕上的指针。
-
Perform() 执行的操作发送到服务器的命令操作。
2、长按控件
方法:longPress()
开始按压一个元素或坐标点(x,y)。 相比press()方法,longPress()多了一个入参,既然长按,得有按的时间吧。duration以毫秒为单位。1000表示按一秒钟。其用法与press()方法相同。
longPress(WebElement el, int x, int y, Duration duration)
例: java TouchAction action = new TouchAction(driver); action.longPress(names.get(1),1000).perform().release(); action.longPress(1 ,302,1000).perform().release();
3、点击控件
方法:tap()
对一个元素或控件执行点击操作。用法参考press()。
tap(WebElement el, int x, int y)
例: java TouchAction action = new TouchAction(driver); action.tap(names.get(1)).perform().release(); action.tap(1 ,302).perform().release();
4、移动
方法:moveTo()
将指针(光标)从过去指向指定的元素或点。
movTo(WebElement el, int x, int y)
其用法参考press()方法。
例: Java TouchAction action = new TouchAction(driver); action.moveTo(names.get(1)).perform().release(); action.moveTo(1 ,302).perform().release();
5、暂停
方法:wait()
暂停脚本的执行,单位为毫秒。 Java action.wait(1000);
13. appium API 之其他操作
其它操作针对移动设备上特有的一些操作。
1、熄屏
方法: * lockDevice()
点击电源键熄灭屏幕。
在iOS设备可以设置熄屏一段时间。Android上面不带参数,所以熄屏之后就不会再点亮屏幕了。 java driver.lockDevice(1000); // iOS driver.lockDriice(); //Android
2、当前Activity(Android only)
方法:currentActivity()
得到当前应用的activity。只适用于Android。 例(通讯录): Java String ca = driver.currentActivity(); System.out.print(ca); -------------输出结果为------------- .activities.PeopleActivity
3、收起键盘
方法:hideKeyboard()
收起键盘,这个方法很有用,当我们对一个输入框输入完成后,需要将键盘收起,再切换到一下输入框进行输入。 Java driver.hideKeyboard(); //收起键盘
4、滑动
方法:swipe()
模拟用户滑动。将控件或元素从一个位置(x,y)拖动到另一个位置(x,y)。
swipe(int startx, int starty, int endx, int endy, int duration) * start_x:开始滑动的x坐标。 * start_y:开始滑动的y坐标。 * end_x:结束滑动的x坐标。 * end_y:结束滑动的y坐标。 * duration:持续时间。
例: Java driver.swipe(75, 500, 75, 0, 800);
5、拉出文件
方法:pullFile()
从设备中拉出文件。
例: Java driver.pullFile('Library/AddressBook/AddressBook.sqlitedb')
6、推送文件
方法:pushFile()
推送文件到设备中去。
pushFile(String remotePath, byte[] base64Data)
例: Java String content = "some data for the file"; byte[] data = Base64.encodeBase64(content.getBytes()); driver.pushFile("sdcard/test.txt", data);