使用 Python 语言 从 0 到 1 搭建完整 Web UI自动化测试学习系列 44--将自动化测试结果自动推送至钉钉工作群聊

测试学习记录,仅供参考!

将钩子函数获取到的自动化测试统计结果发送到钉钉聊天群里面

1、烦请自行下载、注册钉钉(例:企业微信、飞书等等),创建一个聊天群;

2、在群设置里面添加一个聊天机器人(自行添加设置);

3、在机器人设置中获取到聊天群机器人的 'Webhook地址' 和 '加签签名' 字段信息;

Webhook:--发送请求时需要把消息推送给Webhook接口地址

加签:--钉钉安全设置三种方式之一,需要用到的是加签方式--拿到加签签名

生成签名计算在钉钉官方文档中是有的,可直接粘贴复制--自定义机器人接入-钉钉开发平台

4、拿到这两个字段之后就可以在代码中去发送请求,然后把测试结果推送到聊天群里;

生成加密密钥

5、在项目根目录 util_tools 软件包下新建一个名称为 dingRebot.py 的 Python 文件;

python 复制代码
# 导包
import time
import urllib.parse
import hmac
import hashlib
import base64

# 生成加签密钥
def generate_sign():
    # 通过 time.time() 获取时间戳--获取13位乘以1000--调用round函数保留整数--最后再转成字符串得到当前时间戳--返回给timestamp
    timestamp = str(round(time.time() * 1000))
    # 获取钉钉机器人里面的加签密钥--属于某个钉钉群里面的加签密钥
    secret = 'SEC5bec56af5a1059e5e69b75250703dc53236c09e61501b356c3bf21c21b55b5e5'
    # 转码成utf-8
    secret_enc = secret.encode('utf-8')
    # 组合当前时间戳和加签密钥
    str_to_sign = f'{timestamp}\n{secret}'
    # 先打印查看得到的是什么
    print(str_to_sign)

# 调用测试
print(generate_sign())

6、单独运行 dingRebot.py 文件查看结果;

python 复制代码
1621578081
SEC5bec56af5a1059e5e69b75250703dc53236c09e61501b356c3bf21c21b55b5e5
None

进程已结束,退出代码为 0

7、优化 dingRebot.py 文件;

python 复制代码
# 导包
import time
import urllib.parse
import hmac
import hashlib
import base64

# 生成加签密钥
def generate_sign():
    # 通过 time.time() 获取时间戳--获取13位乘以1000--调用round函数保留整数--最后再转成字符串得到当前时间戳--返回给timestamp
    timestamp = str(round(time.time() * 1000))
    # 获取钉钉机器人里面的加签密钥--属于某个钉钉群里面的加签密钥
    secret = 'SEC5bec56af5a1059e5e69b75250703dc53236c09e61501b356c3bf21c21b55b5e5'
    # 转码成utf-8
    secret_enc = secret.encode('utf-8')
    # 组合当前时间戳和加签密钥
    str_to_sign = f'{timestamp}\n{secret}'
    # 转成byte类型
    str_to_sign_enc = str_to_sign.encode('utf-8')
    # 先打印查看
    print(str_to_sign_enc)

# 调用测试
print(generate_sign())

8、再次运行 dingRebot.py 文件查看结果;

拿到这组数据之后,通过加密方式加密当前时间戳和密钥;

python 复制代码
b'1621578081\nSEC5bec56af5a1059e5e69b75250703dc53236c09e61501b356c3bf21c21b55b5e5'
None

进程已结束,退出代码为 0

9、优化 dingRebot.py 文件,进行初步加密;

1)、hmac:调用加密模块;

2)、hmac.new():直接点.调用 hmac.new() 方法;

3)、hmac.new(secret_enc, str_to_sign_enc):传参;里面第一个参数传 secret_enc,第二个参数传 str_to_sign_enc;注意参数别传错了;

4)、hmac.new(secret_enc, str_to_sign_enc, digestmod=hashlib.sha256):调用hashlib模块里面的一个内置方法 digestmod=hashlib.sha256()--直接点.调用时会带有括号,这里不需要直接去掉,调用函数名就行;

