首页 > 其他分享 >Android 平台使用 appium 自动化操作 webView 的经验

Android 平台使用 appium 自动化操作 webView 的经验

时间:2023-04-13 22:59:12浏览次数:45  
标签:appium elements 元素 driver element webView 选择器 webview Android

更多内容见草稿: https://wkmcyz.notion.site/Appium-H5-c9c287855ef74ef0ae5d8f819da3923f

本文章主要介绍在 Android 平台上使用 appium 对 app 内的 webView 进行自动化操作上的一些知识,包括一些配置和可以进行的操作等。
需要读者:

  • 熟悉如何使用 appium 进行 native app 的自动化操作

自动化操作 App 内的 webview 的前置要求

注意: 这是针对某个 app 内的 webview 进行自动化操作;而不是使用 chrome 等浏览器应用里的 webview 进行操作。

  1. 本地有和手机系统的 webview 版本一致的 chromedriver 。
  2. app 的 webView 已经开启了 debug 模式。

这两者的具体操作方法为:

  • 如何获取 chromedriver?
  1. 命令行里执行 adb shell dumpsys package com.google.android.webview | grep versionName 可以获取当前设备的 webview 版本(有些时候会获得多个值,可以每个版本都试一下)。 或者在 “开发者选项” 里也可以查看到系统的 webView 版本。
  2. https://registry.npmmirror.com/binary.html?path=chromedriver/ 这个地址下载对应版本的 chromedriver。
  • 如何开启 app 的 webview 的 debug 模式?
    修改 app 代码实现,详情请搜索 setWebContentsDebuggingEnabled

在 appium 端,增加 desired_capabilities 信息:

# python
options.chromedriver_executable = '/tmp/chromedriver'
options.chrome_options = {
    # 待测试的 app package
    "androidPackage": YOUR_APP_PACKAGE,
}
# 省略其他的 driver capabilities 信息。
# 打开 app 的 webView 页面后,查看当前的 context。
print(driver.contexts)
# 切换到 webView 的 context
driver.switch_to.context("WEBVIEW_XXXX")

appium driver 可以执行的功能。

从 appium 调用 js

def run_js(driver,js_code):
    driver.execute_script(js_code)

run_js(driver, "console.log('123')")

获取 js 的 console 日志

logs = driver.get_log('browser')
for l in logs:
        print("log:", l)
# log: {'level': 'INFO', 'message': 'x.js 4:236286 "123"', 'source': 'console-api', 'timestamp': 1681386146296}
# log: {'level': 'INFO', 'message': 'x.js 4:236286 "123"', 'source': 'console-api', 'timestamp': 1681386146355}

获取页面信息

driver.page_source

寻找元素

  1. 使用 xpath 寻找

略过。

  1. 使用 css_selector 寻找。

如何使用 CSS Selector 获取元素

要使用 CSS 选择器获取元素,首先确保您处于 WebView 上下文,因为 CSS 选择器仅在 WebView 中可用。然后,使用 **`find_element_by_css_selector()`** 或 **`find_elements_by_css_selector()`** 方法查找元素。以下是一些使用 CSS 选择器查找元素的示例:

1. **通过 ID 获取元素**:
    
    ```
    pythonCopy code
    element = driver.find_element_by_css_selector("#element_id")
    
    ```
    
2. **通过类名获取元素**:
    
    ```
    pythonCopy code
    elements = driver.find_elements_by_css_selector(".element_class")
    
    ```
    
3. **通过标签名获取元素**:
    
    ```
    pythonCopy code
    elements = driver.find_elements_by_css_selector("tag_name")
    
    ```
    
4. **通过属性获取元素**:
    
    ```
    pythonCopy code
    element = driver.find_element_by_css_selector("tag_name[attribute='value']")
    
    ```
    
5. **通过子元素获取元素**:
    
    ```
    pythonCopy code
    element = driver.find_element_by_css_selector("parent_tag > child_tag")
    
    ```
    
