Appium

1.基本环境搭建

Appium 是一个开源的移动应用自动化测试工具,支持 iOS 和 Android 平台。它可以用来自动化测试原生应用、混合应用和移动网页应用。Appium 提供了跨平台支持,能够在真实设备、模拟器和虚拟机上进行测试,并使用统一的 API。同时,Appium 兼容 WebDriver 协议,支持多种编程语言,如 Java、Python 和 JavaScript,简化了移动应用测试的自动化过程,并与流行的测试框架如 Selenium 无缝集成。通过 Appium,用户可以轻松地进行移动应用测试,提供了强大高效的测试解决方案。

在移动应用开发领域,有三种常见类型的应用:原生应用、混合应用和移动网页应用。

  1. 原生应用(Native App):原生应用是针对特定平台(如iOS或Android)使用原生编程语言(如Objective-C/Swift或Java/Kotlin)开发的应用程序。这些应用通过应用商店下载并安装在设备上,具有良好的性能和用户体验,并可以访问设备的硬件和功能(如相机、GPS等)。

  2. 混合应用(Hybrid App):混合应用结合了原生应用和Web应用的特点。它使用Web技术(如HTML、CSS、JavaScript)开发应用界面,并在原生的WebView中呈现。混合应用可以跨平台运行,并且在一些情况下可以访问设备的原生功能。

  3. 移动网页应用(Mobile Web App):移动网页应用是基于Web技术开发的应用,通过浏览器访问。这些应用通常响应式设计,适配各种屏幕大小,并可以在不同设备上运行。移动网页应用无需用户下载和安装,但通常访问设备功能的能力有限。

在移动应用测试中,需要针对这三种类型的应用编写测试用例,并确保应用在各种设备和环境下的稳定性、性能和用户体验。Appium作为一个通用的移动应用测试工具,支持测试原生应用、混合应用和移动网页应用,提供了统一的API和跨平台支持,为移动应用测试提供了便利和效率。

ADB(Android Debug Bridge)是一个强大的工具,用于在开发和调试Android应用程序时与Android设备进行通信。通过ADB,开发人员可以执行各种操作,包括安装和卸载应用程序、传输文件、查看设备日志、启动调试模式以及执行shell命令等。

ADB通过USB连接或通过网络连接到设备,并提供了一系列命令行选项,可以访问设备功能和信息,以及进行各种调试操作。开发人员可以使用ADB调试工具对应用程序进行测试、优化和调试,快速定位问题并进行解决。

ADB是Android SDK(软件开发工具包)的一部分,开发人员可以在电脑上运行ADB命令,与连接的Android设备进行通信,是Android应用程序开发过程中不可或缺的一个重要工具。

1.下载 android_SDK 并配置环境变量 android_SDK 依赖 jdk 所以需提前安装并配置 jdk。

path 中加入 build-tools 与 platform-tools 下的程序,注意:build-tools 下还有一个文件夹。

%ANDROID_HOME%\build-tools\34.0.0
%ANDROID_HOME%\platform-tools
%JAVA_HOME%\bin

配置完成后 cmd 输入 adb 不提示不是内部命令也不是可执行程序且 android_SDK\tools\bin\uiautomatorviewer 文件双击即可打开一个可视化界面即可说明安卓 SDK 环境配置完成。

夜神模拟器,是全新一代的安卓模拟器,能够让你在电脑上模拟多个不同型号和版本的手机。可以在 Android5/7/9/12 任意版本上运行相应。通过大屏显示和键鼠操控可以获得比手机更好的视觉享受和操控体验。

启动模拟器后使用 adb 连接模拟器。

adb connect 127.0.0.1:62001

adb devices:列出连接到计算机的所有 Android 设备。

2.adb 操作手机和模拟器

ADB 是 Android Debug Bridge 的缩写,是 Android 开发工具包(SDK)中的一个工具,用于在计算机和 Android 设备之间建立通信桥梁,可以通过 ADB 命令来管理 Android 设备、安装和卸载应用程序、查看日志信息等。ADB 通常用于开发人员调试和测试 Android 应用程序。

查看当前连接设备:adb devices,注意 1.0.41 不会自动连接需要使用 adb connect 127.0.0.1:62001 才能连接模拟器。如果有多个模拟器可以尝试用低版本的 adb 查看设备号。

D:\tools\1.0.36>adb devices
List of devices attached
127.0.0.1:62001 device

如果发现多个设备:

adb -s 设备号 其他指令

举例: adb -s devicel install xxx.apk

安装 apk 文件:

adb install xxx.apk

此安装方式,如果已经存在,无法安装; 推荐使用覆盖安装:adb install -r xxx.apk

卸载App 此命令通常需卸载的应用程序的包名。

adb uninstall com.zhy.app  

往手机SDCard传递文件:

adb push 文件名 手机端SDCard路径

例如: adb push 帅照.jpg /sdcard/

从手机端下载文件:

adb pull /sdcard/xxx.txt 

列出设备上所有的应用程序包名

adb shell pm list packages  

要查看设备上的第三方应用程序包名而不包括系统应用,使用以下命令: adb shell pm list packages -3

命令解析

  • adb:Android 调试桥,一种与模拟器或连接的 Android 设备进行通信的工具。
  • shell:在 Android 设备上打开一个 shell(命令行)。
  • pm:包管理器,用于管理应用程序的安装和卸载。
  • list packages:列出已安装的包(应用程序)。
  • -3:该选项用于过滤出仅显示第三方应用程序(排除系统应用)。

 

3.adb help

当你在命令行中输入 "adb help" 时,会显示关于 adb 命令的使用帮助信息。下面是一些常用 adb 命令的简要说明:

Android Debug Bridge version 1.0.36
Revision 19394af606f6-android

 -a                            - directs adb to listen on all interfaces for a connection
 -d                            - directs command to the only connected USB device
                                 returns an error if more than one USB device is present.
 -e                            - directs command to the only running emulator.
                                 returns an error if more than one emulator is running.
 -s <specific device>          - directs command to the device or emulator with the given
                                 serial number or qualifier. Overrides ANDROID_SERIAL
                                 environment variable.
 -p <product name or path>     - simple product name like 'sooner', or
                                 a relative/absolute path to a product
                                 out directory like 'out/target/product/sooner'.
                                 If -p is not specified, the ANDROID_PRODUCT_OUT
                                 environment variable is used, which must
                                 be an absolute path.
 -H                            - Name of adb server host (default: localhost)
 -P                            - Port of adb server (default: 5037)
 devices [-l]                  - list all connected devices
                                 ('-l' will also list device qualifiers)
 connect <host>[:<port>]       - connect to a device via TCP/IP
                                 Port 5555 is used by default if no port number is specified.
 disconnect [<host>[:<port>]]  - disconnect from a TCP/IP device.
                                 Port 5555 is used by default if no port number is specified.
                                 Using this command with no additional arguments
                                 will disconnect from all connected TCP/IP devices.

