Appium - 入门指南(偏重于实际操作)

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

前言

此文章 偏向于实操
appium支持在不同平台上windowslinux、mac - 使用测试脚本支持不同语言C #jsonRuby等等 - 模拟测试各个平台的appweb、windows、mobile等运行情况支持ios和安卓平台上的原生应用web应用和混合运用
appium类库封装了标准Selenium客户端类库为用户提供所有常见的JSON格式selenium命令以及额外的移动设备控制相关的命令如多点触控手势和屏幕朝向。

一、 Appium介绍

官网http://appium.io/docs/cn/about-appium/intro/

这里主要是windows平台下的安装和使用。

1.1 设计理念

1.1.1 使用系统自带的自动化框架

使用各个系统自带的自动化框架可以让appium 独立运行

  • 不需要把 Appium 特定的或者第三方的代码编译进应用
  • 不用为了自动化而重新编译或修改应用
  • 各个系统使用的自动化框架
    iOS 9.3 及以上: 苹果的 XCUITest
    iOS 9.3 及以下: 苹果的 UIAutomation
    Android 4.3+: 谷歌的 UiAutomator / UiAutomator2
    Android 2.3+: 谷歌的 Instrumentation. (通过绑定独立的项目—— Selendroid 提供对 Instrumentation 的支持)
    Windows: 微软的 WinAppDriver

1.1.2 支持多种语言 --WebDriver API

把各种系统本身提供的框架包装进一套 API —— WebDriver API 中
WebDriver也叫「Selenium WebDriver」)。
在WebDriverAPI中规定了一个客户端-服务器协议称为 JSON Wire Protocol按照这种客户端-服务器架构可以使用任何语言编写的客户端向服务器发送适当的 HTTP 请求。

Appium & WebDriver 客户端在技术上而言不是「测试框架」而是「自动化程序库」

1.2 架构

1.2.1 客户端 / 服务器架构每个平台的驱动

在这里插入图片描述

Appium 的核心一个是暴露 REST API 的 WEB 服务器。它接受来自客户端的连接监听命令并在移动设备上执行答复 HTTP 响应来描述执行结果

1.2.2 Appium服务器

Appium 是一个用 Node.js 写的服务器。可以从源码构建安装或者从 NPM 直接安装

$ npm install -g appium
$ appium
  1. 它监听符合API规范从WebDriver 传入的HTTP request。
  2. WebDriver是一个W3C规范Appium团队为该协议添加了一些扩展使其适用于web浏览器同时也适用在任何设备上测试的任何应用程序。
  3. Appium Server服务器需要在Node.js web服务器中运行。
    • Node.js web服务器可以在运行测试之前在本地机器上启动也可以托管Appium服务器-让它作为运行测试的一部分。

1.2.3 Appium 客户端

Appium 客户端不同客户端支持不同语言来发起http命令。比如postmanAppium server gui等等

  1. 让Appium客户端与Appium Server服务器交互
  2. 解读WebDriver协议将WebDriver协议转换为我们可以轻松使用的客户端库。
    Appium提供了相应客户端的库。比如C# 有NuGet包。

1.2.4 会话Session

自动化始终在一个会话的上下文中执行。
通过客户端程序库以各自的方式发起与服务器的会话但最终都会发给服务器一个 POST /session 请求请求中包含一个被称作「预期能力Desired Capabilities」的 JSON 对象。这时服务器就会开启这个自动化会话并返回一个用于发送后续命令的会话 ID。

1.2.5 预期能力Desired Capabilities

预期能力Desired Capabilities是一些发送给 Appium 服务器的键值对集合比如 map 或 hash它告诉服务器我们想要启动什么类型的自动化会话。
也有许多能力Capabilities可以修改服务器在自动化过程中行为。例如我们可以将 platformName 能力设置为 iOS以告诉 Appium 我们想要 iOS 中的应用会话而不是 Android 或者 Windows 应用会话

