pytest运行结束后触发钉钉通知应使用pytest_sessionfinish hook,它在所有测试完成、退出前执行;需在conftest.py中实现Webhook请求(含毫秒级timestamp和sign)、结果统计与失败用例摘要收集。

pytest运行结束后怎么触发钉钉通知
靠 pytest 的 pytest_sessionfinish hook 就能实现——它在所有测试跑完、退出前执行,是发通知的黄金时机。别用 pytest_terminal_summary,它只影响控制台输出,不保证测试已真正结束(比如有 fixture teardown 还没跑完)。
需要自己写一个 conftest.py 放在项目根目录或 tests/ 下,pytest 会自动加载其中的 hook 函数。
怎么写一个能发钉钉消息的自定义 hook
核心是两步:一是构造钉钉 Webhook 请求(需机器人 access_token + 加签逻辑),二是把测试结果(通过数、失败数、耗时)塞进消息体里。注意:钉钉要求 POST JSON,且必须带 timestamp 和 sign(除非机器人关闭了加签)。
- 先安装依赖:
pip install requests - 从钉钉后台复制机器人的 Webhook URL,形如
https://oapi.dingtalk.com/robot/send?access_token=xxx -
conftest.py中定义pytest_sessionfinish,用session参数拿到session.testscollected和session.testsfailed - 用
time.time()和hmac.new().digest()生成合法 sign(官方文档有 Python 示例,别手写 base64 编码漏掉 padding)
为什么测试失败时消息发不出去?常见坑在哪
最常踩的三个点:Webhook URL 拼错(比如多了一个斜杠)、sign 计算时 timestamp 用了秒级但钉钉要求毫秒级、HTTP 超时没设 timeout=(3, 5) 导致 pytest 卡住或静默失败。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
- 钉钉 sign 计算必须用毫秒时间戳:
int(time.time() * 1000),不是time.time() - requests 调用必须加
timeout,否则网络抖动会导致 pytest 挂起,CI 流程卡死 - 不要在 hook 里抛异常(比如 requests 报错没捕获),pytest 会吞掉它,表面看“通知没发”,实际是请求根本没发出去
- 本地调试时建议先用
print()打印完整 payload 和 URL,再 curl 手动验证
如何让通知内容包含失败用例的简要信息
pytest session 对象本身不存失败详情,得靠 pytest_runtest_makereport 钩子提前收集。你需要在 conftest.py 里同时定义两个 hook:一个存失败报告(用 session.config.cache.set() 或模块级 dict),另一个在 pytest_sessionfinish 里读出来。
- 在
pytest_runtest_makereport中判断report.when == "call" and report.failed - 提取
report.nodeid(用例路径)和report.longreprtext[:200](截断错误堆栈) - 避免直接存整个
report对象(含不可序列化内容),只存字符串字段 - 如果失败用例太多(比如 >5 条),只展示前 3 条,不然钉钉消息会被截断
钉钉通知本身不难,难的是它嵌在 pytest 生命周期里——时机不对、异常未捕获、签名算错,都会导致“以为发了其实没发”。尤其在 CI 环境里,没有控制台输出,问题更隐蔽。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










