首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Python dowhen想你想做

Python dowhen想你想做

作者头像
小田测测看
发布2026-06-17 17:18:02
发布2026-06-17 17:18:02
430
举报

dowhen 是由 Python 核心开发者 Tian Gao 推出的轻量级插桩工具,支持在不改动源码的情况下,在特定时机执行回调,特别适合测试场景:

  • 调试难复现的问题:注入断点或日志
  • 监控第三方库:无需修改源码即可监控行为
  • 模拟异常情况:测试边界条件和错误处理

"dowhen 允许你在特定触发点以清晰可维护的方式执行代码,是测试复杂系统的利器"

安装

代码语言:javascript
复制
pip install dowhen
import dowhen
print(dowhen.__version__)  # 版本

概念

触发点 (when)

定义代码中需要注入的位置:

代码语言:javascript
复制
when(目标函数, "触发点描述")

回调方法

方法

用途

测试场景

do()

执行表达式

修改变量、记录状态

bp()

启动调试器

交互式调试复杂问题

goto()

跳转到指定标签

跳过或模拟代码段

回调链

链式组合多个操作:

代码语言:javascript
复制
when(func, "point").do(...).bp().goto(...)

场景示例

监控函数

代码语言:javascript
复制
from dowhen import when, do

def  process_data(data):
    # 复杂数据处理逻辑
    result = [x * 2for x in data if x > 0]
    returnsum(result)

# 注入监控点
monitor = when(process_data, "result = [...]").do(
    'print(f"输入: {data}, 中间结果: {result}")'
)

# 测试用例
assert process_data([1, 2, 3]) == 12
monitor.remove()

2. 模拟异常条件

代码语言:javascript
复制
from dowhen import when, do

def  safe_divide(a, b):
    if b == 0:
        returnfloat('inf')
    return a / b

# 强制触发除零错误
with when(safe_divide, "if b == 0").do("b = 1"):  # 防止除零
    assert safe_divide(10, 0) == 10.0

# 测试错误处理
error_handler = when(safe_divide, "return a / b").do(
    'raise ValueError("模拟计算错误")'
)
try:
    safe_divide(10, 2)
except ValueError as e:
    print(f"成功捕获模拟错误: {e}")
error_handler.remove()

3. 模拟跳过

代码语言:javascript
复制
from dowhen import when, goto
import time

def expensive_operation(n):
    # 模拟耗时操作
    time.sleep(1)
    result = n * 2
    return result

# 测试跳过耗时操作
with when(expensive_operation, "time.sleep").goto("return result"):
    start = time.time()
    assert expensive_operation(5) == 10
    print(f"执行时间: {time.time() - start:.4f}秒")  # ≈0秒

4. 交互式调试

代码语言:javascript
复制
from dowhen import when, bp

def  complex_calculation(a, b):
    x = a + b
    y = x * 2
    z = y ** 2
    return z

# 设置条件断点
debugger = when(complex_calculation, "y = x * 2").bp().do(
    'print(f"a={a}, b={b}, x={x}, y={y}")'
)

# 触发调试
complex_calculation(3, 4)  # 进入pdb调试器
debugger.disable()  # 禁用调试器

5. 链式回调测试

代码语言:javascript
复制
from dowhen import when, do, goto

def data_pipeline(data):
    data = [x for x in data if x > 0]  # 过滤
    total = sum(data)  # 聚合
    return total / len(data)  # 计算均值

# 多阶段测试
test_handler = (
    when(data_pipeline, "data = [...]")
    .do('print(f"过滤后数据: {data}")')
    .when(data_pipeline, "total = sum")
    .do('print(f"求和结果: {total}")')
    .when(data_pipeline, "return total")
    .goto("data = [...]")  # 循环回起点
)

# 执行测试
result = data_pipeline([1, -2, 3, -4, 5])
print(f"最终结果: {result}")
test_handler.remove()

6. 动态启停

代码语言:javascript
复制
from dowhen import when, do

def api_client(request):
    # 模拟API调用
    return {"status": "success", "data": request * 2}

# 创建可切换的测试点
test_point = when(api_client, "return").do(
    'print(f"API调用: 请求={request}, 响应={_}");'
    'if "error" in request: _["status"] = "error"'
)

# 正常模式
print("正常响应:", api_client("test")) 

# 测试错误处理
test_point.enable()
print("错误模拟:", api_client({"error": True}))
test_point.disable()

7.隔离测试环境****命名测试处理器

代码语言:javascript
复制
# 清晰命名便于管理
perf_test = when(func, "slow_op").goto(...)
error_test = when(func, "validate").do(...)

8.结合测试框架

代码语言:javascript
复制
# pytest示例
import pytest

@pytest.fixture
def mock_database():
    with when(db, "query").do('return ["mock", "data"]'):
        yield

def test_app(mock_database):
    assert app.run() == ["mock", "data"]

资源推荐

  1. 1. 官方文档 - 完整API参考和高级用法
  2. https://dowhen.readthedocs.io/
  3. 2. GitHub仓库

https://github.com/gaogaotiantian/dowhen

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

本文分享自 编程拾光 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 安装
  • 概念
    • 触发点 (when)
    • 回调方法
    • 回调链
  • 场景示例
    • 监控函数
    • 2. 模拟异常条件
    • 3. 模拟跳过
    • 4. 交互式调试
    • 5. 链式回调测试
    • 6. 动态启停
    • 7.隔离测试环境****命名测试处理器
    • 8.结合测试框架
  • 资源推荐
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档