二、环境配置

  1. 安装 npm添加链接描述 https://nodejs.org/en/

  2. 安装AppiumAppium 有命令行版本和桌面版本。可以两个都装上桌面版本在appium官网下载并安装Appium。命令行版本管理员模式运行cmdnpm install -g appium 可能需要设置网络代理。

  3. 安装 node.js https://nodejs.org/en/download/

  4. 安装 UIRecorder https://github.com/Microsoft/WinAppDriver/releases

  5. 安装结束后在cmd界面输入“appium-doctor”检查是否缺少东西。

  6. 电脑启用“开发者模式”

  7. 添加环境变量
    在这里插入图片描述

  8. 安装各平台应用的驱动程序通过驱动程序Appium server才能将我们的测试命令翻译给Appium客户端以及应用

  • WinAppDriver - Windows平台的驱动程序。针对windows应用自动化 WinAppDriver
    • UiAutomator2 - Android,它是Android SDK 安装包的一部分安装 Java and Android SDK后就可以运行了
    • XCUITest - Macios 研发需要Xcode,Xcode只适用于Mac
  1. 安装Appium inspector。用来查看、定位界面元素。如果使用有问题可以去github上搜索https://github.com/appium/appium-desktop/issues
    Appium Inspector 有两种版本
  • 桌面app下载链接https://github.com/appium/appium-inspector/releases

    • Appium 1.22版本之前都附带了Inspector 工具入口在打开之后的搜索图标里如下图新版的inspector已经和Appium server不在一起了需要单独安装。
    • 在这里插入图片描述
  • web应用由Appium Pro托管。直接打开网页就可以 https://inspector.appiumpro.com/
    这两个应用程序有完全相同的功能开网页版会更容易并节省磁盘空间同时可以保持多个标签打开

需要注意的是Appium Inspector设计为默认使用Appium 2.0 (W3C WebDriver协议)。因此如果是从Appium Desktop(默认情况下设计为使用Appium 1.x)迁移可能会有一些不同的地方

appium-doctor提示问题以及解决办法

2.1ANDROID_HOME is not set

解决办法

  • 安装过adb的可以在系统变量-path中找到adb的安装路径因为我用自己安装的路径缺少android.bat文件所以我这里解决办法是采用adb路径是安装vs2022时顺带安装的-勾选移动应用开发包含AndroidSDK项
  • 电脑-高级系统设置-系统变量-新增变量ANDROID_HOME 值设置为adb 文件夹的路径。
  • adb完整路径是C:\Microsoft\AndroidSDK\25\platform-toolsANDROID_HOME路径设置为C:\Microsoft\AndroidSDK\25

2.2 JAVA_HOME is not set

解决办法

  • 在系统变量中找到找到JDK的安装路径
  • 新建变量JAVA_HOMEJDK的路径。这里直接复制完整路径即可。

成功解决之后再次测试appium-doctor提示全部ok

✔ ANDROID_HOME is set to "C:\Microsoft\AndroidSDK\25"
✔ JAVA_HOME is set to "C:\Program Files\Microsoft\jdk-11.0.12.7-hotspot\bin."
✔ ADB exists at C:\Microsoft\AndroidSDK\25\platform-tools\adb.exe
✔ Android exists at C:\Microsoft\AndroidSDK\25\tools\android.bat
✔ Emulator exists at C:\Microsoft\AndroidSDK\25\tools\emulator.exe
✔ Android Checks were successful.

✔ All Checks were successful
(node:25404) Warning: Accessing non-existent property 'padLevels' of module exports inside circular dependency
(Use `node --trace-warnings ...` to show where the warning was created)

三、Appium - 测试程序详细解析

一个简单的自动化程序主要分为启动、交互。
不管哪个客户端启动的步骤和所需要的参数都是一样的。
启动前要设置初始化参数告知服务器启动哪一个应用app在哪个平台用哪个版本
交互要确认交互的对象 - 哪一个ui元素交互的动作以及如何判断动作结束

3.1 Appium 服务器初始化参数Capability

AppiumOptions是Appium中一个关键类
在启动应用时可以设置这些类中的这些参数 http://appium.io/docs/cn/writing-running-appium/caps/#appium-capability

3.1.1 Windows应用设置参数

keyName描述Value
appiumOptions.App应用exe本地绝对路径_或_应用id
appiumOptions.PlatformName操作系统“windows”;
appiumOptions.DeviceName设备类型“windowsPC”;

上面这三个是Windows应用必须要设置的

3.1.2 Android应用设置参数

keyName描述Value
platformName使用的手机操作系统iOS, Android等
platformVersion手机操作系统的版本例如 7.1, 4.4
deviceName使用的手机或模拟器类型adb devices命令查看当前设备名称。在 Andorid 上虽然这个参数目前已被忽略但仍然需要添加上该参数。 为确保在连接多个设备时连接到正确的 Android 设备请使用 udid 功能。
appActivity指从你的包中所要启动的 Android acticity。他通常需要在前面添加. 例如 使用 .MainActivity 代替 MainActivityMainActivity, .Settings
appPackage运行的 Android 应用的包名com.example.android.myApp, com.android.settings
app本地绝对路径_或_远程 http URL 所指向的一个安装包.ipa,.apk,或 .zip 文件。Appium 将其安装到合适的设备上。请注意如果您指定了 appPackage 和 appActivity 参数见下文Android 则不需要此参数了。该参数也与 browserName 不兼容。/abs/path/to/my.apk 或 http://myapp.com/app.ipa

