Appium + mitmProxy 实现APP接口稳定性测试

随着 App 用户量的不断增长,任何小的问题都可能放大成严重的线上事故,为了避免对App造成损害的任何可能性,我们必须从各个方面去思考 App 的稳定性建设,尽可能减少任何潜在的威胁。

1.背景介绍

为了保障 App 的稳定性,我们现在有 XMoney 智能遍历测试(崩溃、界面错乱、加载异常等)、UI 自动化(崩溃和业务逻辑验证)、Top1000 小程序遍历(崩溃和业务逻辑报错)、接口稳定性建设(崩溃和业务逻辑验证)。 今天要给大家介绍的是接口稳定性建设,就是在后端返回数据如果不可靠的情况下,App 是否依然可以稳定运行。

2.实现思路

方案一

Mock有专门的Mock平台, 崩溃有专门的崩溃监控平台, 我们只需要把Mock数据下发到手机,如果有崩溃,会被崩溃平台收集到,崩溃会由值班同学分发给研发。

  1. 将接口代理到Mock平台,Mock平台根据response 生成批量的Mock数据
  2. 通过Appium调用App到制定页面, 触发对应请求,请求到了Mock平台后,Mock平台随机下发Mock数据
  3. 重复打开指定页面, 直到遍历完Mock数据
  4. 崩溃平台进行崩溃分发(人工)

优点:

短时间内可以覆盖大量的mock数据。

缺点:

mock数据不可控。

方案二

方案一有太多的随机性,为了让下发的数据和下发数据后的结果能够对应, 我们为了控制下发的数据, 我们在方案一的基础上自建Mock server, 通过Appium脚本和Mock server的交互,控制下发数据。