5)、hmac.new(secret_enc, str_to_sign_enc, digestmod=hashlib.sha256).digest():调用digest()方法;

6)、hmac_code = hmac.new(secret_enc, str_to_sign_enc, digestmod=hashlib.sha256).digest():返回;

python 复制代码
# 导包
import time
import urllib.parse
import hmac
import hashlib
import base64

# 生成加签密钥
def generate_sign():
    # 通过 time.time() 获取时间戳--获取13位乘以1000--调用round函数保留整数--最后再转成字符串得到当前时间戳--返回给timestamp
    timestamp = str(round(time.time() * 1000))
    # 获取钉钉机器人里面的加签密钥--属于某个钉钉群里面的加签密钥
    secret = 'SEC5bec56af5a1059e5e69b75250703dc53236c09e61501b356c3bf21c21b55b5e5'
    # 转码成utf-8
    secret_enc = secret.encode('utf-8')
    # 组合当前时间戳和加签密钥
    str_to_sign = f'{timestamp}\n{secret}'
    # 转成byte类型
    str_to_sign_enc = str_to_sign.encode('utf-8')
    # 通过加密方式加密当前时间戳和密钥--初步加密
    hmac_code = hmac.new(secret_enc, str_to_sign_enc, digestmod=hashlib.sha256).digest()
    # 打印查看得到的初步加密方式
    print(hmac_code)

# 调用测试
print(generate_sign())

10、运行 dingRebot.py 文件查看初步加密;

python 复制代码
b'\x6a0\xf0\xcbc_\xfb\x86\x16RS\x07kJ\x1fs5\x17\xdc\xb7\xdb\xf0OJ7\xa1\xf7\xdcb\xa9\xf1('
None

进程已结束,退出代码为 0

11、进一步加密,得到最终的一个签名;

1)、urllib.parse:调用 urllib.parse 方法;

2)、urllib.parse.quote_plus():调用 quote_plus() 方法;

3)、urllib.parse.quote_plus(base64):调用 base64 模块里面的方法;

4)、urllib.parse.quote_plus(base64.b64encode()):encode转码decode解码,注意两者区别别弄错了;

5)、sign = urllib.parse.quote_plus(base64.b64encode(hmac_code)):把 hmac_code 传进来并返回;

python 复制代码
# 导包
import time
import urllib.parse
import hmac
import hashlib
import base64

# 生成加签密钥
def generate_sign():
    # 通过 time.time() 获取时间戳--获取13位乘以1000--调用round函数保留整数--最后再转成字符串得到当前时间戳--返回给timestamp
    timestamp = str(round(time.time() * 1000))
    # 获取钉钉机器人里面的加签密钥--属于某个钉钉群里面的加签密钥
    secret = 'SEC5bec56af5a1059e5e69b75250703dc53236c09e61501b356c3bf21c21b55b5e5'
    # 转码成utf-8
    secret_enc = secret.encode('utf-8')
    # 组合当前时间戳和加签密钥
    str_to_sign = f'{timestamp}\n{secret}'
    # 转成byte类型
    str_to_sign_enc = str_to_sign.encode('utf-8')
    # 通过加密方式加密当前时间戳和密钥--初步加密
    hmac_code = hmac.new(secret_enc, str_to_sign_enc, digestmod=hashlib.sha256).digest()
    sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))
    # 打印查看得到的最终签名
    print(sign)

# 调用测试
print(generate_sign())

12、运行 dingRebot.py 文件查看得到的最终签名;

python 复制代码
dWmAZkP%5BUU5cgCckTfOs95qydXYF6BXRDmlH6sHSHT8%6D
None

进程已结束,退出代码为 0

13、通过时间戳和机器人的签名,然后通过加密的方式得到最终签名;

最后把结果给返回出去;返回两个参数,一个是 timestamp(后面需要用到时间戳),第二个是 sign 签名;