3.2 UI元素定位与交互

如果是WPF程序在该控件的Automation里面可以找到对应的设置比如NameAccessibilityID。
在inspector 里面可以看到界面元素具体的值
http://appium.io/docs/en/commands/element/find-elements/index.html#selector-strategies

method描述Value
IDNative element identifier. resource-id for android; name for iOS.
AccessibilityIDAutomationID
Name组件的名称
class Nameui组件的类型BUTTONMENUBAR等等
xpath路径定位依赖元素绝对路径或相关属性定位。不太推荐这种方式

四、Appium实战 之启动应用

4.1 通过Inspector启动 - 记事本应用

Appium inspector是一个软件通过他可以查看界面上的所有元素信息比如某个按键的名字、控件类型、xy坐标等等
通过简单设置Appium inspector中的参数快速启动应用一方面为后面定位控件元素做好准备一方面可以通过启动应用所需要的参数参考到自动化程序中。

  1. 管理员模式启动Appium server
    可以管理员启动桌面版Appium Server GUI.exe输入Host127.0.0.1和端口4723。
    也可以通过管理员模式启动cmd输入appium启动命令行版本
    因为inspector或者其他客户端与 应用或者模拟器之间的通讯交互都需要通过Appium server来传达与翻译。所以要先启动Appium server。
    后续交互历史记录在Appium server界面也可以看到详细信息。
    在这里插入图片描述
    在这里插入图片描述

  2. 管理员模式启动Appium Inspector设置Remote path
    如果Appium版本是1.x 而inspector 版本是新的就需要设置远端路径 - Remote path 为/wd/hub
    如果Appium 版本是2.x 则不用设置
    Appium版本为 v1.22.3所以需要设置

  • wd 可以理解是WebDriver 的缩写
  • hub 是指主中心 节点在selenium 分布式里中心节点
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/edec3033d4b54cfe8313ae5481ceafe2.png
  1. 添加Capabilities
    在Desired Capabilities 下面依次添加需要启动应用的信息。
    在这里插入图片描述
    app要启动的应用这里添加notepad.exe的路径
    deviceName启动的设备
    platformName这个应用所需要使用的平台
    这三个信息是必要的。告诉Appium inspector我们需要在何种环境下启动何种应用
    右边会自动将我们填入的信息转换成JSON 表达方式
    点击save保存现在的信息。
  2. 点击Start Session
    在这里插入图片描述
    启动session后inspector会启动记事本应用
  • 左侧界面预览区是和当前应用同步界面的预览画面不会实时更新。需要手动点击刷新按钮来同步画面。但是在预览区点击按钮实际打开的应用会实时同步操作。
  • App Source查看当前界面元素信息这些信息可以用来帮助我们在写自动化时定位某个界面元素。

五、Appium实战 之编写Mstest 自动化程序

自动化测试程序是模拟应用启动、运行以及其他的一些特定操作。
所以基于inpector启动应用的流程我们可以在自己加一些操作比如输入字符串保存文档等。
我这里是对自己写的WPF应用进行自动化测试先在文本框中输入字符串然后保存文档。
在这里插入图片描述

5.1 新建MSTest 测试项目或者单元测试项目

5.2 添加NuGet包

项目上右键 - NuGet包管理 - 搜索并添加NuGet包需要添加以下三个
- Microsoft.WinAppDriver.Appium.WebDriver
- Selenium.WebDriver
- Selenium.Support

在安装时注意看下面的依赖项 版本说明比如.Appium.WebDriver需要Selenium 包相关版本为3.8.0+。工具-程序包管理控制台 输入Get-Package 获取当前项目的NuGet包信息
我安装的版本信息如下

  • Appium.WebDriver {5.0.0-alpha} NodepadTest
  • Selenium.WebDriver {4.0.0} NodepadTest - Selenium.Support {4.0.0} NodepadTest

官网Samples项目版本如下 Appium官方样例代码下载地址https://github.com/Microsoft/WinAppDriver/tree/v1.0#using-appium

  • Microsoft.WinAppDriver.Appium.We… {1.0.1-Preview} NotepadCalculatorTest
  • Selenium.Support {3.8.0} NotepadCalculatorTest
  • Selenium.WebDriver {3.8.0} NotepadCalculatorTest