device commands:
  adb push <local>... <remote>
                               - copy files/dirs to device
  adb pull [-a] <remote>... <local>
                               - copy files/dirs from device
                                 (-a preserves file timestamp and mode)
  adb sync [ <directory> ]     - copy host->device only if changed
                                 (-l means list but don't copy)
  adb shell [-e escape] [-n] [-Tt] [-x] [command]
                               - run remote shell command (interactive shell if no command given)
                                 (-e: choose escape character, or "none"; default '~')
                                 (-n: don't read from stdin)
                                 (-T: disable PTY allocation)
                                 (-t: force PTY allocation)
                                 (-x: disable remote exit codes and stdout/stderr separation)
  adb emu <command>            - run emulator console command
  adb logcat [ <filter-spec> ] - View device log
  adb forward --list           - list all forward socket connections.
                                 the format is a list of lines with the following format:
                                    <serial> " " <local> " " <remote> "\n"
  adb forward <local> <remote> - forward socket connections
                                 forward specs are one of:
                                   tcp:<port>
                                   localabstract:<unix domain socket name>
                                   localreserved:<unix domain socket name>
                                   localfilesystem:<unix domain socket name>
                                   dev:<character device name>
                                   jdwp:<process pid> (remote only)
  adb forward --no-rebind <local> <remote>
                               - same as 'adb forward <local> <remote>' but fails
                                 if <local> is already forwarded
  adb forward --remove <local> - remove a specific forward socket connection
  adb forward --remove-all     - remove all forward socket connections
  adb reverse --list           - list all reverse socket connections from device
  adb reverse <remote> <local> - reverse socket connections
                                 reverse specs are one of:
                                   tcp:<port>
                                   localabstract:<unix domain socket name>
                                   localreserved:<unix domain socket name>
                                   localfilesystem:<unix domain socket name>
  adb reverse --no-rebind <remote> <local>
                               - same as 'adb reverse <remote> <local>' but fails
                                 if <remote> is already reversed.
  adb reverse --remove <remote>
                               - remove a specific reversed socket connection
  adb reverse --remove-all     - remove all reversed socket connections from device
  adb jdwp                     - list PIDs of processes hosting a JDWP transport
  adb install [-lrtsdg] <file>
                               - push this package file to the device and install it
                                 (-l: forward lock application)
                                 (-r: replace existing application)
                                 (-t: allow test packages)
                                 (-s: install application on sdcard)
                                 (-d: allow version code downgrade (debuggable packages only))
                                 (-g: grant all runtime permissions)
  adb install-multiple [-lrtsdpg] <file...>
                               - push this package file to the device and install it
                                 (-l: forward lock application)
                                 (-r: replace existing application)
                                 (-t: allow test packages)
                                 (-s: install application on sdcard)
                                 (-d: allow version code downgrade (debuggable packages only))
                                 (-p: partial application install)
                                 (-g: grant all runtime permissions)
  adb uninstall [-k] <package> - remove this app package from the device
                                 ('-k' means keep the data and cache directories)
  adb bugreport [<zip_file>]   - return all information from the device
                                 that should be included in a bug report.

  adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]
                               - write an archive of the device's data to <file>.
                                 If no -f option is supplied then the data is written
                                 to "backup.ab" in the current directory.
                                 (-apk|-noapk enable/disable backup of the .apks themselves
                                    in the archive; the default is noapk.)
                                 (-obb|-noobb enable/disable backup of any installed apk expansion
                                    (aka .obb) files associated with each application; the default
                                    is noobb.)
                                 (-shared|-noshared enable/disable backup of the device's
                                    shared storage / SD card contents; the default is noshared.)
                                 (-all means to back up all installed applications)
                                 (-system|-nosystem toggles whether -all automatically includes
                                    system applications; the default is to include system apps)
                                 (<packages...> is the list of applications to be backed up.  If
                                    the -all or -shared flags are passed, then the package
                                    list is optional.  Applications explicitly given on the
                                    command line will be included even if -nosystem would
                                    ordinarily cause them to be omitted.)

  adb restore <file>           - restore device contents from the <file> backup archive

  adb disable-verity           - disable dm-verity checking on USERDEBUG builds
  adb enable-verity            - re-enable dm-verity checking on USERDEBUG builds
  adb keygen <file>            - generate adb public/private key. The private key is stored in <file>,
                                 and the public key is stored in <file>.pub. Any existing files
                                 are overwritten.
  adb help                     - show this help message
  adb version                  - show version num

scripting:
  adb wait-for[-<transport>]-<state>
                               - wait for device to be in the given state:
                                 device, recovery, sideload, or bootloader
                                 Transport is: usb, local or any [default=any]
  adb start-server             - ensure that there is a server running
  adb kill-server              - kill the server if it is running
  adb get-state                - prints: offline | bootloader | device
  adb get-serialno             - prints: <serial-number>
  adb get-devpath              - prints: <device-path>
  adb remount                  - remounts the /system, /vendor (if present) and /oem (if present) partitions on the device read-write
  adb reboot [bootloader|recovery]
                               - reboots the device, optionally into the bootloader or recovery program.
  adb reboot sideload          - reboots the device into the sideload mode in recovery program (adb root required).
  adb reboot sideload-auto-reboot
                               - reboots into the sideload mode, then reboots automatically after the sideload regardless of the result.
  adb sideload <file>          - sideloads the given package
  adb root                     - restarts the adbd daemon with root permissions
  adb unroot                   - restarts the adbd daemon without root permissions
  adb usb                      - restarts the adbd daemon listening on USB
  adb tcpip <port>             - restarts the adbd daemon listening on TCP on the specified port

networking:
  adb ppp <tty> [parameters]   - Run PPP over USB.
 Note: you should not automatically start a PPP connection.
 <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1
 [parameters] - Eg. defaultroute debug dump local notty usepeerdns

adb sync notes: adb sync [ <directory> ]
  <localdir> can be interpreted in several ways:

  - If <directory> is not specified, /system, /vendor (if present), /oem (if present) and /data partitions will be updated.

  - If it is "system", "vendor", "oem" or "data", only the corresponding partition
    is updated.

internal debugging:
  adb reconnect                  Kick current connection from host side and make it reconnect.
  adb reconnect device           Kick current connection from device side and make it reconnect.
environment variables:
  ADB_TRACE                    - Print debug information. A comma separated list of the following values
                                 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp
  ANDROID_SERIAL               - The serial number to connect to. -s takes priority over this if given.
  ANDROID_LOG_TAGS             - When used with the logcat option, only these debug tags are printed.

翻译.....

4.adb 应用调试

查看焦点应用程序

一、windows环境下:在 Android 9 及更高版本中,由于安全性增强措施,部分命令可能无法直接运行。可以尝试使用以下命令来获取当前焦点应用程序:将 mFocusedActivity 换成 mResumedActivity 即可。

adb shell dumpsys activity | findstr mFocusedActivity

在 Android 12 及更高使用如下命令。

adb shell dumpsys window | findstr "mCurrentFocus"

二、Linux、Mac环境下:

adb shell dumpsys activity | grep mFocusedActivity

启动指定应用的特定 Activity

adb shell am start 包名/完整Activity路径

如:adb shell am start com.zhy.aaa/com.zhy.aaa.MainActivity如果需要携带参数(携带一个Key 为name参数):adb shell am start com.zhy.aaa/com.zhy.aaa.MainActivity -e name zhy

要使用 adb 获取应用程序的启动时间,您可以通过以下步骤进行:

  1. 首先,在终端或命令提示符中,连接到设备并运行以下命令以启动日志记录。
adb shell am start -W <package_name>/<activity_name>

请将package_name替换为应用程序的包名,将activity_name替换为要启动的活动名称。

启动应用程序后,会看到应用程序的启动时间(包括启动时间、总时间等)。

D:\tools\1.0.36>adb shell am start -W com.android.settings/.Settings$WallpaperSettingsActivity
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.android.settings/.Settings }
Warning: Activity not started, its current task has been brought to the front
Status: ok
Activity: com.android.settings/.Settings
ThisTime: 76
TotalTime: 76
WaitTime: 79
Complete