6. **通过兄弟元素获取元素**:
    
    ```
    pythonCopy code
    element = driver.find_element_by_css_selector("sibling_tag1 ~ sibling_tag2")
    
    ```
    
这些仅是使用 CSS 选择器查找元素的一些基本示例。CSS 选择器提供了许多其他方法和组合,可以更具体地选择元素。在使用 CSS 选择器时,请确保您熟悉 CSS 选择器语法。

如何使用 CSS Selector 获取元素

通过属性获取元素是指使用 CSS 选择器根据元素的属性(如 idclassname 等)来查找页面上的元素。以下是一些基于属性的 CSS 选择器示例:

  1. 通过特定属性获取元素

    查找具有特定属性的元素,无论属性值是什么。例如,查找具有 data-custom-attribute 属性的所有元素:

    elements = driver.find_elements_by_css_selector("[data-custom-attribute]")
    
  2. 通过属性值获取元素

    查找具有特定属性值的元素。例如,查找 name 属性值为 username 的所有元素:

    elements = driver.find_elements_by_css_selector("[name='username']")
    
  3. 通过部分属性值获取元素

    查找属性值包含指定子串的元素。例如,查找 class 属性值包含 container 的所有元素:

    elements = driver.find_elements_by_css_selector("[class*='container']")
    
  4. 通过属性值前缀获取元素

    查找属性值以特定前缀开头的元素。例如,查找 href 属性值以 https:// 开头的所有链接:

    elements = driver.find_elements_by_css_selector("a[href^='https://']")
    
  5. 通过属性值后缀获取元素

    查找属性值以特定后缀结尾的元素。例如,查找 src 属性值以 .jpg 结尾的所有图片:

    elements = driver.find_elements_by_css_selector("img[src$='.jpg']")
    

这些示例展示了如何使用不同的属性选择器来查找元素。可以组合这些选择器以满足更复杂的选择需求。请注意,这些选择器仅适用于 WebView 上下文,因为它们是基于 CSS 选择器的。在原生应用上下文中,请使用其他定位策略。

获取元素位置

  • 通过上面的方法获取到目标元素以后,可以使用 element.rect 获取到其在 webView 里的宽高和位置坐标。
    webView 使用逻辑像素,跟物理像素有倍数差距。int(driver.execute_script("return window.devicePixelRatio;"))

    
    def get_device_pixel_ratio(driver) -> int:
        device_pixel_ratio = int(driver.execute_script("return window.devicePixelRatio;"))
        return device_pixel_ratio
    
    
  • webView 是可滑动的,获得的 x/y 需要考虑当前的滑动值。

  • 获取 element 在屏幕上的坐标 (没考虑 statusbar)

    def get_device_pixel_ratio(driver) -> float:
        device_pixel_ratio = float(driver.execute_script("return window.devicePixelRatio;"))
        return device_pixel_ratio
    
    def get_scroll(driver) -> Tuple[float, float]:
        scroll_x = float(driver.execute_script("return window.pageXOffset;"))
        scroll_y = float(driver.execute_script("return window.pageYOffset;"))
        return scroll_x, scroll_y
    
    def get_element_asb_location(driver, element) -> Tuple[float, float, float, float]:
        webview_elment_rect = element.rect
        webview_elment_height = webview_elment_rect['height']
        webview_elment_width = webview_elment_rect['width']
        webview_elment_x = webview_elment_rect['x']
        webview_elment_y = webview_elment_rect['y']
        print(webview_elment_rect)
        device_pixel_ratio = get_device_pixel_ratio(driver)
        scroll_x, scroll_y = get_scroll(driver)
        print(scroll_x, scroll_y)
        return (
            webview_elment_height * device_pixel_ratio,
            webview_elment_width * device_pixel_ratio,
            (webview_elment_x - scroll_x) * device_pixel_ratio,
            (webview_elment_y - scroll_y) * device_pixel_ratio,
        )
    

标签:appium,elements,元素,driver,element,webView,选择器,webview,Android
From: https://www.cnblogs.com/wkmcyz/p/17316848.html