Appium版本更新的时候会优化很多功能如果报一些错误可以试试把版本改一改。

  • Microsoft.WinAppDriver.Appium.WebDriver 这是一个用于Appium临时的Selenium WebDriver的扩展它实现了Windows应用程序驱动程序(WinAppDriver)的操作API功能。这仅用于预览目的。 Microsoft WinAppDriver 提供
  • Appium.WebDriver - Selenium Webdriver extension for Appium. 由Appium提供
https://www.nuget.org/packages 可以搜索关于NuGet包的相关信息

这两个包选择一个使用我这里选择的- Appium.WebDriver {5.0.0-alpha} NodepadTest

5.3 添加session

  1. 添加using 引用库
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Appium.Service;
using OpenQA.Selenium.Appium.Windows;
using OpenQA.Selenium;
using System;
using System.Threading;
using OpenQA.Selenium.Appium.Interactions;
using OpenQA.Selenium.Interactions;
using System.Collections.Generic;
using OpenQA.Selenium.Support.UI;
  1. 添加session 启动function在method下调用这个函数的话就可以启动该Application了。我这里用的是我自己写的一个WPF应用。可以用notepad.exe
public  WindowsDriver<WindowsElement> StartNodepadApplication()
        {
            //1.add capabilities
            var appiumOptions = new AppiumOptions();
            //appiumOptions.App = @"C:\Windows\System32\notepad.exe";//notepad
            appiumOptions.App = "D:\\test\\Appium\\WPFApplication\\AppiumMyApp\\AppiumMyApp\\bin\\x64\\Release\\net6.0-windows\\AppiumMyApp.exe";   
            appiumOptions.PlatformName = "windows";
            appiumOptions.DeviceName = "windowsPC";
            
            //2.start the driver
            var appiumLocalServer=new AppiumServiceBuilder().UsingAnyFreePort().Build();
            appiumLocalServer.Start();
            var driver = new WindowsDriver<WindowsElement>(appiumLocalServer, appiumOptions);
           //return the sever session
            return driver;
     }
  1. 完善TestMethod,定位界面元素并进行交互操作
    • 点击clear button
    • 点击编辑button
    • 发送字符串到文本框
    • 点击save button
    • 建立DefaultWait每500ms轮询一次查看是否弹出了保存文件的对话框我这里用来界面出现保存button 如果出现表示前面的步骤执行结束。才会继续执行后续的动作
    • 同样建立第二个DefaultWait等到界面弹出一个对话框 包含一个元素Name为“文件已导出”表示文件已经保存完毕了。
[TestMethod]
        public void TestWaitForProgressBar()
        {
       	 //start session
            var session = StartNodepadApplication();
        // FindUIElementMethod1 -Name,click clear button
            var clearButton = session.FindElementByName("Clear");
            clearButton.Click();
       // FindUIElementMethod2 -AccessibilityId, click button
            var textBox = session.FindElementByAccessibilityId("MyTextBoxID");
            textBox.Clear();
       //SendKeys     
            textBox.SendKeys("-----------------------------------------\n");
            textBox.SendKeys("******************************************\n");
            textBox.SendKeys("my name is jerry\n");
            //click save
            var saveButton= session.FindElementByName("Save");
            saveButton.Click();
            
      //Wait for the progress to process for a while.untill Element appear or disappear
      //1.add a DefaultWait,Poll once every 500ms
            var wait = new DefaultWait<WindowsDriver<WindowsElement>>(session)
            {
                Timeout = TimeSpan.FromSeconds(60),
                PollingInterval = TimeSpan.FromMilliseconds(500)
            };
            wait.IgnoreExceptionTypes(typeof(NoSuchElementException));

            //界面能找到说明前面动作已经执行完毕
            wait.Until(d => d.FindElementByName("保存(S)"));
            //click save button in SaveFileDialog
            var dialogSavebutton = session.FindElementByName("保存(S)");
            dialogSavebutton.Click();

   	//2.
            var wait2 = new DefaultWait<WindowsDriver<WindowsElement>>(session)
            {
                Timeout = TimeSpan.FromSeconds(60),
                PollingInterval = TimeSpan.FromMilliseconds(500)
            };
            wait.IgnoreExceptionTypes(typeof(NoSuchElementException));

            //find element to verify save done
            wait.Until(d =>
            {
                return d.FindElementByName("文件已导出");
            });
            session.FindElementByName("确定").Click();

            textBox = session.FindElementByAccessibilityId("MyTextBoxID");
            textBox.Clear();
            textBox.SendKeys("file save done this is second time I am here-\n");

            session.Close();
        }