在使用 adb 命令启动应用程序时,会返回一些关于应用程序启动性能的信息,其中包括以下三个关键指标的含义:

  1. ThisTime(本次时间):指应用程序启动的实际时间,即应用程序从启动到完全显示在屏幕上所花费的时间。

  2. TotalTime(总时间):指应用程序启动的总时间,包括等待时间和实际启动时间。总时间是应用程序启动的完整过程所花费的时间。

  3. WaitTime(等待时间):指在启动应用程序之前,应用程序等待的时间。等待时间包括应用程序启动前的任何延迟或等待时间。

这些指标可以帮助您评估应用程序的启动性能和优化启动时间。通过监视这些指标,您可以了解应用程序启动的效率,并采取必要的措施来改善用户体验。

5.安装 Appium

1.安装 node.js 并使用 npm 方法全局安装 Appium

npm i -g appium

安装后,应该能够从命令行运行 Appium:

appium

如果更新 Appium,请使用:npm npm update -g appium

2.安装 UiAutomator2 驱动

如果没有驱动,你几乎无法使用 Appium,驱动是允许 Appium 自动化特定平台的接口。

appium driver install uiautomator2

根据驱动的要求,除了一个运行中的 Appium 服务器,还需要设置 ANDROID_HOME 环境变量,指向安装 Android SDK 的目录。它将包含 platform-tools 和 build-tools 目录。

它应该产生类似下面的输出:

Attempting to find and install driver 'uiautomator2'
✔ Installing 'uiautomator2' using NPM install spec 'appium-uiautomator2-driver'
Driver uiautomator2@2.0.5 successfully installed
- automationName: UiAutomator2
- platformNames: ["Android"]

最后启动 appium 看到一些以如下的输出说明启动成功

C:\Users\Administrator>appium
[Appium] Welcome to Appium v2.5.4
[Appium] The autodetected Appium home path: C:\Users\Administrator\.appium
[Appium] Attempting to load driver uiautomator2...
[Appium] Requiring driver at C:\Users\Administrator\.appium\node_modules\appium-uiautomator2-driver\build\index.js
[Appium] AndroidUiautomator2Driver has been successfully loaded in 54.365s
[Appium] Appium REST http interface listener started on http://0.0.0.0:4723
[Appium] You can provide the following URLs in your client code to connect to this server:
[Appium]        http://192.168.4.25:4723/
[Appium]        http://127.0.0.1:4723/ (only accessible from the same host)
[Appium] Available drivers:
[Appium]   - uiautomator2@3.5.2 (automationName 'UiAutomator2')
[Appium] No plugins have been installed. Use the "appium plugin" command to install the one(s) you want to use.

打开 PyCharm 并创建项目 appium-test,并在项目中安装 Appium-Python-Client4.0.0

文档:Client Challenge

代码如下:

from time import sleep

from appium import webdriver
from appium.options.android import UiAutomator2Options

capabilities = dict(
    platformName='Android',
    automationName='uiautomator2',
    deviceName='Android',
    appPackage='com.android.settings',
    appActivity='.Settings'
)
appium_server_url = 'http://localhost:4723'
driver = webdriver.Remote(appium_server_url, options=UiAutomator2Options().load_capabilities(capabilities))
sleep(3)
driver.quit()

如果看到模拟器启动系统设置程序,说明已经配置成功。

如果出现启动手机屏幕闪退,appium 提示丢失连接,adb 重连后报错是因为 adb 有两个版本不兼容。找到夜神模拟器中的 adb拷贝到 Android 的目录替换即可。

D:\Program Files\Nox\bin下的adb相关三个文件:adb.exe、AdbWinApi.dll、AdbWinUsbApi.dll

在使用 Appium 进行移动应用测试时,capabilities是用于定义测试配置的重要参数。以下是一些常用的属性,特别是在 Android 和 iOS 平台上:

常用 Android Desired Capabilities

  1. platformName: 指定平台名称,通常为'Android''iOS'

  2. platformVersion: 设备的操作系统版本,格式为字符串(例如'10''11.0')。

  3. deviceName: 要使用的设备名称,可以是物理设备的名称或模拟器的名称。

  4. app: 应用的路径,通常是在本地机器上或 URL 地址(用于 APK 或 IPA 文件)。

  5. appPackage: Android 应用的包名,例如'cn.readpad.whiteboard'

  6. appActivity: Android 应用的主活动名称,通常为点分隔的格式(例如'.MainActivity')。

  7. automationName: 自动化引擎的名称,常用的值是'uiautomator2''espresso'(对于 Android)以及'XCUITest'(对于 iOS)。

  8. noReset: 设置为True时,Appium 不会在测试开始前重置应用程序的状态。

  9. fullReset: 设置为True时,会完全重置应用程序的状态,通常用于回到初始状态。

  10. waitForIdleTimeout: 等待应用程序处于空闲状态的超时(以毫秒为单位)。

  11. unicodeKeyboard: 如果设置为True,则使用 Unicode 键盘进行输入。

  12. resetKeyboard: 如果设置为True,则在测试完成后重置键盘到原始状态。

