Appium自动化测试框架

1.基础

--appium是一款开源的移动端自动化测试工具,支持ios和android平台上开发的APP

--appium支持跨平台使用,可使用同一套API来写自动化测试脚本,在ios/android平台上测试,加大了代码的复用性

--appium支持多语言,Python/Java/Ruby等

--appium真正的工作引擎其实是第三方自动化框架,无需在APP中植入appium特地代码或第三方代码

iOS:苹果的UIAutomation框架

android 4.2+:Google的UIAutomator框架

android 2.3+:Google的Instrumentation框架

--appium把第三方框架封装成一套API,称为WebDriver(Selenium WebDriver),指定了客户端到服务器的协议

--appium扩充了WebDriver的协议,添加了与移动测试自动化相关的API方法

--appium相关概念

C/S架构:客户-服务器架构,只要客户端能发送HTTP请求给服务器,客户端就可使用多种编程语言实现;appium核心是一个Web服务器,该服务器提供了一套REST接口。服务器在收到客户端命令后,会在移动设备上执行这些命令,后将执行结果放在HTTP响应中并返回客户端。

会话:自动化总是在名为会话的上下文中进行。客户端将初始化一个用来和服务器交互的会话,然后发送附有Desired Capabilities的JSON对象参数的POST请求/会话给服务器,服务器就会开始一个自动化的会话,返回一个会话ID,客户端在得到这个ID后便开始发送后续命令。

Desired Capabilities:一些键值对的集合,告诉服务器要启动怎样的自动化会话。

Appium服务器:使用Node.js编写,功能是监听接口,接收PC客户端发送的指令,将其转换为移动设备能识别的指令,后发送给移动设备进行操作,再等待移动设备返回操作结果,并发送给客户端。服务器可放在PC客户端,也可放在云端,默认端口号4723

Appium客户端:主要指实现了Appium功能的WebDriver协议的客户端库,其中提供了一些封装好的API以支持访问移动端。客户端提供了很多语言库以支持JAVA等编程语言,这些语言库让Appium实现了对WebDriver协议的扩展。当使用Appium时,只需要使用这些语言库代替常规的WebDriver库就可以了

Appium Desktop:不仅封装了运行Appium服务器所需的所有依赖元素,还提供了Inspector工具,以方便使用者检查应用的界面元素的层级,从而简化测试用例编写

--Appium工作原理:(Appium基于WebDriver协议,并利用Bootstrap.jar来调用UIAutomator框架,进而执行指令)

编写客户端脚本-->开启Appium服务器-->Appium服务器在收到客户端请求后,将请求解析为UIAutomator可识别的指令,再将这些指令转发给Android设备的Bootstrap.jar服务,默认使用4724端口-->调用UIAutomator,在设备上执行自动化测试并将结果返回给Appium服务器-->Appium服务器将执行结果返回给Appium客户端

--Appium与Selenium

Appium类库封装了标准的Selenium客户端类库,为用户提供了所有常见的JSON格式的Selenium命令以及额外的与移动设备控制相关的命令;Appium扩展了WebDriver协议,以前WebDriver API可继承,Selenium WebDriver可直接拿来用

2.环境搭建

--需要:编程语言(java),appium client, appium server, android sdk, android studio/idea, android模拟器/android手机/iphone手机

--安装Android SDK

Android SDK是android应用的软件开发工具包,提供了android api库和开发工具构建。 https://www.jianshu.com/p/2078112331fb Android SDK的安装与环境变量配置

http://www.testclass.net/appium_base/appium-base-sdk

--.apk files are for android apps. / .ipa for iOS / Xcode是IOS的开发环境

--安装java->安装Android sdk->安装Android studio(包含了Android sdk和Android模拟器)/IDEA->安装appium客户端-->安装appium(服务器)->安装android手机驱动(adb devices) / 打开模拟器

3.定位Appium元素的3个利器

--UI Automator Viewer:仅限Android系统

--Inspector:Android & IOS

