测试学习记录,仅供参考!
将钩子函数获取到的自动化测试统计结果发送到钉钉聊天群里面
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×tamp={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}×tamp={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 文件;

未完待续。。。