常用 iOS Desired Capabilities

  1. platformName: 通常为'iOS'

  2. platformVersion: iOS 操作系统版本。

  3. deviceName: iOS 设备名称。

  4. app: iOS 应用的路径或 URL。

  5. udid: 连接到设备的唯一设备 ID,通常用于物理设备。

  6. automationName:'XCUITest'是当前 iOS 推荐的自动化引擎。

  7. xcodeOrgIdxcodeSigningId: 用于设置 Xcode 的组织 ID 和签名 ID。

  8. newCommandTimeout: 如果没有命令达到该时间,则会关闭会话(单位为秒)。

其他功能选择

此外,还可以根据需要设置其他高级配置,这些可能包括:

  • chromeOptions: 当使用 Chrome 或 WebView 时,指定 Chrome 的某些选项。
  • network поведение(网络行为)等。

示例代码

以下是一个包含多种能力的示例代码:

capabilities = {  
    'platformName': 'Android',  
    'platformVersion': '11',  
    'deviceName': 'Android Emulator',  
    'appPackage': 'cn.readpad.whiteboard',  
    'appActivity': '.MainActivity',  
    'automationName': 'UiAutomator2',  
    'noReset': True,  
    'fullReset': False,  
    'waitForIdleTimeout': 1000,  
    'unicodeKeyboard': True,  
    'resetKeyboard': True,  
}

使用这些能力时,确保它们适合你的设备和应用程序的特性,以获得最佳的测试效果。

练习:

1.安装应用宝应用,获取应用首页的appPackage 与 appActivity ,并使用代码启动使其打开。

2.安装向日葵客户端应用,获取应用首页的appPackage 与appActivity ,并使用代码启动使其打开。

参考代码:

1.应用宝

C:\Users\Administrator>adb shell dumpsys activity | findstr mResumedActivity
    mResumedActivity: ActivityRecord{65e9245 u0 com.tencent.android.qqdownloader/com.tencent.assistantv2.activity.MainActivity t26}

appPackage:com.tencent.android.qqdownloader

appActivity:com.tencent.assistantv2.activity.MainActivity

2.向日葵控制端

C:\Users\Administrator>adb shell dumpsys activity | findstr mResumedActivity
    mResumedActivity: ActivityRecord{ccd6151 u0 com.oray.sunlogin.service/com.oray.sunlogin.application.Main t31}

appPackage:com.oray.sunlogin.service

appActivity:com.oray.sunlogin.application.Main

6.Java 操作

在Java中使用Appium进行自动化测试的步骤与Python相似。下面是一个简单的Java代码示例,演示如何使用Appium与Android设备进行连接并启动设置应用。

如果使用Maven管理Java项目,请在pom.xml中添加以下依赖项:

<dependencies>  
    <dependency>  
        <groupId>io.appium</groupId>  
        <artifactId>java-client</artifactId>  
        <version>7.6.0</version>  
    </dependency>  
</dependencies>

以下是一个简单的Java代码示例,连接到Appium服务器并启动Android设置应用:

import io.appium.java_client.AppiumDriver;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.remote.MobileCapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import java.net.MalformedURLException;
import java.net.URL;


public class AppiumExample {
    public static void main(String[] args) throws InterruptedException, MalformedURLException {
        // 设置Capabilities  
        DesiredCapabilities capabilities = new DesiredCapabilities();
        capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
        capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android");
        capabilities.setCapability("appPackage", "com.android.settings");
        capabilities.setCapability("appActivity", ".Settings");
        capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, "UiAutomator2");

        // Appium服务器地址  
        String appiumServerUrl = "http://localhost:4723";

        // 创建AndroidDriver实例
        AppiumDriver driver = new AndroidDriver(new URL(appiumServerUrl), capabilities);
        // 等待3秒
        Thread.sleep(3000);

        // 退出驱动
        driver.quit();
    }
}

运行代码

  1. 确保Appium服务器正在运行,通常通过命令行运行appium启动。
  2. 将上面的代码放入Java项目中,并确保您已经正确配置了Maven依赖。
  3. 运行该程序,Appium将启动Android设备上的设置应用程序。

7.UI Automator Viewer

UI Automator Viewer 是 Android Studio 提供的图形工具,用于查看和与 Android 应用程序用户界面进行交互。它允许开发人员查看应用程序的布局层次结构,检查 UI 元素,并生成自动化 UI 测试脚本。该工具位于 SDK 目录下的 tools 子目录下。可以看到,它是通过 bat 文件启动的。

使用 UI Automator Viewer 之前先确保安装 jdk。如果 UI Automator Viewer 闪退一般是 jdk 未成功安装或版本不对。

将应用启动到指定页面上后点击第二个图标按钮即可获取设备快照 Device Screenshot (uiautomator dump)。

点击对应的节点即可在右下角看到节点的信息。

使用 appium 代码点击该节点。

# element = driver.find_element(By.ID, "com.android.settings:id/dashboard_tile")
element = driver.find_element(By.CLASS_NAME, "android.widget.LinearLayout")
element.click()

可以看到页面已经正常跳转。

注意:如果见到如下报错,则重启 adb 服务即可。

如果你想重启ADB服务器,可以按照以下步骤进行操作:

打开命令提示符(CMD)或终端窗口。

输入以下命令来停止ADB服务器:

adb kill-server

然后输入以下命令来启动ADB服务器:

adb start-server

确保ADB服务器已成功启动,并且没有任何错误信息显示。

通过这种方法重新启动ADB服务器可能有助于解决一些与ADB服务器相关的问题。

练习:

1.使用 adb 命令测试出淘宝 App 的启动时间的是否满足需求? 启动时间必须≤1s

2.使用 UiAutoMatorViewer 获取的淘宝 App 搜索输入框下面列元素信息?

1题

C:\Users\Administrator>adb shell dumpsys activity | findstr mFocusedActivity
  mFocusedActivity: ActivityRecord{f1a4c39 u0 com.taobao.taobao/com.taobao.tao.TBMainActivity t24}


C:\Users\Administrator>adb shell am start -W com.taobao.taobao/com.taobao.tao.TBMainActivity
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.taobao.taobao/com.taobao.tao.TBMainActivity }
Status: ok
Activity: com.taobao.taobao/com.taobao.tao.TBMainActivity
ThisTime: 306
TotalTime: 306
WaitTime: 314
Complete