--Chrome浏览器的ADB插件,主要用于基于浏览器的Web应用

4.Desired Capabilities

--Desired Capabilities在启动session时必须提供

--Desired Capabilities本质上是key value的对象,客户端将这些键值对发给服务端,告诉服务端启动怎样的会话

--Appium的Desired Capabilities是扩展了webdriver的Desired Capabilities的,一般需指定以下配置

platformName---使用哪种移动平台,ios, Android, FirefoxOS

deviceName--指定真机或模拟器的设备名称,如Nexus_5X_API_29

automationName---使用哪种自动化引擎,appium(默认)or Selendroid  (非必须)/ UiAutomator2(目前公司用这个)

platformVersion---指定平台的系统版本,如Android平台,版本为5.1

appPackage---待测app的包名, 如com.example.android.myapp, com.android.settings

appActivity---待测app的活动名,如MainActivity, .Setting。注意:原生app的话要在activity前加"."

app---安装包路径,若android指定了appPackage和appActivity,则不需要该参数 (非必须)

browserName---使用的浏览器名称,Chrome/Safari (非必须)

noReset---不重置应用,false(默认)或true (非必须)

--如何获取deviceName

cmd-->adb shell getprop ro.product.model

--如何获取platformVersion

cmd-->adb shell getprop ro.build.version.release

--如何获取appPackage/appActivity

情况一:提供被测应用的APK包(适用于Android系统)

使用AAPT构建工具(C:\Users\yoyo\Android-SDK\build-tools\31.0.0\aapt.exe)

命令:cmd->aapt dump badging apk 包名,如 aapt dump badging apk fengkuangshuiguodazhan_112.apk

情况二:提供安装了被测应用的手机设备

cmd-->adb logcat | grep Displayed

5.Android Studio学习教程

Android Studio 简介丨慕课网教程 (imooc.com)

6.界面元素(控件)的定位

常见控件:文本框、按钮、单选、复选框、滚动条、进度条等

定位单个元素

--driver.findElement(By.id("com.android.calculator2:id/formula")) --- resource-id 就是我们理解的id属性 --driver.findElement(By.name("9")) --- text就是我们要查找的name WebElement button = driver.findElement(By.className("android.widget.Button")); --- 对应于class属性 driver.findElement(By.xpath("//android.widget.Button[contains(@text,'7')]")).click(); //7 driver.findElement(By.xpath("//android.widget.Button[contains(@content-desc,'times')]")).click(); //* 出现class相同情况下可用控件的属性值区分 java driver.findElementByAccessibilityId("plus").click(); --- Accessibility id就是contentDescription属性, 就是content-desc (ByClassName/CssSelector/Id/LinkText/Name/PartialLinkText/TagName/Xpath)

--根据坐标定位元素 driver.tap([(936,1776)],10) 第一个参数是要操作的坐标,第二个是单击操作的时长,默认毫秒