python 复制代码
# 导包
import time
import urllib.parse
import hmac
import hashlib
import base64

# 生成加签密钥
def generate_sign():
    # 通过 time.time() 获取时间戳--获取13位乘以1000--调用round函数保留整数--最后再转成字符串得到当前时间戳--返回给timestamp
    timestamp = str(round(time.time() * 1000))
    # 获取钉钉机器人里面的加签密钥--属于某个钉钉群里面的加签密钥
    secret = 'SEC5bec56af5a1059e5e69b75250703dc53236c09e61501b356c3bf21c21b55b5e5'
    # 转码成utf-8
    secret_enc = secret.encode('utf-8')
    # 组合当前时间戳和加签密钥
    str_to_sign = f'{timestamp}\n{secret}'
    # 转成byte类型
    str_to_sign_enc = str_to_sign.encode('utf-8')
    # 通过加密方式加密当前时间戳和密钥--初步加密
    hmac_code = hmac.new(secret_enc, str_to_sign_enc, digestmod=hashlib.sha256).digest()
    sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))

    return timestamp, sign

# 调用测试
print(generate_sign())

发起机器人信息请求

14、签名方法编写完成之后,继续写发送机器人消息方法;

python 复制代码
# 导包
import time
import urllib.parse
import hmac
import hashlib
import base64
import requests

# 生成加签密钥
def generate_sign():
    # 通过 time.time() 获取时间戳--获取13位乘以1000--调用round函数保留整数--最后再转成字符串得到当前时间戳--返回给timestamp
    timestamp = str(round(time.time() * 1000))
    # 获取钉钉机器人里面的加签密钥--属于某个钉钉群里面的加签密钥
    secret = 'SEC5bec56af5a1059e5e69b75250703dc53236c09e61501b356c3bf21c21b55b5e5'
    # 转码成utf-8
    secret_enc = secret.encode('utf-8')
    # 组合当前时间戳和加签密钥
    str_to_sign = f'{timestamp}\n{secret}'
    # 转成byte类型
    str_to_sign_enc = str_to_sign.encode('utf-8')
    # 通过加密方式加密当前时间戳和密钥--初步加密
    hmac_code = hmac.new(secret_enc, str_to_sign_enc, digestmod=hashlib.sha256).digest()
    sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))

    return timestamp, sign

# 发送钉钉群消息
def send_dd_msg(content_str, at_all=True):
    """
    :param content_str: 发送的内容
    :param at_all: 是否@全员,默认为True
    :return:
    """
    # 调用generate_sign()方法--用两个参数去接受调用generate_sign()方法返回函数的结果
    timestamp, sign = generate_sign()
    # 参照官方文档组成一个完整的url地址--通过'&'符号去拼接已经复制好的 Webhook、时间戳、签名
    url = f'https://oapi.dingtalk.com/robot/send?access_token=db50eb02dea33ed5ef5e5cfc2cc9f50d737f0ac2c636e9b329e511c365d5ae55&timestamp={timestamp}&sign={sign}'
    # 请求头(参考钉钉开放接口官方文档)--这里是一个 json 提交格式
    headers = {'Content-Type': 'application/json;charset=UTF-8'}
    # 入参--消息类型msgtype:文本text--第二个又是嵌套字典text发送内容:要传进来的参数content--下一个参数名是'at'是否发送全员提醒
    data = {
        'msgtype': 'text',
        'text': {'content': content_str},
        'at': {'isAtAll': at_all}
    }
    # 发起请求,引入requests模块--使用post请求方式,传已经拼接完成的url,用json格式提交入参data,再把请求头headers传给它--返回出去
    res = requests.post(url=url, json=data, headers=headers)
    # 返回文本信息res.text
    return res.text


# 调用发送消息方法
print(send_dd_msg('这是一个测试消息:123'))

15、运行一下,查看能否成功发送出消息;

python 复制代码
{"errcode":0,"errmsg":"ok"}

进程已结束,退出代码为 0

1)、可以查看到发送的测试消息是提醒全部人员;