相关文章

  • android: minSdkVersion、targetSdkVersion、CompileSdkVersion三个api版本号的区别
    一,minSdkVersion:   app可以安装的最低的api版本:   1,安装:googleplay和应用市场会根据用户的api版本,           判断用户是否可以看到你的app    2, 运行:在minSdkVersion指定版本的api上运行时,           ......
  • android S 上 安装apk出现android.os.FileUriExposedException
    报错:android.os.FileUriExposedException:file:///data/user/0/com.example.overlay.exposedbeyondappthroughIntent.getData()原因:andorid7.0系统以后,引入“私有目录被限制访问”,“StrictModeAPI政策”导致的问题。解决办法很简单。就是用新的方式获取uri。”St......
  • adb命令获取android app FPS 执行命令后只出现一行16666666的解决方案
    一、问题描述使用命令command='adbshelldumpsysSurfaceFlinger--latency{}/{}#0'.format(package_name,activity)获取androidapp的fps数据,执行命令后街股票打印如下:  二、问题分析1、刚开始以为是命令里面的SurfaceView写的有问题,执行命令adbshelldumpsys......
  • Android性能优化之APK瘦身
    结构分析首先上传一张瘦身前通过Analyzeapp分析出来的图片(打开方式:AndroidStudio下——>Build——>Analyzeapp):imageAPK包结构如下:lib/:包含特定于处理器软件层的编译代码。该目录包含了每种平台的子目录,像armeabi,armeabi-v7a,arm64-v8a,x86,x86_64,和mips。大多数情况......
  • Android开发startActivityForResult()弃用,推荐使用registerForActivityResult()方法
    SecondActivity中publicclassSecondActivityextendsAppCompatActivity{privatestaticfinalStringTAG="SecondActivity";@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);......
  • 微信小程序嵌套的webview页面实现导航,可跳转高德百度等app
    需求:微信小程序中使用webview嵌套了h5页面,h5页面中有经纬度,需要实现唤醒高德app。实现思路:此处h5未配置wxSDK,无法直接使用openLocation,所以将经纬度传给小程序,map页面为跳转中间页,再实现打开地图页面。h5://高德地图导航constaMapNavigate=(address,lng,lat)=>{......
  • Android技术分享 | 一行代码实现屏幕、声音采集
    之前发布过一行代码实现安卓屏幕采集编码,并介绍了如何屏幕采集编码并进行了封装,简单的调用即可实现MediaProjection权限申请、H264硬编码、错误处理等功能。本文将介绍新增的功能,还是只需一行代码即可实现屏幕、声音采集。一行代码实现屏幕采集编码之前的文章,我们已经介绍过如何......
  • android AsyncTask
    在Android中每一个应用都拥有自己的独立进程,而一个进程可以拥有多个线程,在这些线程中有一个线程叫做MainThread(也叫UIThread).它负责显示、更新UI,与用户交互.其他的线程叫做WorkerThread(也叫工作线程),由于在主线程中做耗时的操作会阻塞主线程,影响UI更新,会让用户感觉到应......
  • 查看xxx.apk文件的AndroidManifest.xml操作步骤:
    查看xxx.apk文件的AndroidManifest.xml操作步骤: 1.使用7.zip打开xxx.apk文件,且将该文件夹中的AndroidManifest.xml文件复制出来。 2、AndroidManifest.xml文件复制到AXMLPrinter2文件夹中。 3、在AXMLPrinter2文件夹输入cmd进入命令行模式。 4、输入java-jarAXMLPrinter2.jarAn......
  • android: 平台版本对应api及占比统计(android studio 2022.1.1)
    一,查看平台版本对应的api官方文档地址:https://developer.android.google.cn/guide/topics/manifest/uses-sdk-element.html?utm_campaign=adp_series_sdkversion_010616&utm_source=medium&utm_medium=blog&hl=zh-cn#ApiLevels如图: 二,查看各版本的支持比率:启动androi......