(该方法不建议使用,因为该方法对坐标有严重的依赖,若换了手机/模拟器,分辨率不同就会导致脚本失败

driver.findElementByAndroidUIAutomator("new UiSelector().resourceId(\"com.hsbc.mobilebanking.insurance.sampleapp:id/dev\")").click();

driver.findElementByAndroidUIAutomator("new UiSelector().className(\"android.widget.Button\")").click();

IOS: iosClassChain();  / iosPredicateString();

定位多个元素

List<WebElement> listElement = driver.findElements(By.className(("android.widget.Button")));
listElement.get(0).click();

7.元素操作

TouchAction操作(辅助类)

TouchAction action = new TouchAction(driver);

1.按压控件(通过手指按压手机屏幕的某个位置) press(WebElement el) / 坐标点(x,y) press(int x, int y)

action.press(e1).release().perform()

action.press(x=0,y=308).release().perform()

--release()结束的行动取消屏幕上的指针

--perform()执行的操作发送到服务器的命令操作

2.长按控件 longPress(WebElement el, Duration duration) 以毫秒为单位,1000表示一秒钟 action.longPress(e1,1000).perform();

3.点击控件 tap(WebElement el)

action.tap(e1).perform();

4.移动 movTo(WebElement el, int x, int y) 将指针(光标)从过去指向指定的元素或点

action.moveTo(1 ,302).perform().release();

5.暂停 action.wait(1000); 单位为毫秒

模拟键盘操作

1.driver.findElements(By.name("Name")).sendKeys("jack");

2.pressKeyCode()方法为android特有

--driver.pressKeyCode(29); // 字母“a”

--driver.pressKeyCode(AndroidKeyCode.HOME);

上下文操作

上下文操作主要针对混合应用,混合应用就是APP里嵌入网页。Android上的浏览器就属于混合应用
1.获取当前上下文 String cc = driver.getContext(); (cc = "NATIVE_APP')
2.获取所有上下文句柄 getContextHandles();
3.调用 context () 方法,实参指定上下文的名称,切换到特定的上下文中。 java driver.context (‘NATIVE_APP’) 

其他操作

1.当前Activity(Android only)
String ca = driver.currentActivity();

2.driver.findElement(By.id("com.android.calculator2:id/formula")).sendKeys() 模拟键盘输入文本

3.拖拽操作 driver.drag_and_drop(e1,e2); //待修正

4.滑动 模拟用户滑动。将控件或元素从一个位置(x,y)拖动到另一个位置(x,y)

WebElement e1 = driver.findElementById("com.android.systemui:id/slider");
int xpoint = e1.getLocation().getX();
int ypoint = e1.getLocation().getY();
int xmindpoint = xpoint + e1.getSize().getWidth()/2;
driver.swipe(xpoint,ypoint,xmindpoint,ypoint,0);

5.拉出文件,从设备中拉出文件 driver.pullFile('Library/AddressBook/AddressBook.sqlitedb')

6.推送文件,推动文件到设备中去 pushFile(String remotePath, byte[] base64Data)
String content = "some data for the file"; byte[] data = Base64.encodeBase64(content.getBytes()); driver.pushFile("sdcard/test.txt", data);

7.多点操作(图片放大/缩小)

使用MultiAction类来实现多点操作(待补充)

8.手势密码(待补充)

TouchAction(driver).press(x=363,y=524).wait(1500).move_to(x=111,y=222).wait(1000).move_to...release().perform();

8.系统操作

driver.isLocked() 检测屏幕是否已锁屏

--在iOS设备可以设置熄屏一段时间。Android上面不带参数,所以熄屏之后就不会再点亮屏幕了

driver.lockDevice(1000); // iOS driver.lockDevice(); //Android

driver.unlockDevice() 解锁屏幕

driver.hideKeyboard() 隐藏系统键盘

9.应用操作

driver.installApp("D:\android\apk\ContactManager.apk"); --- 安装应用到设备中去,需要apk包的路径

driver.isAppInstalled('com.example.android.apis'); --- 检查应用是否安装,需要传应用包的名字,返回true/false

activateAPP() 启动android应用,参数为应用包名。如果应用未运行,则打开应用,若应用在后台,在将应用重新置于前台

java driver.removeApp("com.example.android.apis"); --- 删除应用 ,从设备中删除一个应用

closeApp() --- 关闭应用,默认关闭当前打开的应用,不需要入参,将应用置于后台,可通过launchApp()再次启动

driver.closeApp(); driver.launchApp(); 重新启动应用,该方法需要配合closeApp()使用的

driver.runAppInBackground(2); 将应用置于后台,需要入参,需要指定应用置于后台的时长

driver.resetApp(); --- 应用重置,重置当前被测程序到初始化状态,该方法不需要入参

安装和卸载应用

前提是模拟器已启动;

模拟器或真机上安装应用,.apk放到sdk的platform-tools目录(与adb同一级别)-->cmd(cd C:\software\Android\Android\Sdk\platform-tools)-->adb install new_aos_app.apk

卸载应用 adb uninstall com.mobilebanking.hsbc.insurance.sampleapp(应用的包名)

10.Appium的其他功能

10.1 Appium的三种等待方式(针对页面的元素没有出现而无法定位元素)

(1)强制等待 Thread.sleep(3000);

(2) 显示等待 根据条件是否满足来决定是否终止等待,若在指定等待时间内发现元素,则无须等到指定等待时间即可提前终止轮询,继续执行后面语句,若等待时间找不到元素则抛出异常NoSuchElementException

WebDriverWait wait = new WebDriverWait(driver,3,1); 每1s检测一次,最多检测3s wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("kw66")));

