python中breakpoint什么意思,如何修补内置的python 3 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

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')

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

module under test

#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

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?

解决方案

To solve, upgrade your project to 3.8!

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.

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())

The exact same code does not finish but triggers the breakpoint in 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

but this is obviously ugly.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值