APP自动化测试-8.移动端混合应用自动化测试

2023-11-18

APP自动化测试-8.移动端混合应用自动化测试



前言

Hybrid App,俗称混合应用,是介于 Web App 和 Native App 两者之间的一种 App 形式,Hybrid App 利用了 Web App 和 Native App 的优点,通过一个原生实现的 Native Container 展示 HTML5 的页面。更通俗的讲法可以归结为,在原生移动应用中嵌入了 Webview,然后通过该 Webview 来访问网页,Hybrid App 具有维护更新简单,用户体验优异以及较好的跨平台特性,是目前主流的移动应用开发模式


一、webview

1. webview简介

webview是android系统提供的能够显示网页的系统控件,Android4.4以下的版本,webview底层实现是使用webkit内核,Android4.4以上版本,采用chromium作为系统webview底层支持,API没有改变,支持HTML5,CSS3,javascript

webkit for webview chromium for webview 备注
HTML% 278 434 http://html5test.com/
远程调试 不支持 支持 Android4.4版本以上支持
内存占用 相差20M左右
WebAudio 不支持 支持 Android4.45.0以上支持
WebGL 不支持 支持 Android4.45.0以上支持
WebRTC 不支持 支持 Android4.45.0以上支持

2. webview判断

  • 断网查看:原生页面有缓存,网络断开后依然可以查看
  • 看加载条:webview页面打开时,上方会显示加载条
  • 看顶部是否有关闭按钮:一般webview页面左上角会显示关闭按钮
  • 下拉刷新查看页面是否刷新:
  • 下拉刷新是否显示网页提供方:webview页面下拉回现实网页提供方
  • 用工具查看:uiautomator查看页面的class属性,webview类的属性为:android.webkit.WebView

二、环境准备

  • PC端可以访问Google
  • PC端准备app对应的chromedriver
  • 移动端被测应用需要打开webview开关

chromedriver和mapping.json的资源整理了一下,打包上传了,下载地址,包含所有版本的chromedriver和版本对照的json文件,下载完成后在脚本中直接使用:chromedriverExecutableDir和chromedriverChromeMappingFile参数进行引用即可

三、脚本编写

由于大多数应用商店的应用webview的开关的都是关闭的,在这里以appium官方提供的demo为例,进行简单的脚本示例。

appium-demo下载地址

1. 启动被测应用

配置测试设备和驱动,启动appium-demo

desired_caps = {
            "platformName": "android",
            "appium:deviceName": "b1f37e8e",
            "appium:appPackage": "io.appium.android.apis",
            "appium:appActivity": ".ApiDemos",
            "chromedriverExecutableDir": "/Users/test/tools/chromedriverdir",
            "chromedriverChromeMappingFile": "/Users/test/PycharmProjects/test_appium/testcase/mapping.json"
        }

self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)

2. 进入webview页面

self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, 'Views').click()
        webview = "WebView"
        self.driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, f'new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().text("{webview}").instance(0));').click()

3. 原生页面与webview页面切换

进入webview页面后直接去定位操作元素是无法成功的,这时候需要由原生页面切换至webview页面,使用driver的context方法

print(self.driver.contexts)
        # 切换上下文,由原生切换至webview
        self.driver.switch_to.context(self.driver.contexts[-1])
        self.driver.find_element(By.XPATH, '//*[@id="i_am_a_textbox"]').send_keys("this is a test message")

完整代码如下:

from time import sleep

import pytest
from appium import webdriver
from appium.webdriver.common.appiumby import AppiumBy
from selenium.webdriver.common.by import By


class TestHybrid:

    def setup(self):
        desired_caps = {
            "platformName": "android",
            "appium:deviceName": "b1f37e8e",
            "appium:appPackage": "io.appium.android.apis",
            "appium:appActivity": ".ApiDemos",
            "chromedriverExecutableDir": "/Users/gaozeyu/tools/chromedriverdir",
            "chromedriverChromeMappingFile": "/Users/gaozeyu/PycharmProjects/test_appium/testcase/mapping.json"
        }

        self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)

        # 设置隐式等待
        self.driver.implicitly_wait(10)

    def teardown(self):
        self.driver.quit()

    def test_hybrid(self):
        sleep(3)
        self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, 'Views').click()
        webview = "WebView"
        self.driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, f'new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().text("{webview}").instance(0));').click()

        print(self.driver.contexts)
        # 切换上下文,由原生切换至webview
        self.driver.switch_to.context(self.driver.contexts[-1])
        self.driver.find_element(By.XPATH, '//*[@id="i_am_a_textbox"]').send_keys("this is a test message")

        # 窗口切换
        print(self.driver.window_handles)
        self.driver.find_element(By.XPATH, '//*[@id="i am a link"]').click()
        print(self.driver.window_handles)

        sleep(3)

        if __name__ == 'main':
            pytest.main()