(3)隐式等待

implicitly_wait()方法设定等待时间,单位秒,当界面上的全部元素都显示出来后,才会执行后续语句。若界面全部元素显示出来所需时间短于等待时间,会提前终止轮询,执行后面语句;若到了等待时间依然找不到元素,则抛出异常

driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);

10.2 断言

10.3 获取Toast元素的内容

--Toast元素:(一些提示信息)

Toast元素只包含一条简易消息的提示框,作为浮动窗口,既不能获得焦点也不能被单击;存在时间很短,一般3~5s消失;无法被UI Automator View工具定位到

--可借助Xpath表达式字符串来定位Toast元素

10.4模拟滚动条操作 driver.swipe();

10.5捕获因界面元素定位失败产生的异常

print(traceback.print_exe());

截图 driver.save_screenshot("err.png");

Addition:

1.IOS

—操作系统基于XNU内核,应用开发语言为swift(推荐)或objective-c

—ios自动化测试工具(框架):Appium, UIAutomation, XCUITest(目前公司用这个)

—模拟器  .app     真机 .ipa

—Desired Capabilities

{

  "platformName": "iOS",

  "deviceName": "iPhone 11",

  "platformVersion": "13.5",

  "automationName": "XCUITest",

  "udid": "345A96CB-1167-4140-B2E4-953FE0E576A1",

  "app": "/Users/xxxx/Downloads/MDev.app"

}

—模拟器命令:xcrun (Xcode command-line tool runner)

--真机命令

—解压IPA文件获取bundle id(待check)

把.ipa文件的后缀重命名为.zip, 解压.zip压缩包,会有一个Payload 文件夹. 点开Payload文件夹会有一个.app的文件.
右键点击.app文件 -> Show Package content. 将会打开新的文件夹包含很多文件.
用Xcode打开文件info.plist,就可以找到bundle id, 类似 com…game

—元素定位方式   

othersText = MobileBy.iOSClassChain("**/XCUIElementTypeButton[`label == 'Others'`]");  ---原生支持的定位方式 ios class chain

uniquePageLocator = MobileBy.iOSNsPredicateString("label == 'accessibility_accounts_viewmore_close'");  ---原生支持的定位方式 ios predicate string

xpath, accessibility id, id, name

2.AOS

—操作系统基于Linux内核,应用开发语言Kotlin(推荐)或Java

—aos自动化测试工具(框架):Appium, UIAutomator, UIAutomator2(目前公司用这个)

—模拟器和真机  .apk

—Desired Capabilities

{

  "platformName": "android",

  "deviceName": "Android SDK built for x86",

  "platformVersion": "10.0",

  "automationName", "UiAutomator2"

  "appPackage": "com.xxxx”,

  "appActivity": "com.xxxx”

// “app”:”Users/xxxx/Downloads/MDev.apk”

}

—命令:adb (Android Debug Bridge安卓调试桥:用于电脑端和手机/模拟器之间的通信)

3.集成开发环境

xcode

—Xcode是苹果公司向开发人员提供的集成开发环境,用于开发macOS, iOS, ipadOS, WatchOS和tvOS的应用程序

IDEA/Eclipse

—基于java的集成开发环境

Android studio

—Android Studio 是谷歌推出的一个Android集成开发工具,基于IDEA

posted @ 2021-12-13 14:36  meiyouyou  阅读(935)  评论(0编辑  收藏  举报