2题

3.题

adb logcat

看日志

8.Appium基础Api

如果一个应用需要跳转到另外一个应用,就可以使用这个 api 进行应用的跳转,就像我们通过外卖应用 下订单之后会跳转到支付应用一样。

driver.activate_app("com.android.gallery3d")
driver.terminate_app("com.android.gallery3d")

启动相册,关闭相册。

一些应用市场的软件可能会有一个按钮,如果某一个程序已经安装则卸载,如果没有安装则安装。

# 安装app
#参数:
#  app_path:apk路径
driver.install_app(app_path)
# 卸载app
#参数:
#  app_id:应用程序包名
driver.remove_app(app_id)
#判断app是否已经安装
#参数:
#  app_id:应用程序包名
#返回值:
#  布尔类型,True为安装,False为没有安装
driver.is_app_installed(app_id)

如果《应用宝》已经安装,则卸载,否则就安装该 app

if driver.is_app_installed("com.tencent.android.qqdownloader"):
    driver.remove_app("com.tencent.android.qqdownloader")
else:
    driver.install_app("D://应用宝.apk")

银行类 app 会在进入后台一定时间后,如果再回到前台也页面会重新输入密码,如果需要自动化测试这 种功能,可以使用这个 api 进行测试

# app放置到后台一定时间后再回到前台,模拟热启动
#参数:
#  seconds:后台停留多少秒
driver.background_app(seconds)

back、forward、refresh也是常见的操作,用法和浏览器差不多。

driver.back()
driver.forward()
driver.refresh()

练习:

1.编写程序打开应用宝,点击热门应用栏全部按钮,进入热门应用并获取它们的名字打印到控制台。

2.点击前三个应用的下载按钮,将应用下载到模拟器(如果已经下载则跳过安装)。

3.点击返回按钮返回主页。

参考代码:

from time import sleep

from appium import webdriver
from appium.options.android import UiAutomator2Options
from appium.webdriver.common.appiumby import AppiumBy

capabilities = dict(
    platformName='Android',
    automationName='uiautomator2',
    deviceName='Android',
    appPackage='com.android.settings',
    appActivity='.Settings'
)
appium_server_url = 'http://localhost:4723'
driver = webdriver.Remote(appium_server_url, options=UiAutomator2Options().load_capabilities(capabilities))
if driver.is_app_installed("com.tencent.android.qqdownloader"):
    driver.remove_app("com.tencent.android.qqdownloader")
else:
    driver.install_app("D://1.0.36/apk/应用宝.apk")

sleep(3)
driver.quit()

代码2

from time import sleep

from appium import webdriver
from appium.options.android import UiAutomator2Options
from selenium.webdriver.common.by import By

capabilities = dict(
    platformName='Android',
    automationName='uiautomator2',
    deviceName='Android',
    appPackage=' com.tencent.android.qqdownloader',
    appActivity='com.tencent.assistantv2.activity.MainActivity'
)
appium_server_url = 'http://localhost:4723'
driver = webdriver.Remote(appium_server_url, options=UiAutomator2Options().load_capabilities(capabilities))
sleep(5)
driver.find_element(By.XPATH, "//*[@text='同意']").click()
# sleep(3)
# driver.back()
sleep(5)
driver.find_element(By.XPATH, "//*[@text='精选']").click()
sleep(5)
driver.find_element(By.XPATH, "//*[@text='全部']").click()
sleep(10)
els = driver.find_elements(By.CLASS_NAME, "android.widget.TextView")
for e in els:
    print(e.text)
sleep(10)
driver.quit()

9.元素等待

在 Appium 中,您可以使用隐式等待来设置全局的等待时间,这样在查找元素时如果元素未立即找到,Appium 将等待一段时间再继续执行后续代码。下面是如何设置隐式等待的示例代码:

# 设置隐式等待时间为10秒
driver.implicitly_wait(10)
print("查找元素")
# 在进行元素定位时,如果元素不立即找到,Appium 将等待最多10秒
element = driver.find_element(By.XPATH, '//*[@text="壁纸"]')
print("找到点击")
element.click()

在上面的示例中,driver.implicitly_wait(10) 表示设置隐式等待时间为 10 秒。当调用 find_element_by_id 方法时,如果元素不立即找到,Appium 将最多等待10秒后继续执行后续代码。超出时长抛出 NoSuchElementError: An element could not be located on the page using the given search parameters.异常。注意在 appium 操作 app 时可以使用人工干预的。

在 Appium 中,可以使用显式等待来等待特定条件发生后再继续执行后续代码。下面是一个使用显式等待的示例代码:from selenium.webdriver.support import expected_conditions

# 设置最大等待时间为10秒
wait = WebDriverWait(driver, 10)
element = wait.until(
    expected_conditions.visibility_of_element_located((By.XPATH, '//*[@text="壁纸"]')))
# 对元素进行操作
element.click()

在上面的示例中,我们直接通过 By 模块来指定定位方法,比如 By.ID、By.XPATH 等,然后使用 WebDriverWait 和 expected_conditions 中的方法来实现显式等待,并且我们将最大等待时间设置为10秒。

显式等待和隐式等待是两种在自动化测试中用于等待元素加载的不同技术。它们之间的主要区别如下:

1.显式等待:

  • 显式等待是在需要等待特定条件发生时才等待,等待条件可以是元素可见、元素存在、元素可点击等。
  • 通过使用WebDriverWaitexpected_conditions类,可以设置具体的等待条件和最大等待时间。
  • 只会等待特定条件成立后再继续执行后续代码,如果等待时间超过最大等待时间则抛出超时异常。
  • 更灵活,可以针对不同元素设置不同的等待条件和时间。

2.隐式等待:

  • 隐式等待是在查找元素时等待一定的时间,如果元素立即找到则立即继续执行后续代码,如果未找到则等待设定的时间后再继续执行。
  • 通过driver.implicitly_wait(time)方法设置全局的等待时间,适用于所有的元素查找操作。
  • 不会针对特定的条件等待,而是等待固定的时间后继续执行。如果元素在等待时间内找到,则会立即继续执行,否则会抛出找不到元素的异常。

总体而言,显式等待更加灵活,可以根据具体需要设置不同的等待条件和时间,而隐式等待则提供了全局的等待时间设置,适用于整个测试用例。根据具体情况选择合适的等待方式可以提高稳定性和效率。

10.元素操作API

在 Appium 中,获取元素后可以使用一系列属性和方法 API 对元素进行操作和验证。以下是一些常用的属性和方法 API:

常用属性:

  1. text: 获取元素的文本内容
  2. location: 获取元素在屏幕上的位置
  3. size: 获取元素的大小(宽度和高度)

