需求梳理:
微信小程序的登录流程
developers.weixin.qq.com/miniprogram…
小程序登陆需要在小程序内部调用wx.login()的方法拿到code,然后去请求服务获取到token后续的接口才能请求。
Python 使用minium,JS 使用miniprogram-automator,这是微信官方提供的 UI 自动化测试的工具,它们的原理都是调起微信开发者工具,然后会对外提供了一个自动化测试的端口,然后它们的 API 应该都是和这个端口进行通信。
1、miniprogram-automator 使用文档: developers.weixin.qq.com/miniprogram…
2、minium MiniTest 使用文档: minitest.weixin.qq.com/#/minium/Py…
运行环境
- Python 3.8及以上
- 微信开发者工具 (本文档中简称IDE)最新版本,并打开安全模式: 设置 -> 安全设置 -> 服务端口: 打开
- 微信 >= 7.0.7 (确认微信公共库版本 >= 2.7.3即可)
安装
自动安装pip3 install minium或者
pip3 install [https://minitest.weixin.qq.com/minium/Python/dist/minium-latest.zip](https://minitest.weixin.qq.com/minium/Python/dist/minium-latest.zip)
如果需要ios真机测试, 会额外安装一些依赖库
pip3 install minium[ios]
手动安装 下载minium安装包, 解压后进入文件夹, 运行
python3 setup.py install
环境检查
minium安装完成后,可执行以下命令查看版本:
minitest -v
出现如以下内容的构建信息则已安装成功
{‘version’: ‘1.1.0’, ‘revision’: ‘2fac2e36c281213874110f2088bc08c570bc1a2d’, ‘branch’: ‘master’, ‘update_at’: ‘2021-08-05 21:17:09’}
开发者工具自动化能力检查
“path/to/cli” auto --project “path/to/project” --auto-port 9420
例:
C:\Program Files (x86)\Tencent\微信web开发者工具> .\cli.bat auto --project “D:\test-data\home-elev-master” --auto-port 9420
脚本开发
1、原理:Python 使用minium,使用minium.app.call_wx_method()方法调用wx.login()方法就可以获取code。
开发文档:minitest.weixin.qq.com/#/minium/Py…
2、编写调试脚本
#!/usr/bin/env python3
import minium
mini = minium.Minium({
"project_path": "D:\\test-data\home-elev-master", # 小程序的路径
"dev_tool_path": "C:\Program Files (x86)\Tencent\微信web开发者工具\cli.bat" # 开发者工具的路径
})
# 调用wx.login()方法获取code
login_info = mini.app.call_wx_method("login")
wx_code = login_info["result"]["result"]["code"]
print(wx_code)
# 调试前注意环境的设置
3、封装
#!/usr/bin/env python3
import minium
class WxLogin:
def __init__(self):
self.mini = minium.Minium({
"project_path": "D:\\test-data\home-elev-master", # 小程序的路径
"dev_tool_path": "C:\Program Files (x86)\Tencent\微信web开发者工具\cli.bat" # 开发者工具的路径
})
def get_login_code(self):
# 调用wx.login接口获取登录信息
login_info = self.mini.app.call_wx_method("login")
# 获取code
wx_code = login_info["result"]["result"]["code"]
print(wx_code)
return wx_code
4、调用
def minigram_login():
"""
获取token
"""
url = "xxx"
headers = {"content-type": "application/json"}
# 获取code
wx_code = WxLogin().get_login_code()
data = {"code": wx_code}
response = requests.post(url=url, json=data, headers=headers)
assert response.json()["success"] == 1
token = response.json()["obj"]["token"]
print(token)
return token
Mac端实测
根据手机号授权获取登录信息
import requests
from minium import Minium
import threading
mini = Minium({
"project_path": "/Users/lizhixiang/Downloads/test-py-auto-test", # 小程序的路径
"dev_tool_path": "/Applications/wechatwebdevtools.app/Contents/MacOS/cli" # 开发者工具的路径
})
# self.native = native
class HookNative(object):
def __init__(self, native, test) -> None:
self.native = native
self.test = test
def release(self):
self.test = None
self.native = None
def __getattr__(self, name):
item = getattr(self.native, name)
if name not in ("screen_shot", "kvtest_get", "capture") and callable(item):
def wrapper(*args, **kwargs):
time.sleep(2)
self.test.capture("before %s" % name)
ret = item(*args, **kwargs)
self.test.logger.info("call %s ret %s" % (name, ret))
self.test.capture("after %s" % name)
return ret
return wrapper
return item
class WxLogin:
# def __init__(self, native):
def get_login_code():
login_info = mini.app.call_wx_method("login")
wx_code = login_info["result"]["result"]["code"]
print(wx_code)
return wx_code
@classmethod
def get_user_phone(cls):
called = threading.Semaphore(0)
detail = errMsg = None
def callback(args):
nonlocal detail, errMsg
called.release()
detail = args[0]["detail"]
errMsg = detail["errMsg"]
mini.app.hook_current_page_method("testGetPhoneNumber", callback)
mini.app.get_current_page().get_element("#testGetPhoneNumber").tap()
# if cls.native.handle_modal("取消", title="微信帐号还没有绑定手机号"):
# assert called.acquire(timeout=10), "callback called"
# assert "getPhoneNumber:fail" in errMsg
# else:
# cls.native.get_user_phone()
assert called.acquire(timeout=10), "callback called"
# assert {"errMsg": "getPhoneNumber:ok"} in detail
return detail
@classmethod
def minigram_login(cls):
url = "接口地址"
headers = {"content-type": "application/json"}
wx_code = cls.get_login_code()
data = {"code": wx_code, "appId": '替换成appId'}
with requests.Session() as session:
response = session.post(url=url, json=data, headers=headers)
response_json = response.json()
print(response_json)
openid = response_json["data"]["openId"]
detail = cls.get_user_phone()
print(detail)
query = {"openId": openid, "appId": '替换成appId', "phoneEncryptedData": detail['encryptedData'], "phoneIv": detail['iv']} onekey_url = '接口地址'
print(query)
response_token_res = session.post(url=onekey_url, json=query, headers=headers)
response_json_token = response_token_res.json()
print(response_json_token)
token = response_json_token["data"]["token"]
print(token)
return token
if __name__ == '__main__':
WxLogin.minigram_login()
前端小程序可以使用下面代码测试,备miniprogram-demo-test
附录:
1、小程序自动化框架 minium 官方文档、minium 测试 demo
git.weixin.qq.com/groups/mini…
2、录制回放
developers.weixin.qq.com/miniprogram…
3、微信小程序自动化框架 minium 实践:
developers.weixin.qq.com/community/d…
4、miniprogram-demo-test