四、踩坑小结

  1. 应用启动后直接闪退(之前是正常的):重启手机
  2. 连接不上手机:尝试关闭chrome浏览器的调试窗口后重试
  3. 版本不匹配:建议直接下载所有版本,配置mapping文件,后续项目中可以直接使用

总结

  1. 应用的chrome版本一定要与chromedriver匹配
  2. 原生页面和webview页面混合时注意上下文的切换
  3. webview可能由多个页面,需要使用switch_to.window()进行页面的切换
  4. webview的开关需要开发开启,否则无法操作
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

APP自动化测试-8.移动端混合应用自动化测试 的相关文章

  • UpdatePanel 启动脚本未执行

    我正在编写一个在 SharePoint 网站中使用的 ASP NET Web 部件 并尝试使用 UpdatePanel 来呈现查询结果 我想使用 JQuery 插件来修改从异步回发返回的表 但我无法让启动脚本在异步更新上执行 我发现这个帖子
  • Google 地图 Javascript v3 折线点击事件

    我正在尝试显示一张地图 其中有多条路线布置为折线 单击多段线时 我想显示特定于该线的数据 将数据与线关联不是问题 但无论单击哪条线 显示的数据都会与最近绘制的线关联 就好像每条新折线都会覆盖最后一条线一样 我有一个数据库 其中包含 gpx
  • AsyncTask:DoInBackground(String ...)与DoInBackground(Params ...)冲突?

    当尝试使用时Async task要执行 HTTP post 我得到以下信息 ASyncTask DoInBackground String clashes with DoInBackground Params in Android os A
  • 如何为 App Store 添加关联域? - App Store Connect 的 app-ads.txt 文件

    如您所知 Admob 向发布商发送了有关 app ads txt 文件的电子邮件 Admob 在电子邮件中表示 因此 我们邀请您仔细检查您的 app ads txt 文件 如果 您已经在发布日期之前发布了一份 文件 应发布在列出的网站的根目
  • logcat 信息出现在 Android Studio 的“运行”选项卡中

    我的 android studio 运行选项卡很简单 然后它变得更难并给我更多信息 例如 logcat 中的信息 如何禁用或删除第二张图片中出现的更多信息并返回到第一张图片中的第一个外观 我只需要正在运行的 flutter 应用程序的日志输
  • 如何处理 setTimeout() 的多个实例?

    阻止创建 setTimeout 函数的多个实例 在 JavaScript 中 的最推荐 最佳方法是什么 一个例子 伪代码 function mouseClick moveDiv div 0001 mouseX mouseY function
  • IntelliJ 12 中的 Android Hello World - 找不到 android.app.Activity 类

    请看下文 我感觉 SDK 配置不正确 但我不知道如何解决 我尝试用谷歌搜索答案 但没有人遇到这个确切的问题 难道是我的Java版本不对 这两个 SDK 似乎可能相互冲突 我通过以下方式制作了这个项目 创建新项目 Android gt 应用模
  • Ajax 函数在重定向后不保存滚动位置

    正如标题所述 我编写了一个 ajax 函数 该函数应该滚动到用户在重定向之前所在的位置 我写了一个alert对于测试场景 它确实触发了 但滚动不断回到顶部 我在这里做错了什么 JavaScript ajax type GET url Adm
  • 如何使用 Node.js 解析 JSON? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我应该如何使用 Node js 解析 JSON 是否有一些模块可以安全地验证和解析 JSON 你可以简单地使用JSON parse h
  • 如何使 4.X Typescript 项目与旧版本的 Typescript(如 3.X)兼容?

    如何使基于 TS 4 X 构建的软件包与 3 X 兼容 例如 如果我有较新的版本 则使用新功能 否则使用any or unknown或旧版本支持的任何内容 有没有可能使用指令 https www typescriptlang org doc
  • 如何使用 API 中的数据填充选择的下拉元素 - ReactJS

    我对 React 还很陌生 我正在从 API 获取数据 当我检查控制台日志时可以看到数据 但是我不知道如何使用 map 创建一个新数组 然后选项元素可以使用该数组来显示货币代码 目前它填充下拉列表 但选项元素全部为空 结果显示为 NaN 下
  • 将字节数组保存为 Android 设备文件夹中的 jpg 文件

    我正在尝试将图像保存在 Android 设备的文件夹中 我使用的代码如下 var newFolder AndroidEnvironment GetExternalStoragePublicDirectory AndroidEnvironme
  • 协程中未捕获异常

    我似乎无法在协程中完成错误处理 我读了很多文章并且异常处理文档 https kotlinlang org docs reference coroutines exception handling html exception propaga
  • 如何将 SD 卡图像添加到 coverflow?

    Here is my coverflow with drawables This is my Image Adapter Code The Constant IMAGE RESOURCE IDS private static final L
  • 如何以编程方式设置带有密码的屏幕锁定?

    有没有人可以帮我设置密码以锁定屏幕 谢谢 在您的应用程序中使用此代码 它对我有用 DevicePolicyManager devicePolicyManager DevicePolicyManager getSystemService Co
  • Android:适合SystemWindows和换行符干扰bottomSheets

    我发现如果父布局包含android fitsSystemWindows true 当发生与视图相关的操作时 它会干扰我的 BottomSheets 定位 具体来说 我遇到的是 文本视图中的换行符将触发底页偏移系统 通知栏的高度 换行符 fi
  • 检测 html 选择框上的编程更改

    有没有办法让 HTML 选择元素在每次以编程方式更改其选择时调用函数 当使用 JavaScript 修改选择框中的当前选择时 IE 和 FF 都不会触发 onchange 此外 更改选择的 js 函数是框架的一部分 因此我无法更改它以在结束
  • javascript 闭包和对象引用

    我的情况有点晦涩难懂 主要是因为我认为我已经掌握了闭包 所以基本上我想要的是将集合重置为默认值 假设我有一个集合 它具有带有对象参数数组的构造函数 var c new collection x y z 然后集合定期更新 因为我没有保留数组的
  • javascript从字符串创建不区分大小写的正则表达式

    我试图通过以不区分大小写的方式将输入与正则表达式匹配来进行验证 正则表达式作为对象上的字符串从服务中下来 我可能会得到类似的东西 regex ane 我可以执行以下操作 var rx new RegExp object regex The
  • 尽管 getBoundingClientRect() 是假的,但如何将事件坐标转换为 SVG 坐标?

    我正在尝试根据鼠标的位置在 SVG 元素上动态绘制内容 不幸的是 我很难将 mousemove 事件中的鼠标坐标转换为 SVG 元素的坐标空间 这是我一直在测试的一个有缺陷的函数 CylinderDemo prototype handleM