常用方法:

  1. click(): 点击元素
  2. sendKeys(text): 在元素上输入文本
  3. clear(): 清空元素中的文本
  4. is_selected(): 判断元素是否被选中
  5. is_enabled(): 判断元素是否可操作
  6. is_displayed(): 判断元素是否可见
  7. get_attribute(attrName): 获取元素的指定属性的值如:checkable, checked, {class,className}, clickable, {content-desc,contentDescription}, enabled, focusable, focused, {long-clickable,longClickable}, package, password, {resource-id,resourceId}, scrollable, selection-start, selection-end, selected, {text,name}, hint, extras, bounds, displayed, contentSize, {a11y-important,importantForAccessibility}, {screen-reader-focusable,screenReaderFocusable}, {input-type,inputType}, {drawing-order,drawingOrder}, {showing-hint,showingHintText}, {text-entry-key,textEntryKey}, {multiline,multiLine}, dismissable, {a11y-focused,accessibilityFocused}, heading, {live-region,liveRegion}, {context-clickable,contextClickable}, {max-text-length,maxTextLength}, {content-invalid,contentInvalid}, {error,errorText}, {pane-title,paneTitle}, actions

案例

element = driver.find_element(By.ID, "com.android.settings:id/search")
# 对元素进行点击
element.click()
# 对文本框进行输入
element = driver.find_element(By.ID, "android:id/search_src_text")
element.send_keys("张三")
sleep(3)
# 对文本框进行清空
element.clear()

案例:

driver.implicitly_wait(1)

driver.find_element(By.XPATH, "//*[@text='显示']").click()

# elements = driver.find_elements(By.XPATH, "//android.widget.TextView")
elements = driver.find_elements(By.CLASS_NAME, "android.widget.TextView")
for element in elements:
    print(element.text)

11.滑动和拖拽

我们在做自动化测试的时候,有些按钮是需要滑动几次屏幕后才会出现,此时,我们需要使用代码来模 拟手指的滑动,也就是我们将要学习的滑动和拖拽事件。

1.swipe 从一个坐标位置滑动到另一个坐标位置,只能是两个点之间的滑动(值不能超过屏幕分辨率范围)。

# 模拟手指从(100, 1000),滑动到(100, 0)的位置
driver.swipe(100, 1000, 100, 0)
# 模拟手指从(100, 1000),滑动到(100, 2000)的位置
driver.swipe(100, 1000, 100, 2000)
# 模拟手指从(100, 1000),滑动到(100, 0)的位置,持续3秒
driver.swipe(100, 1000, 100, 0, 3000)

距离相同时,持续时间越长,惯性越小。持续时间相同时,手指滑动的距离越大,实际滑动的距离也就越大。

2.scroll 从一个元素滑动到另一个元素,直到页面自动停止。  

# 模拟手指从 WLAN,滑动到 声音 的位置,时间3秒,不填默认 0.6秒。
destination_el = driver.find_element(By.XPATH, "//*[@text='WLAN']")
origin_el = driver.find_element(By.XPATH, "//*[@text='声音']")
driver.scroll(origin_el, destination_el, 3000)

注意:元素如果在该屏幕上看不见,这不能滑动。

练习:

1.在应用市场中搜索抖音并进行安装,安装完成后点击打开。

2.打开抖音,并使用代码刷短视频,5秒换一个短视频。

题1

from time import sleep

from appium import webdriver
from appium.options.android import UiAutomator2Options
from selenium.webdriver.common.by import By

capabilities = dict(
    platformName='Android',
    automationName='uiautomator2',
    deviceName='Android',
    appPackage='com.yysc.one.vs',
    appActivity='com.duoduoapp.market.activity.ui.WelcomeActivity'
)
appium_server_url = 'http://localhost:4723'
driver = webdriver.Remote(appium_server_url, options=UiAutomator2Options().load_capabilities(capabilities))
driver.implicitly_wait(20)
driver.find_element(By.XPATH, "//*[@text='同意']").click()
driver.find_element(By.ID, "com.yysc.one.vs:id/la_search").click()

driver.find_element(By.ID, "com.yysc.one.vs:id/et_search").send_keys("抖音")
driver.find_element(By.ID, "com.yysc.one.vs:id/la_search").click()
driver.find_element(By.XPATH, "//*[@text='下载']").click()
driver.find_element(By.XPATH, "//*[@text='安装']").click()
sleep(10)
driver.quit()

题2

from time import sleep

from appium import webdriver
from appium.options.android import UiAutomator2Options
from selenium.webdriver.common.by import By

capabilities = dict(
    platformName='Android',
    automationName='uiautomator2',
    deviceName='Android',
    appPackage='com.ss.android.ugc.aweme',
    appActivity='.splash.SplashActivity'
)
appium_server_url = 'http://localhost:4723'
driver = webdriver.Remote(appium_server_url, options=UiAutomator2Options().load_capabilities(capabilities))
driver.implicitly_wait(20)
driver.find_element(By.XPATH, "//*[@text='同意']").click()
for i in range(10):
    driver.swipe(300, 1000, 300, 200)
    sleep(5)
sleep(10)
driver.quit()

12.ActionChains(一)

ActionChains 是一种自动执行简单交互的方法,例如鼠标移动、鼠标按钮操作、按键和上下文菜单交互。这对于执行更复杂的操作(例如悬停和拖放)很有用。

注意如果需要使用五指点击,通过 driver.tap()方法即可完成。

driver.tap([(100, 20), (100, 60), (100, 100)], 500)

用最多五根手指敲击特定位置,按住一定时间 positions:表示要敲击的手指的 x/y 坐标的元组数组。长度最多可为 5 个。持续时间:点击的时间长度,以毫秒为单位。

生成用户操作:

在 ActionChains 对象上调用操作的方法时,操作将存储在 ActionChains 对象的队列中。调用 perform 方法时,事件将按照其排队顺序触发。ActionChains 可以在链模式中使用

menu = driver.find_element(By.CSS_SELECTOR, ".nav")
hidden_submenu = driver.find_element(By.CSS_SELECTOR, ".nav #submenu1")
ActionChains(driver).move_to_element(menu).click(hidden_submenu).perform()

或者可以一个接一个地排队,然后执行

menu = driver.find_element(By.CSS_SELECTOR, ".nav")
hidden_submenu = driver.find_element(By.CSS_SELECTOR, ".nav #submenu1")

actions = ActionChains(driver)
actions.move_to_element(menu)
actions.click(hidden_submenu)
actions.perform()

无论哪种方式,操作都按照它们被调用的顺序一个接一个地执行。

案例:指定位置点击

