前言

此文章 偏向于实操
appium支持在不同平台上(windows,linux、mac) - 使用测试脚本(支持不同语言C #,json,Ruby等等) - 模拟测试各个平台的app(web、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命令。比如postman,Appium 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. 安装Appium:Appium 有命令行版本和桌面版本。可以两个都装上,桌面版本:在appium官网下载并安装Appium。命令行版本,管理员模式运行cmd:npm 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 - Mac,ios 研发需要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-tools,ANDROID_HOME路径设置为C:\Microsoft\AndroidSDK\25

2.2 JAVA_HOME is not set

解决办法:

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

成功解决之后再次测试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 代替 MainActivity)MainActivity, .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里面可以找到对应的设置,比如Name,AccessibilityID。
在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组件的类型BUTTON,MENUBAR等等
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);
}

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

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