2)、设置 at_all=False 参数为False;

python 复制代码
# 调用发送消息方法
print(send_dd_msg('这是一个测试消息:123', at_all=False))


# 运行dingRebot.py文件结果
{"errcode":0,"errmsg":"ok"}

进程已结束,退出代码为 0

3)、再次发送执行,可以看到只是发送一条普通消息,不进行全员提醒;

把加签签名、url 地址写到配置文件中

16、把加签签名、url 地址写到配置文件中去(后续需要再其他的钉钉群里发送消息,直接修改'地址'和'加签'信息即可)

17、优化项目根目录 configs 软件包下 setting.py 文件--(把'加签签名'和'url 地址'放在setting.py文件中)

python 复制代码
# 导包
import os
import sys

DIR_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(DIR_PATH)

# 显示等待时间设置,默认为10秒
WAIT_TIME = 10

# 设置浏览器
browser_type = 'edge'
# browser_type = 'chrome'

# 消息是否发送--True是发送,False是不发送
is_dd_msg = False
# 自定义机器人签名
secret = 'SEC5bec56af5a1059e5e69b75250703dc53236c09e61501b356c3bf21c21b55b5e5'
# URL地址
webhook = ('https://oapi.dingtalk.com/robot/send?access_token=db50eb05dea33ed5ef5e5cfc2cc9f50d737f0ac2c636e9b329e511c365d5ae55')

# 文件路径
FILE_PATH = {
    'log': os.path.join(DIR_PATH, 'log'),
    'screenshot': os.path.join(DIR_PATH, 'screenshot'),
    'ini': os.path.join(DIR_PATH, 'config', 'config.ini')
}

18、优化项目根目录 util_tools 软件包下 dingRebot.py 文件;通过配置文件调用;

python 复制代码
# 导包
import time
import urllib.parse
import hmac
import hashlib
import base64
import requests
from config import setting

# 生成加签密钥
def generate_sign():
    # 通过 time.time() 获取时间戳--获取13位乘以1000--调用round函数保留整数--最后再转成字符串得到当前时间戳--返回给timestamp
    timestamp = str(round(time.time() * 1000))
    # 获取钉钉机器人里面的加签密钥--属于某个钉钉群里面的加签密钥--通过配置文件调用
    secret = setting.secret
    # 转码成utf-8
    secret_enc = secret.encode('utf-8')
    # 组合当前时间戳和加签密钥
    str_to_sign = f'{timestamp}\n{secret}'
    # 转成byte类型
    str_to_sign_enc = str_to_sign.encode('utf-8')
    # 通过加密方式加密当前时间戳和密钥--初步加密
    hmac_code = hmac.new(secret_enc, str_to_sign_enc, digestmod=hashlib.sha256).digest()
    sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))

    return timestamp, sign

# 发送钉钉群消息
def send_dd_msg(content_str, at_all=True):
    """
    :param content_str: 发送的内容
    :param at_all: 是否@全员,默认为True
    :return:
    """
    # 调用generate_sign()方法--用两个参数去接受调用generate_sign()方法返回函数的结果
    timestamp, sign = generate_sign()
    # 参照官方文档组成一个完整的url地址--通过'&'符号去拼接已经复制好的 Webhook、时间戳、签名--通过配置文件调用
    url = f'{setting.webhook}&timestamp={timestamp}&sign={sign}'
    # 请求头(参考钉钉开放接口官方文档)--这里是一个 json 提交格式
    headers = {'Content-Type': 'application/json;charset=UTF-8'}
    # 入参--消息类型msgtype:文本text--第二个又是嵌套字典text发送内容:要传进来的参数content--下一个参数名是'at'是否发送全员提醒
    data = {
        'msgtype': 'text',
        'text': {'content': content_str},
        'at': {'isAtAll': at_all}
    }
    # 发起请求,引入requests模块--使用post请求方式,传已经拼接完成的url,用json格式提交入参data,再把请求头headers传给它--返回出去
    res = requests.post(url=url, json=data, headers=headers)
    # 返回文本信息res.text
    return res.text