actions = ActionChains(driver)
actions.w3c_actions.pointer_action.move_to_location(144, 614)
actions.w3c_actions.pointer_action.click()
actions.perform()

案例:按下坐标后3秒放开

actions = ActionChains(driver)
actions.w3c_actions.pointer_action.move_to_location(144, 614)
actions.w3c_actions.pointer_action.pointer_down()
actions.w3c_actions.pointer_action.pause(3)
actions.w3c_actions.pointer_action.pointer_up()

13.ActionChains(二)

在 UIA2 上,某些元素可以使用指针操作而不是 Selenium Python 客户端中的默认指针操作进行处理。 例如,下面的操作生成器是将默认操作替换为指针操作。

打开页面 .ChooseLockPattern 并在其上绘制图型。

要计算九宫格中每个格子的中心坐标,首先,我们需要确定九宫格的分布。九宫格通常以3×3的形式排列,因此我们将其分为9个小格子。

给定两个坐标:

  • 起始坐标:(36, 506)
  • 结束坐标:(684, 1154)

首先,我们计算九宫格的宽度和高度:

  1. 计算宽度和高度:宽度 = 684 -36=648;高度 = 1154 -506=648

    • 宽度 = 结束坐标的 x 值 - 起始坐标的 x 值
    • 高度 = 结束坐标的 y 值 - 起始坐标的 y 值
  2. 计算每个格子的宽度和高度: 因为是 3 × 3 的九宫格,因此:每个格子的宽度 = 648 /3=216;每个格子的高度 = 648 /3=216

    • 每个格子的宽度 = 宽度 / 3
    • 每个格子的高度 = 高度 / 3
  3. 计算每个格子的左上角坐标: 每个格子的左上角坐标可以通过以下公式计算:

    • 对于第 i 行、第 j 列的格子:
      • 左上角坐标:(起始 x + j * 每个格子的宽度, 起始 y + i * 每个格子的高度)
  4. 计算每个格子的中心坐标

    • 格子的中心坐标为:
      • 中心坐标 = (左上角坐标 x + 每个格子的宽度 / 2, 左上角坐标 y + 每个格子的高度 / 2)

我们可以列出 9 个格子的中心坐标:

  • 第一行

    • 第一格中心:(36+0×216+108,506+0×216+108)=(108,578)(36+0×216+108,506+0×216+108)=(108,578)
    • 第二格中心:(36+1×216+108,506+0×216+108)=(324,578)(36+1×216+108,506+0×216+108)=(324,578)
    • 第三格中心:(36+2×216+108,506+0×216+108)=(540,578)(36+2×216+108,506+0×216+108)=(540,578)
  • 第二行

    • 第一格中心:(36+0×216+108,506+1×216+108)=(108,794)(36+0×216+108,506+1×216+108)=(108,794)
    • 第二格中心:(36+1×216+108,506+1×216+108)=(324,794)(36+1×216+108,506+1×216+108)=(324,794)
    • 第三格中心:(36+2×216+108,506+1×216+108)=(540,794)(36+2×216+108,506+1×216+108)=(540,794)
  • 第三行

    • 第一格中心:(36+0×216+108,506+2×216+108)=(108,1010)(36+0×216+108,506+2×216+108)=(108,1010)
    • 第二格中心:(36+1×216+108,506+2×216+108)=(324,1010)(36+1×216+108,506+2×216+108)=(324,1010)
    • 第三格中心:(36+2×216+108,506+2×216+108)=(540,1010)(36+2×216+108,506+2×216+108)=(540,1010)

最终的每个格子的中心坐标如下:

  1. (108, 578)
  2. (324, 578)
  3. (540, 578)
  4. (108, 794)
  5. (324, 794)
  6. (540, 794)
  7. (108, 1010)
  8. (324, 1010)
  9. (540, 1010)

这样就得到了九宫格所有格子的中心坐标。

el = driver.find_element(By.ID, "com.android.settings:id/lockPattern")
print(el.get_attribute("bounds"))
sleep(1)
# 创建一个ActionChains对象
actions = ActionChains(driver)
actions.w3c_actions.pointer_action.move_to_location(108, 578)
actions.w3c_actions.pointer_action.pointer_down()

actions.w3c_actions.pointer_action.move_to_location(324, 578)
actions.w3c_actions.pointer_action.move_to_location(540, 578)
actions.w3c_actions.pointer_action.move_to_location(324, 794)
actions.w3c_actions.pointer_action.move_to_location(324, 1010)
actions.w3c_actions.pointer_action.release()
actions.perform()

14.手机操作API

自动化测试可能会需要根据当前设备的屏幕分辨率来计算一些点击或者滑动的坐标。

print(driver.get_window_size())

输出:{'width': 720, 'height': 1280}

有些自动化的操作可能没有反应,但并不报错。此时我们就可以将操作过后的关键情况,截图留存。后期也可以根据图片发现问题。

# 截图到电脑
driver.get_screenshot_as_file('D://screen.png')

视频应用在使用流量看视频的时候,大部分都会提示用户正在是否继续播放。作为测试人员,我们可能需要用自动化的形式来判断是否有对应的提示。即,用流量的时候应该有提示,不用流量的时候应该没有提示。

# 获取网络
print(driver.network_connection)
# 修改手机网络
driver.set_network_connection(4)

表格

Value (Alias)DataWifiAirplane Mode
0 (None)000
1 (Airplane Mode)001
2 (Wifi only)010
4 (Data only)100
6 (All network on)110

模拟按“返回键”“home键” 等等操作,比如,很多应用有按两次返回键退出应用的功能,如果这个功能需要我们做自动化,那么一定会用到这个方法

# 发送手机键码 
driver.press_keycode(4)

码表参考:

KEYCODE_CALL拨号键5
KEYCODE_ENDCALL挂机键6
KEYCODE_HOME按键Home3
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

操作通知栏

# 打开手机通知栏
driver.open_notifications()

appium 官方并没有为我们提供关闭通知的 api,那么现实生活中怎么关闭,就怎样操作就行,比如,手指从下往上滑动,或者,按返回键 driver.press_keycode(4)。

练习:

1.使用代码判断是否安装无尽白板应用,如果没有这安装。

2.打开无尽白板并根据应用启动流程进入绘图页面。

3.绘制如下图形并保存到本地。

参考代码:1

if not driver.is_app_installed("driver"):
    driver.install_app("D://1.0.36/apk/无尽白板.apk")

参考代码:2

from time import sleep

from appium import webdriver
from appium.options.android import UiAutomator2Options
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By