经调研,Mock server 比较大众的方案就是采用[mitmproxy](https://github.com/mitmproxy/mitmproxy), [mitmproxy](https://github.com/mitmproxy/mitmproxy)可实现 python 脚本的注入, 通过 python 脚本可以拦截请求的 request 和 response 数据,然后篡改数据后返回。因为 mitmproxy 是一个shell工具, 无法直接和python脚本交互, 所以python脚本和mitproxy的交互方式采用的是.ini的形式,互相读取 .ini 文件中的内容来实现数据交互。

优点:

mock数据可控制,可以校验预期结果。

缺点:

需要准备mock数据, mock数据要经常维护。

2种方案我们都有应用,方案一较为简单,在集成测试阶段执行,我们不再展开介绍。 方案二稍微麻烦一些,回归测试阶段执行。以下将详细介绍下方案二如何实现。

3.代码设计

方案流程

代码示例

测试Case

通过Mock更新数据,测试小程序升级的逻辑 (因涉及代码较多,大家可通过完整系统查看)

测试小程序的同步升级和异步升级逻辑, 修改测试配置后,mitmproxy会监控对应的接口请求, 发现存在要修改数据的请求,则进行response修改后返回给手机端。 手机端验证是否升级成功。

步骤:

  1. 修改测试配置(通过ini文件和mitmproxy实现联动, mitmproxy会在每次触发接口请求时检测当前的测试配置文件)

  2. 打开手机app

  3. 打开某个小程序

  4. 验证是否升级成功 (示例为把官方小程序Demo升级成为携程小程序)

    """ @File : test_update.py @Author : YangTongGang @Desc : 小程序升级(同步更新、异步更新) """

    class TestUpdate(BaseTestCases): """检测小程序同步更新、异步更新 已适配(iOS & Android) """ def setUp(self) -> None: # super(TestUpdate, self).setUp() self.business.del_sf_app('智能小程序') if self.is_android: self.business.del_sf_mine_app('智能小程序')

    def __update_action(self, is_sync=True):# 把CTS升级成携程, 并修改max age = 0# 控制mitmproxy进行不同的测试if is_sync:test_type = TestType.TestMaxAgeZeroelse:test_type = TestType.TestSaveResponseself.changeTestType(test_type)protocol = CaseManager.official_demo_case().protocolself.business.open_swan(protocol)if is_sync:test_type = TestType.TestSyncUpdateelse:test_type = TestType.TestAsyncUpdateself.changeTestType(test_type)def test_max_age_force_update(self):"""测试小程序同步更新"""self.__update_action()self.business.open_app()protocol = CaseManager.official_demo_case().protocolif self.business.open_swan(protocol):self.assert_validate('汽车票')
    Mitmproxy 启动

通过shell脚本启动mitmproxy并加载 http_handle.py文件,加载的python文件通过重写response或者request来达到监控每次请求的request和response的能力。

每次收到测试任务时,测试任务都会有相应的配置, 如果发现需要启动代理服务,则会自动调用如下脚本,启动代理, 然后手动配置测试机代理到服务地址,或者把任务打到固定的测试机上。

#!/usr/bin/env bash
: '
@File   : start_ui_mock.sh
@Author : YangTongGang
@Desc   : 启动UI Mock服务
'script_file=/CaseTester/HTTPRouter/http_router.pypath=$0
current_path=${path%/*}
current_path=${current_path%/*}
# 启动mock 数据服务
file=/SHELL/start_mock.sh
file_path=${current_path}${file}
chmod +x "${file_path}"
sh "${file_path}" ${script_file}#!/usr/bin/env bash
: '
@File   : start_mock.sh
@Author : YangTongGang
@Desc   : 启动接口Mock服务
'path=$0
file_path=$1
current_path=${path%/*}
current_path=${current_path%/*}
file_path=${current_path}'/..'${file_path}
echo "${file_path}"local_ip=$(ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d "addr:"|head -n 1)
echo '=========== 代理服务地址 ============'
echo 'Script:' "${file_path##*/}"
echo ''
echo "${local_ip}":8088
echo ''
echo '==================================='# mitmdump -s "${file_path}" -p 8088  --flow-detail 0
status=$(mitmdump -s ${file_path} -p 8088  --flow-detail 0)
if [$? == 0]
thenexit 0
fi

监控response

注册对应的接口处理模块,遇到对应的接口时执行对应的测试。

"""
@File   : http_router.py
@Author : YangTongGang
@Desc   : 请求中转站
"""# 注册handle
HANDLES = [# Core更新请求UpdateCoreHandle,# APS拉包请求PkgAPSHandle,# PMS拉包请求PkgPMSHandle,# Update接口UpdateHandle,# 我的页面, 下拉二楼的静默更新个数GetPkgListHandle
]def response(flow):"""接口response"""url = flow.request.urlpath = urlparse.urlsplit(url)['path']proxy_mock_urls = []for handle in HANDLES:proxy_mock_urls.append(handle.identifier)test_type = get_proxy_test_type()if test_type == TestType.TestNone:returnif path not in proxy_mock_urls:returnresponse_dic = json.loads(flow.response.content)for handle in HANDLES:if handle.identifier in path:handler = handle(response_dic, test_type)response_dic = handler.package_dicflow.response.content = bytes(json.dumps(response_dic), encoding='utf8')return

4.机房设计简介 

为了方便理解整个业务设计,顺便把我们的机房设计也给大家简单介绍一下。任务执行一般都是通过流水线派发到指定机房的随机空闲手机,测试完成后直接返回测试报告,测试执行人无需关心中间过程,也无需维护各种脚本。脚本都在机房维护, 避免在本地Appium部署困难, 脚本更新不及时等问题。

5.结语 

因为实际使用过程中依然需要大量人工介入,收益较小,所以执行频率不高,且该方案时间略微久远,所以在此只给大家抛砖引玉,开拓下思路之用,后续如有需要可以作为一种备选方案。

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你! 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/709610.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Docker】前端基于dockerfiel构建镜像部署,实现在容器启动时传递环境变量, 请求不同服务地址

前端部署采用 docker 的方式, 实现在容器启动时传递环境变量, 请求不同服务地址 实现思路: 定义.env.xxx 文件(环境变量赋值),在compose.yml中引入.env.xxx 文件,环境变量通过nginx的sub_filte…

算法基础(三)(模拟)

1.模拟算法介绍: 模拟算法通过模拟实际情况来解决问题,一般容易理解但是实现起来比较复杂,有很多需要注意的细节,或者是一些所谓很“麻烦”的东西。模拟题一般不涉及太难的算法,一般就是由较多的简单但是不好处理的部…

redis启动错误

错误: Creating Server TCP listening socket 127.0.0.1:6379: bind: No error redis-server.exe redis.windows.conf redis-cli.exe shutdown auth "yourpassword"

深基杨辉三角

题目描述 给出 n(n≤20)&#xff0c;输出杨辉三角的前 n 行。 如果你不知道什么是杨辉三角&#xff0c;可以观察样例找找规律。 输入格式 无 输出格式 无 输入输出样例 输入 #1 6 输出 #1 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1 解 #include<iostream&g…

深基蛇形方阵

题目描述 给出一个不大于 9 的正整数 n&#xff0c;输出 nn 的蛇形方阵。 从左上角填上 1 开始&#xff0c;顺时针方向依次填入数字&#xff0c;如同样例所示。注意每个数字有都会占用 3 个字符&#xff0c;前面使用空格补齐。 输入格式 输入一个正整数 nn&#xff0c;含义…

9 easy 28. 找出字符串中第一个匹配项的下标

暴力法&#xff1a; //给你两个字符串 haystack 和 needle &#xff0c;请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标&#xff08;下标从 0 开始&#xff09;。 //如果 needle 不是 haystack 的一部分&#xff0c;则返回 -1 。 // // // // 示例 1&…

TypeScript04:其他常用类型

一、联合类型 联合类型&#xff1a;多种类型任选其一&#xff0c;配合类型保护进行判断。 类型保护&#xff1a;当对某个变量进行类型判断之后&#xff0c;在判断的语句块中便可以确定它的 确切类型&#xff0c; typeof 可以触发基本类型的类型保护。 let name:string | und…

harbor配置目录被误删后救援

我司微服务产品的业务镜像&#xff0c;在客户现场上云安全检测中发现需要打补丁&#xff1b;放在角落、时不常用一次的harbor镜像仓库需要用到了&#xff1a;将加固后的基础镜像上传以备份&#xff0c;方便其他同学拉取使用。 然鹅&#xff0c;启动后harbor-db频繁重启 harbo…

c# string.Empty与“ “

背景&#xff1a; 在项目中加了几行代码&#xff0c;结果程序就莫名奇妙崩掉了。初步判断是有个 仔细分析了一下&#xff0c;添加的代码&#xff0c;用到 string.Empty来清空原来string变量中的值。然后就仔细研究了一下 string.Empty 和 “” 之间的区别 Empty是string类中的…

最新 CLion 2023.3.4 下载与安装 + 永久免费

文章目录 Stage 1 : 官网下载Stage 2 : 下载工具Stage 3-1 : windows为例Stage 3-2 : mac为例常见问题部分小伙伴 Mac 系统执行脚本遇到如下错误&#xff1a;解决方法&#xff1a; 执行脚本做了啥&#xff1f;和正版区别&#xff1f; Stage 1 : 官网下载 先去官网下载 我这里下…

python对接阿里云2.0SDK对接短信发送代码例子

由于官方推荐使用2.0 所以咱们与时俱进 代码部分 from alibabacloud_dysmsapi20170525.client import Client as Dysmsapi20170525Client from alibabacloud_tea_openapi import models as open_api_models from alibabacloud_dysmsapi20170525 import models as dysmsapi_20…

EAP-TLS实验之H3C MSR2600-10-X1配置相关

H3C MSR2600充当802.1x流程中的NAS&#xff08;Network Access System&#xff09;角色&#xff0c;一般负责实际待验证的设备与认证服务器之间沟通的桥梁&#xff08;当然也可以配置成认证服务器角色&#xff09;工作。在挑选购买支持802.1x的路由器或交换机时需要跟厂家明确是…

DFS之剪枝与优化

剪枝 1.优化搜索顺序&#xff1a;在大部分情况下&#xff0c;我们应该优先搜索分支较少的结点 2.排除等效冗余&#xff08;在不考虑顺序的情况下&#xff0c;尽量用组合的方式来搜索&#xff09; 3.可行性剪枝 4.最优性剪枝 5.记忆化搜索 165. 小猫爬山 - AcWing题库 import …

旧项目集成阿里云滑动验证码(web和H5方式)

简述 旧项目集成阿里云滑动验证码(web和H5方式) 适用于servlet和HTML项目,VUE + springboot请看另一篇文档 前情提示 系统: 一说 部分截图、链接等因过期、更换域名、MD语法等可能不显示,可联系反馈(备注好博文地址),谢谢❤带有​​#号、删除线、不操作、不执行​…

【力扣hot100】刷题笔记Day16

前言 干活炼丹闲暇之余来刷刷题&#xff01;NoNo应该说刷题闲暇才炼丹 994. 腐烂的橘子 - 力扣&#xff08;LeetCode&#xff09; BFS队列 参考橘子哥的题解 class Solution:def orangesRotting(self, grid: List[List[int]]) -> int:row, col, time len(grid), len(grid…

双非二本找实习前的准备day2

学习目标&#xff1a; 每天2-3到简单sql&#xff08;刷完即止&#xff09;&#xff0c;每天复习代码随想录上的题目3道算法&#xff08;时间充足可以继续&#xff09;&#xff0c;背诵的八股的问题也在这里记录了 今日碎碎念&#xff1a; SQL有些题用到的知识感觉不会出现在…

小狐狸chat2.7.2免授权修复版可用版

小狐狸chat2.7.2免授权修复版可用版 在网络上面找了好几个版本不能使用&#xff0c;今天发布这个仔细测试正常使用 主要功能&#xff1a;独立版无限多开支持分销会员充值自己APP打包小程序万能创作MJ绘图多个国内接口 国外很火的ChatGPT&#xff0c;这是一种基于人工智能技术…

《汇编语言》- 读书笔记 - 第13章-int 指令

《汇编语言》- 读书笔记 - 第13章-int 指令 13.1 int 指令13.2 编写供应用程序调用的中断例程中断例程&#xff1a;求一 word 型数据的平方主程序中断处理程序执行效果 中断例程&#xff1a;将一个全是字母&#xff0c;以0结尾的字符串&#xff0c;转化为大写主程序中断处理程序…

vue-router4 (二) 引入并配置路由

1.在项目src/router/index.ts 文件夹下配置路由&#xff1a; import { createRouter ,createWebHistory,RouteRecordRaw} from "vue-router"; //1.引入路由//3.routes配置项 const routes:Array<RouteRecordRaw> [{path:"/", //路径name:"…

IDEA利用鼠标调整字体大小

就可以按住ctrl和鼠标调节代码字体的大小啦&#xff01; 如果有用&#xff0c;记得给我来个赞~ 谢啦&#xff01;