19、优化项目根目录下 conftest.py 文件--发送自动化测试结果信息;

python 复制代码
# 导包
import time
import pytest
from util_tools.connectMysql import ConnectMysql
from util_tools.dingRebot import send_dd_msg
from util_tools.logs_util.recordlog import logs
from config.setting import is_dd_msg

# 添加后置应用--数据清理
@pytest.fixture(scope='session', autouse=True)
def data_cleaning():
    """测试结束后清理测试数据"""
    # 初始化连接数据库对象
    conn = ConnectMysql()
    yield
    logs.info('正在清理测试数据...')
    # 删除语句(注册成功用户)--若有别的可以继续写
    sql = 'delete from ecs_users where user_name="test06"'
    # 调用删除语句
    conn.delete(sql)

def pytest_terminal_summary(terminalreporter, exitstatus, config):
    """
    pytest预定义钩子函数,用于自动收集测试用例执行结果
    :param terminalreporter: 报告汇总,内部使用的终端测试报告器对象,用于输出内容
    :param exitstatus: 返回码退出状态:0-用例全部通过;1-有用例失败;2-还没执行,在收集用例就失败了;3、4-其他报错;5-收集到0条用例
    :param config: pytest全局config配置对象
    :return:
    """
    # 调用里面的内置方法,最后把收集统计到的测试用例总数量返回出去给一个变量(把所有测试用例收集完之后才去统计)
    total = terminalreporter._numcollected
    # 通过数
    passed = len(terminalreporter.stats.get('passed', []))
    # 失败数
    failed = len(terminalreporter.stats.get('failed', []))
    # 错误数
    error = len(terminalreporter.stats.get('error', []))
    # 跳过数
    skipped = len(terminalreporter.stats.get('skipped', []))
    # 执行总时长--调用内置函数round()
    duration = round(time.time() - terminalreporter._sessionstarttime, 2)

    # 定义一个字符串
    summary = f"""
    自动化测试结果,通知如下,具体执行结果如下:
    测试用例总合计数:{total}
    测试执行通过数:{passed}
    测试执行失败数:{failed}
    错误数量:{error}
    跳过执行测试用例数量:{skipped}
    执行测试用例总耗时:{duration}秒
    """
    print(summary)
    # 判断is_dd_msg值
    if is_dd_msg:
        # 发送消息
        send_dd_msg(summary)

20、运行主函数 run.py 文件;

未完待续。。。

相关推荐
沈浩(种子思维作者)2 小时前
铁的居里点(770度就不被磁铁吸了)道理是什么?能不能精确计算出来?
人工智能·python·flask·量子计算
沛沛老爹2 小时前
Web开发者转型AI:多模态Agent视频分析技能开发实战
前端·人工智能·音视频
yufuu982 小时前
使用Scikit-learn进行机器学习模型评估
jvm·数据库·python
David凉宸2 小时前
vue2与vue3的差异在哪里?
前端·javascript·vue.js
笔画人生2 小时前
Cursor + 蓝耘API:用自然语言完成全栈项目开发
前端·后端
计算机毕业编程指导师2 小时前
大数据可视化毕设:Hadoop+Spark交通分析系统从零到上线 毕业设计 选题推荐 毕设选题 数据分析 机器学习 数据挖掘
大数据·hadoop·python·计算机·spark·毕业设计·城市交通
计算机毕业编程指导师2 小时前
【计算机毕设选题】基于Spark的车辆排放分析:2026年热门大数据项目 毕业设计 选题推荐 毕设选题 数据分析 机器学习 数据挖掘
大数据·hadoop·python·计算机·spark·毕业设计·车辆排放
浔川python社2 小时前
浔川社团关于产品数据情况的官方通告
python
AC赳赳老秦2 小时前
外文文献精读:DeepSeek翻译并解析顶会论文核心技术要点
前端·flutter·zookeeper·自动化·rabbitmq·prometheus·deepseek