capabilities = dict(
    platformName='Android',
    automationName='uiautomator2',
    deviceName='Android',
    appPackage='cn.readpad.whiteboard',
    appActivity='.MainActivity'
)
appium_server_url = 'http://localhost:4723'
driver = webdriver.Remote(appium_server_url, options=UiAutomator2Options().load_capabilities(capabilities))
driver.implicitly_wait(20)
driver.find_element(By.XPATH, "//*[@text='同意']").click()
els = driver.find_elements(By.ID, "cn.readpad.whiteboard:id/toolImageView")
els[3].click()
size = driver.get_window_size()
h = size["height"]
w = size["width"]

# 画长方形
actions = ActionChains(driver)
actions.w3c_actions.pointer_action.move_to_location(150, 150)
actions.w3c_actions.pointer_action.pointer_down()

actions.w3c_actions.pointer_action.move_to_location(w - 150, 150)
actions.w3c_actions.pointer_action.move_to_location(w - 150, h - 150)
actions.w3c_actions.pointer_action.move_to_location(150, h - 150)
actions.w3c_actions.pointer_action.move_to_location(150, 150)
actions.w3c_actions.pointer_action.release()
actions.perform()

# 画圆形

els[7].click()
actions = ActionChains(driver)
actions.w3c_actions.pointer_action.move_to_location(200, 200)
actions.w3c_actions.pointer_action.pointer_down()
actions.w3c_actions.pointer_action.move_to_location(500, 500)
actions.w3c_actions.pointer_action.release()
actions.perform()
# 保存图片到手机

driver.find_element(By.XPATH, "//*[@content-desc='保存']").click()
driver.get_screenshot_as_file("d://无尽白板.png")
sleep(20)
driver.quit()

15.若依app调试

1.打开若依官网下载RuoYi-Vue 前端分离版和RuoYi-App 移动端版。

2.使用 idea 打开相应后台项目、网页端项目。

3.使用 HBuilderX 打开app代码,浏览器调试无误后打包安装。

4.对若依app项目的基础功能进行自动化测试。

from time import sleep
from appium import webdriver
from appium.options.android import UiAutomator2Options
from appium.webdriver.common.appiumby import AppiumBy
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By

capabilities = dict(
    platformName='Android',
    automationName='uiautomator2',
    deviceName='Android',
    appPackage='uni.UNI25A9D80',
    appActivity='io.dcloud.PandoraEntryActivity'
)
appium_server_url = 'http://localhost:4723'
driver = webdriver.Remote(appium_server_url, options=UiAutomator2Options().load_capabilities(capabilities))
actions = ActionChains(driver)
driver.implicitly_wait(10)
eles = driver.find_elements(By.CLASS_NAME, 'android.widget.EditText')
eles[0].send_keys('admin')
eles[1].send_keys('admin123')
driver.find_element(By.XPATH, "//*[@index='6']").click()
driver.find_element(By.XPATH, "//*[@text='我的']").click()
driver.find_element(By.XPATH, "//*[@text='编辑资料']").click()
dl = driver.find_elements(By.CLASS_NAME, "android.widget.EditText")
list1 = ['陈坤鹏', '17798391364', '12341@163.com']
for i in range(3):
    dl[i].clear()
    dl[i].send_keys(list1[i])
driver.find_element(By.XPATH, "//*[@text='男']").click()
driver.find_element(By.XPATH, "//*[@text='提交  ']").click()
driver.tap([(31, 69)])
driver.find_element(By.XPATH, "//*[@text='应用设置']").click()
driver.find_element(By.XPATH, "//*[@text='退出登录']").click()
driver.find_element(By.XPATH, "//*[@text='确定']").click()
sleep(5)
driver.quit()

16.web app测试

使用 Appium 测试 Web 应用程序的步骤通常包括以下几个方面:

1.安装 Appium: 使用以下命令通过 npm 安装 Appium: npm install -g appium

2.安装 Appium 客户端: 根据你选择的编程语言安装相应的 Appium 客户端库(例如 Java、Python、JavaScript 等)。

3.配置浏览器驱动: 根据你的需求安装相应的浏览器(如 Chrome 或 Safari)和其对应的驱动(如 ChromeDriver)如果使用系统自带浏览器需根据报错提示下载对应版本的驱动。

from time import sleep

from appium import webdriver

from appium.options.android import UiAutomator2Options
from selenium.webdriver.common.by import By

capabilities = dict(
    platformName='Android',
    automationName='uiautomator2',
    deviceName='Android',
    appPackage='com.android.browser',
    appActivity='.BrowserActivity',
    chromedriverExecutable=r"D:\chromedriver.exe",
)
driver = webdriver.Remote('http://localhost:4723',
                          options=UiAutomator2Options().load_capabilities(capabilities))
driver.implicitly_wait(10)
# 点击输入网址后回车打开目标网址
driver.find_element(By.XPATH, "//android.widget.EditText[@resource-id='com.android.browser:id/url']").click()
driver.find_element(By.XPATH, "//android.widget.EditText[@resource-id='com.android.browser:id/url']").send_keys(
    "http://222.85.193.12:8808/#/")
driver.press_keycode(66)
contexts = driver.contexts
print("Available contexts:", contexts)
driver.switch_to.context("WEBVIEW_com.android.browser")
print(driver.title)
driver.find_element(By.XPATH, '/html/body/uni-app/uni-page/uni-page-head/div/div[2]/uni-input/div/form/input').send_keys("admin")
sleep(10)

driver.quit()

一般的 driver.switch_to.context("WEBVIEW_com.android.browser") 如果浏览器驱动未下载会报错,根据报错信息下载后配置chromedriverExecutable 属性即可。

An unknown server-side error occurred while processing the command.Original error: No Chromedriver found that can automate Chrome '92.0.4515'.You could also try to enable automated chromedrivers download as a possible workaround.
  1. 设置能力 (Capabilities):
    • platformName: 指定测试的平台,这里是 Android。
    • automationName: 指定自动化框架,这里使用uiautomator2
    • deviceName: 指定设备名称(可以是设备型号或模拟器名称)。
    • appPackage: 指定要启动的应用程序包名,这里是 Android 浏览器。
    • appActivity: 指定启动的应用程序活动。
    • chromedriverExecutable: 指定 Chrome 驱动程序的路径,以便与 Chrome 浏览器进行交互。
  2. 获取上下文:
    • 获取当前可用的所有上下文(通常包括原生应用和 WebView),并打印出来。
    • 使用press_keycode(66)模拟回车键,这样可以打开输入的网址。
    • 切换到特定的 WebView 上下文,以便与网页元素进行交互。
    • 使用 XPath 定位到网页上输入用户名的文本框,并发送文本“admin”。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值