Python 如何在测试期间禁用try/except块?
我编写了一个cronjob,它遍历帐户列表并为它们执行一些web调用(如下所示): 因为这个作业是由heroku one每10分钟运行一次,所以我不希望整个作业因为一个帐户出现问题而失败(这种情况经常发生)。我在这里放了一个try-catch子句,以便该任务是“容错的” 但是,我注意到,当我进行测试时,这个try/catch块给我带来了一些隐秘的问题,因为即使出现了一些严重错误,任务仍然可以继续执行 在测试期间禁用try/except块的最佳方法是什么 我已经考虑过如何像这样直接实现代码:Python 如何在测试期间禁用try/except块?,python,testing,Python,Testing,我编写了一个cronjob,它遍历帐户列表并为它们执行一些web调用(如下所示): 因为这个作业是由heroku one每10分钟运行一次,所以我不希望整个作业因为一个帐户出现问题而失败(这种情况经常发生)。我在这里放了一个try-catch子句,以便该任务是“容错的” 但是,我注意到,当我进行测试时,这个try/catch块给我带来了一些隐秘的问题,因为即使出现了一些严重错误,任务仍然可以继续执行 在测试期间禁用try/except块的最佳方法是什么 我已经考虑过如何像这样直接实现代码: fo
for account in self.ActiveAccountFactory():
self.logger.debug('Updating %s', account.login)
self.update_account_from_fb(account)
self.check_balances()
self.check_rois()
self.logger.exception(traceback.format_exc())
在我的测试用例中,这使得我的测试非常笨拙,因为我正在复制大量代码
我该怎么办
try…除了
块在测试时比较困难,因为它们捕获并试图处理您真正希望看到的错误。你已经发现了。在测试过程中
except Exception as e:
(不要使用异常,e
,它不向前兼容)替换在您的环境中不太可能发生的异常类型,例如
except AssertionError as e:
文本编辑器将为您执行此操作(然后将其反转),只需单击几下鼠标。您可以通过添加
\u testing=False
参数使callables test感知。在测试时,使用该代码在callable for中编写备用路径。然后从测试文件调用时,pass _testing=True
对于这个问题中出现的情况,将if\u testing:raise
放在异常主体中会“uncatch”异常
调节模块级别代码是骗子。为了在包pack
中测试模块mod
时获得特殊行为,我将
_testing = False # in `pack.__init__`
from pack import _testing # in pack.mod
然后test\u mod
import pack
pack._testing = True
from pack import mod
首先:不要使用
Exception
吞咽所有异常。这是个糟糕的设计。所以别说了
这样一来:
您可以做的一件事是为logger.exception
方法设置monkeypatch。然后,您可以根据是否调用该测试、它是创建模拟记录器、单独的测试记录器,还是在发生某些异常时停止测试的自定义测试记录器类,以您认为合适的方式处理该测试。您甚至可以选择通过引发错误立即结束测试
下面是一个使用的示例。我喜欢pytest
这样做,因为他们已经有了一个预定义的fixture设置,不需要样板代码。但是,也有其他方法可以做到这一点(例如,将其用作的一部分)
我会给你的班级打电话SomeClass
。我们将要做的是创建一个补丁版本的SomeClass
对象作为固定装置。补丁版本将不会登录到记录器;相反,它将有一个模拟记录器。记录器发生的任何情况都将记录在模拟记录器中,以便稍后检查
import pytest
import unittest.mock as mock # import mock for Python 2
@pytest.fixture
def SomeClassObj_with_patched_logger(monkeypatch):
##### SETUP PHASE ####
# create a basic mock logger:
mock_logger = mock.Mock(spec=LoggerClass)
# patch the 'logger' attribute so that when it is called on
# 'some_class_instance' (which is bound to 'self' in the method)
# things are re-routed to mock_logger
monkeypatch.setattr('some_class_instance.logger', mock_logger)
# now create class instance you will test with the same name
# as the patched object
some_class_instance = SomeClass()
# the class object you created will now be patched
# we can now send that patched object to any test we want
# using the standard pytest fixture way of doing things
yield some_class_instance
###### TEARDOWN PHASE #######
# after all tests have been run, we can inspect what happened to
# the mock logger like so:
print('\n#### ', mock_logger.method_calls)
如果模拟记录器的方法调用中出现call.exception
,则您知道该方法已被调用。你也可以用很多其他的方法来处理这个问题,这只是其中之一
如果您使用的是logging
模块,LoggerClass
应该是logging.Logger
。或者,您可以只执行mock\u logger=mock.mock()
。或者,您可以创建自己的自定义测试记录器类,该类在调用其exception
方法时引发异常。天空是极限
在任何测试中使用修补对象,如:
def test_something(SomeClassObj_with_patched_logger):
# no need to do the line below really, just getting
# a shorter variable name
my_obj = SomeClassObj_with_patched_logger
#### DO STUFF WITH my_obj #####
如果您不熟悉
pytest
,请参阅以获取更深入的信息 除例外情况外,不要使用毯子。将适当的异常处理放在代码中正确的位置。在except
块中添加一个简单的raise
,以重新引发原始异常。
def test_something(SomeClassObj_with_patched_logger):
# no need to do the line below really, just getting
# a shorter variable name
my_obj = SomeClassObj_with_patched_logger
#### DO STUFF WITH my_obj #####