前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >proxy在app自动化中的应用

proxy在app自动化中的应用

作者头像
赵云龙龙
发布2021-06-09 15:24:01
1.1K0
发布2021-06-09 15:24:01
举报
文章被收录于专栏:python爱好部落python爱好部落

在做测试的时候,如果客户端有很多场景,我们又不太好造数据,可以考虑mock. app的mock怎么做呢?我们可以考虑用mitmproxy

mitmproxy 提供了三个命令,启动模式不同: mitmproxy -> 提供一个命令行界面(该命令不支持windows)。 mitmdump -> 提供一个简单的终端输出。 mitmweb -> 提供一个浏览器界面。

mitmproxy的信息,可以参考: https://crifan.github.io/crawler_proxy_tool_mimproxy/website/mitmdump/install/win.html 然后在移动设备上设置代理。 在手机浏览器中输入mitm.it 下载并安装证书 接下来就是写代理脚本了。 脚本编写的两个条件 1.1、编写一个 py 文件供 mitmproxy 加载,文件中定义了若干函数,这些函数实现了某些 mitmproxy 提供的事件,mitmproxy 会在某个事件发生时调用对应的函数 1.2、编写一个 py 文件供 mitmproxy 加载,文件定义了【变量 addons】,addons 是个数组,每个元素是一个类实例,这些类有若干方法,这些方法实现了某些 mitmproxy 提供的事件,mitmproxy 会在某个事件发生时调用对应的方法。这些类,称为一个个 addon。 基本模板为

from mitmproxy import http, ctx
import json

class xxx:
    def xxx:
    def xxx

addons = [
    xxx() //类名的加载,也可以定义多个类,然后以数组的形式添加,进行加载
]

客户端请求修改 3.1、修改请求针对域名,替换请求链接。

from mitmproxy import ctx, http
import json

class Modify:

        def request(self, flow):
            #替换请求链接
            if flow.request.url.startswith("http://spay1.shuqireader.com/api/ios/info?method=priceList"):
            #有分享
            flow.request.url = "http://activity.x.xxx.xx.cn/share?id=2653&useShare=1"
            ctx.log.info("修改链接")
                
         
addons = [
    Modify()
]

3.2、修改cookie

from mitmproxy import ctx, http
import json

class Modify:

     def request(self, flow):
         #替换cookie,两种匹配请求链接的方式
        # if flow.request.host == "xxx.x.xxx.com.cn":
        if flow.request.url.startswith("https://xxx.x.xxx.com.cn/"):
            print(flow.request.url)
            print(flow.request.cookies)
            flow.request.cookies["_testCookie1"] = "xxx-91"
            flow.request.cookies["testCookie2"] = "123"

            req = flow.request.cookies["_testCookie1"]
            ctx.log.info(req)
         
addons = [
    Modify()
]

3.3、修改请求参数

from mitmproxy import ctx, http
import json

class Modify:
     def request(self, flow):
                if flow.request.url.startswith("http://xxx.x.xxx.com.cn/customActivity/bookcode/doJoin"):
            ctx.log.info("modify request form")
            if flow.request.urlencoded_form:
                flow.request.urlencoded_form["code"] = "11111"
            else:
                flow.request.urlencoded_form = [
                    ("actId", "20727"),("nick","name")
                ]
         
addons = [
    Modify()
]

4、响应修改 4.1、修改响应的状态码

from mitmproxy import ctx, http
import json

class Modify:
    def response(self, flow):
         if flow.request.url.startswith("http://baidu.com.cn"):
            flow.response = http.HTTPResponse.make(404)
            ctx.log.info("modify status code")
 
 addons = [
    Modify()
]

4.2、修改响应的消息体-直接修改响应字段

from mitmproxy import ctx, http
import json

class Modify:
    def response(self, flow):
        if flow.request.url.startswith("https://xxx.x.xxx.com.cn/activityInfo/getPrizeInfo=="):
             //获取响应的json字符串,转成python对象进行解析和修改
            response = json.loads(flow.response.get_text())
            response['limitCount'] = 1
            //修改完成后,python对象转成json字符串,set进请求的响应体重发送给客户端
            flow.response.set_text(json.dumps(response))
            ctx.log.info('modify limitCount')
 
 addons = [
    Modify()
]

4.3、修改响应的消息体-通过读取json文件的字符串返给客户端

from mitmproxy import ctx, http
import json

class Modify:
    def response(self, flow):
        if flow.request.url.startswith("https://xxx.x.xxx.com.cn/activityInfo/getPrizeInfo=="):
            //读取文件,在当前文件路径下执行脚本,否则需要写文件的绝对路径;不然会找不到该json文件
             with open('getStatus.json','rb') as f:
                //从json文件中读取数据成python对象
                res = json.load(f)
            //将读取的python对象转成json字符串发送给客户端
            flow.response.set_text(json.dumps(res))
            ctx.log.info("modify order status")
 
 addons = [
    Modify()
]

这样,我们就可以自定义返回,

from mitmproxy import ctx, http
import json

class Modify:
    def response(self, flow):
        if flow.request.url.startswith("https://xxxx/services/api/dod/oneapp/trial/ocb/cc"):
            # 读取文件,在当前文件路径下执行脚本,否则需要写文件的绝对路径;不然会找不到该json文件
            with open('getStatus.json', 'rb') as f:
                # 从json文件中读取数据成python对象
                res = json.load(f)
                # 将读取的python对象转成json字符串发送给客户端
                flow.response.set_text(json.dumps(res))
                ctx.log.info("modify order status")
addons = [Modify()]

如何请求呢?一般我们用os.system的时候,会全程代理某个请求,但是我们想不同的case,代理不同的请求,怎么弄。 建议用subprocess 因为如果你的程序不会自动停止,那么用os.system(cmd),cmd会一直持续运行知道调用的程序返回结果。 subprocess可以开启一个子线程,在子线程里面调用,在你需要的时候就可以把这个子线程关掉,这样代码也更灵活 例如:

p = subprocess.Popen("your command")
#todo
#anything you want
time.sleep(10)
p.kill()
这段代码就是在"your command"运行10秒以后,把它杀掉

这样我们就可以在pytest的conftest里面请求我们的调用了

import pytest
import uiautomator2 as u2
from utils.run_helper import Device
import subprocess

@pytest.fixture(scope="module")
def proxy():
    cmd=r"mitmdump -s C:\work\code\regression\utils\defineproxy.py -p 8889"
    p = subprocess.Popen(cmd)
    print(p.stdout)
    yield
    p.kill()


@pytest.fixture(scope="module")
def driver():
    _driver = u2.connect()
    d = Device(_driver)
    d.start_app()
    yield _driver

当然我们可以代理的json用文件,也可以用fast api来返回。据说fast api很好用,有点像flask, 例如:

import uvicorn
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def root():
    return {"message": "Hello World"}

if __name__ == '__main__':
    uvicorn.run(app='main:app', host="127.0.0.1", port=8002, reload=True, debug=True)

这样,自动化跑起来就爽爽的了。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-05-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 python粉丝团 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
命令行工具
腾讯云命令行工具 TCCLI 是管理腾讯云资源的统一工具。使用腾讯云命令行工具,您可以快速调用腾讯云 API 来管理您的腾讯云资源。此外,您还可以基于腾讯云的命令行工具来做自动化和脚本处理,以更多样的方式进行组合和重用。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档