项目右键-运行测试-可以看到会开始执行自动化测试。

六、编写android自动化应用测试程序

6.1 inspector 连接真机

6.1.1获取连接真机app的相关参数

准备工作手机开启开发者模式一般连续点击系统版本5下开启usb 调试模式
最好是能使用root 命令的手机因为我在使用普通手机时出现了连接不上的问题
第三章提到过安卓应用启动需要设置以下Capabilities获取方式标注在了右边
可参考链接https://blog.csdn.net/u012028250/article/details/120371345

keyName描述adb 命令
platformName手机操作系统Android
platformVersion操作系统版本adb shell getprop ro.build.version.release在这里插入图片描述
deviceName手机或模拟器类型adb devices
在这里插入图片描述
appPackage运行的 Android 应用的包名手机上打开要测试的app输入 adb shell "dumpsys window | grep mCurrentFocus" 在这里插入图片描述
appActivity从包中所要启动的 Android acticity同上

appPackage获取方式有如下几种package都是com.xxx

  • adb shell pm list packages列出手机上所有的包找到所需要的包名
  • adb shell am monitor 获取当前应用程序包名

appActivity获取方式

  • adb shell dumpsys activity | findstr “mResume”
    在这里插入图片描述com.sec.android.app.camera/.Camera t243} ---即appPackage / appActivity
  • adb shell "dumpsys window \| grep mCurrentFocus"
    在这里插入图片描述
    mCurrentFocus=Window{c22cf8f u0 com.sec.android.app.camera/com.sec.android.app.camera.Camera} ---即appPackage / appActivity
    获取之后填入到inspector中
    在这里插入图片描述

图片中SM-A336B是通过adb shell getprop ro.product.model获取的指的是手机型号可填可不填。
appium:automationName指以什么方式解析界面元素UiAutomator2
填完之后点击start session手机会自动安装appium 相关软件然后就可以启动手机中应用并且获取界面控件元素了。

6.1.1查看界面元素信息

在这里插入图片描述

6.2 MSTest测试程序连接真机

6.2.1 参考inspector启动应用


        private AndroidDriver<AndroidElement> StartApp()
        {
            System.Environment.SetEnvironmentVariable("ANDROID_HOME", @"C:\\Microsoft\\AndroidSDK\\25");
            System.Environment.SetEnvironmentVariable("JAVA_HOME", @"C:\\Program Files\\Microsoft\\jdk-11.0.12.7-hotspot");

            //connect to a device or emulator
            var capabilities = new AppiumOptions();
             capabilities.DeviceName=@"SM-A336B-58f407b9db347ece";
            //capabilities.DeviceName = @"58f407b9db347ece";
            capabilities.AutomationName = @"UiAutomator2";
            capabilities.PlatformName = "Android";
            capabilities.PlatformVersion = "12";

            //specifying which app we want to install or launch
            capabilities.AddAdditionalAppiumOption("appPackage", "com.sec.android.app.camera");
            capabilities.AddAdditionalAppiumOption("appActivity", "com.sec.android.app.camera.Camera");
            
            //specify startup flags appium sever to execute adb shell commands
            var serveroptions = new OptionCollector();
            var relaxedSecurityOption = new KeyValuePair<string, string>("--relaxed-security", "");
            serveroptions.AddArguments(relaxedSecurityOption);
            var _appiumLocalService = new AppiumServiceBuilder().UsingAnyFreePort().WithArguments(serveroptions).Build();
            
            //start the service
            _appiumLocalService.Start();
            var driver = new AndroidDriver<AndroidElement>(_appiumLocalService, capabilities);
            return driver;
        }

6.2.1 完善TestMethod


[ClassCleanup]//clear up local service
static public void CleanUp()
{
    _appiumLocalService?.Dispose();
    _appiumLocalService = null;
}
       
[TestMethod]
public void TestListInstallPackage()
{
    AndroidDriver<AndroidElement> driver = StartApp();
    //use shell command to list all installed package on the device
    string script = "mobile:shell";
    var arguments = new Dictionary<string, string>
    {
        {"command","pm list package" },
        { "----show-versioncode",""},
    };
    var list = driver.ExecuteScript(script, arguments);
    Assert.IsNotNull(list);
    Console.Write(list);
}

然后点击运行测试就可以看到手机相机启动了。

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6