如何修补内置的python 3 breakpoint()? [英] How to patch the python 3 breakpoint() builtin?

查看:83
本文介绍了如何修补内置的python 3 breakpoint()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一个装饰器,如果发生严重错误,该程序将使用breakpoint()暂停程序.

I wrote a decorator that halts my program with breakpoint() if a critical error happens.

def the_breakpoint_dec(func):
    @functools.wraps(func):
    async def my_wrapper(func):
       retval=await func(*args,**kwargs)
       return retval if retval else breakpoint()
    return my_wrapper

我正在做单元测试,想确保断点命中,而没有实际触发它,所以我一直在尝试使用@ mock.patch装饰器修补breakpoint(),但是它不起作用.我尝试过一些测试到20左右断点的路径

I'm doing unit testing and want to make sure the breakpoint hits, without actually triggering it, so I've been trying to patch breakpoint() with the @mock.patch decorator, but it's not working. Some of the tested paths to breakpoint of the 20 or so i've tried are

@mock.patch('pdb.breakpoint')
@mock.patch('builtins.breakpoint')
@mock.patch('builtins.pdb.breakpoint')
@mock.patch('my_module.breakpoint')
@mock.patch('my_module.builtins.breakpoint')
@mock.patch('sys.breakpointhook')
@mock.patch('my_module.sys.breakpointhook')
@mock.patch('my_decorator_module.sys.breakpointhook')
@mock.patch('my_decorator_module.sys.breakpoint')


然后我将测试函数定义为def并传递模拟:

I then make the test function def and pass in the mock:

#testmodule.py
pytestmark=pytest.mark.asyncio
@mock.patch('just_another_path_to_breakpoint()_that_doesnt_work')
async def test_func_to_test(self, mock_breakpoint, some_other_mock): 
    mock_breakpoint.return_value=None
    await decorated_func()
    mock_breakpoint.assert_called() # never hit because pdb prompt opens in interpreter

被测模块

#moduleundertest.py

class bar:
    @the_breakpoint_dec
    async def decorated_func(self):
        for i in range(3)
            try:
                return await something_likely_to_fail()
            except:
                pass

最初,我要修补的breakpoint()是从提到的装饰器中调用的.几个小时的失败后,我注释掉了装饰器,并将breakpoint()直接移到了要测试的方法中.修补仍然失败.修补此内置文件的正确方法是什么,如果在装饰器中对其进行修补时必须做一些特殊的事情,那是什么呢?

Initially the breakpoint() I wanted to patch was being called from the mentioned decorator. After several hours of failures I commented out the decorator and moved breakpoint() directly into the method under test. The the patching still failed. What is the proper way to patch this builtin, and if some special thing must be done to patch it when it's in a decorator, what thing is that?

推荐答案

要解决,请将您的项目升级到3.8!

我尝试在3.8中重现您的方案,但不能,该修补程序对我来说效果很好.但是,当尝试使用3.7及以下版本时,修补程序停止工作,并且我的程序将进入断点.我对此没有任何解释.

I tried to reproduce your scenario in 3.8 and couldn't, the patching worked fine for me. But then when trying with 3.7 and below, the patching stopped working and my program would enter the breakpoint. I have no explanation for this.

这是我编写的一个完整的运行示例.它运行 function_to_test ,模拟成功然后失败( True / False ).正如 assert s所证明的那样,它仅在失败情况下调用 breakpoint(),但由于我们模拟了 breakpoint(),因此测试完全退出了-至少在3.8中.

Here's a complete running example I coded up. It runs the function_to_test, simulating success and then failure (True/False). As proven by the asserts it only invokes breakpoint() in the failure case, but the test exits cleanly due to our mocked breakpoint() -- at least in 3.8.

from unittest import mock
import functools
import asyncio

def break_if_function_fails(func):
    @functools.wraps(func)
    async def my_wrapper(*args, **kwargs):
        retval = await func(*args, **kwargs)
        return retval if retval else breakpoint()
    return my_wrapper

@break_if_function_fails
async def function_to_test(retval):
    return retval

@mock.patch('builtins.breakpoint')
async def do_test(mock_breakpoint):
    print('Entering test')
    await function_to_test(True)
    mock_breakpoint.assert_not_called()
    await function_to_test(False)
    mock_breakpoint.assert_called()
    print('Exiting test')

asyncio.run(do_test())

完全相同的代码不会完成,但是触发3.7中的断点.

The exact same code does not finish but triggers the breakpoint in 3.7.

如果必须继续使用3.7,则仍然可以

If you must stay with 3.7, you can still do

@mock.patch('builtins.breakpoint')
async def do_test(mock_breakpoint):
    backup_breakpoint = builtins.breakpoint
    builtins.breakpoint = mock_breakpoint
    ...
    builtins.breakpoint = backup_breakpoint

但这显然很丑.

这篇关于如何修补内置的python 3 breakpoint()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