随机推荐

  • 使用CURL上传图片至远程服务器(PHP >5.5)

    开头引入 use CURLFile curl文件上传 接收并上传 if FILES data file new CURLFile FILES file1 tmp name image jpeg FILES file1 name 文件流 fi
  • MVP和MVC的区别

    前提回顾 MVC架构 MVC就是Model View Controller 它们的作用是 它们之间的关系如下图所示 View传送指令到Controller Controller完成业务逻辑后 改变Model的状态 Model将新的数据发送到
  • RPC 开发系列一:RPC 基本介绍

    一 什么是 RPC RPC 的全称是 Remote Procedure Call 即远程过程调用 功能 屏蔽远程调用跟本地调用的区别 让我们感觉就是调用项目内的方法 隐藏底层网络通信的复杂性 让我们更专注于业务逻辑 二 RPC 通信流程 发
  • sourceforge文件下载过慢之原始解决方法

    近日 从sourceforge下载文件超线慢 从下午一直下载到网上11点多 居然下不完39MB的资料 百度一下方法有很多 却一个都没成功 比如 http sourceforge mirrorservice org 更是没用 部份有用 因为不
  • __cdecl __stdcall __fastcall区别

    一 三者区别一览表 stdcall cdecl fastcall 参数传递方式 右 gt 左 压栈 右 gt 左 压栈 左边开始的两个不大于4字节 DWORD 的参数分别放在ECX和EDX寄存器 其余的参数仍旧自右向左压栈传送 清理栈方 被
  • 【逆波兰表达式求值】

    逆波兰表达式求值 给你一个字符串数组 tokens 表示一个根据 逆波兰表示法 表示的算术表达式 请你计算该表达式 返回一个表示表达式值的整数 注意 有效的算符为 和 每个操作数 运算对象 都可以是一个整数或者另一个表达式 两个整数之间的除
  • 【SpringBoot框架篇】31.基于分布式锁或xxx-job实现分布式任务调度

    文章目录 1 简介 2 分布式锁实现 2 1 引用依赖 2 2 定义分布式锁注解 2 3 配置切入点和获取锁释放锁逻辑 2 4 测试任务 3 使用分布式任务调度平台xxx job 3 1 下载源码并运行项目 3 2 springBoot项目
  • 微信小程序之授权登录篇

    之前微信授权登录时是直接可以通过getUserInfo接口 弹出授权弹窗 由于微信官方修改了 getUserInfo 接口 所以现在无法实现一进入微信小程序就弹出授权窗口 只能通过 button 去触发 微信的官方解释如下 为优化用户体验
  • React 初识之Umi项目搭建实战

    一 创建项目 创建之前需要安装 Node js 和 npm yarn 这俩个环境 在WebStorm里面创建一个项目 输入命令 yarn create umi 弹出选项 这里我们选择第二项APP 选择是否使用typescript 这里选no
  • JavaScript常用事件讲解

    声明 本人的所有博客皆为个人笔记 作为个人知识索引使用 因此在叙述上存在逻辑不通顺 跨度大等问题 希望理解 分享出来仅供大家学习翻阅 若有错误希望指出 感谢 事件流 事件流描述的是从页面接收事件的顺序 事件冒泡 事件开始由最具体的元素接收
  • c语言统计各类字符个数

    输入十个字符 统计其中英文字母 空格或回车 数字字符和其他字符的个数 7 43 统计字符分数 15 全屏浏览题目 切换布局 作者 颜晖 单位 浙大城市学院 本题要求编写程序 输入10个字符 统计其中英文字母 空格或回车 数字字符和其他字符的
  • mysql的索引 优化 前导列

    组合索引之 前导列 1 对于where子句中出现的列要想索引生效 会有一些限制 这就和前导列有关 2 所谓前导列 就是在创建复合索引语句的第一列或者连续的多列 比如通过 CREATE INDEX comp ind ON table1 x y
  • 第一个Node程序,Node入门

    第一个Node程序 在前面的所有内容中 我们编写的JavaScript代码都是在浏览器中运行的 因此 我们可以直接在浏览器中敲代码 然后直接运行 从本章开始 我们编写的JavaScript代码将不能在浏览器环境中执行了 而是在Node环境中
  • 位运算及其应用详解

    http blog chinaunix net uid 21411227 id 1826986 html 一 逻辑运算符 1 位与运算 1 运算规则 位与运算的实质是将参与运算的两个数据 按对应的二进制数逐位进行逻辑与运算 例如 int型常
  • 低代码发展史及现状

    做开发 真的一定需要写代码吗 这次真的轮到程序员革自己的命了 业内很多人都这样感叹 2019年见证了低代码 零代码市场的首次爆发 种种迹象似乎在提醒着我们 一个新的 风口 正在形成 Do developers really need to
  • NeRF项目LLFF 解决新场景pose生成的问题

    最近一直在做NeRF相关的项目 其中LLFF前向数据集 是NeRF常用数据集 本文讲下怎么对NeRF数据进行处理 几个重要的链接地址 github llff GitHub Fyusion LLFF Code release for Loca
  • upload-labs-2

    登陆第二关 查看代码 发现是文件类验证 抓包 修改为允许发现成功 放包
  • solr的三种提交方式

    三种solr提交索引的方式 1 commit 通过api直接commit 这样性能比较差 在我测试下 平均每条commit600ms HttpSolrServer solrServer new HttpSolrServer http loc
  • Docker安装mysql

    Docker安装mysql 查看镜像 下载镜像 启动容器 进入mysql数据库 查看镜像 docker search mysql 5 7 下载镜像 docker pull mysql 5 7 启动容器 可以直接执行这一步 一步到位 dock
  • APP自动化测试-8.移动端混合应用自动化测试

    APP自动化测试 8 移动端混合应用自动化测试 文章目录 APP自动化测试 8 移动端混合应用自动化测试 前言 一 webview 1 webview简介 2 webview判断 二 环境准备 三 脚本编写 1 启动被测应用 2 进入web