Python Django测试:请参阅创建错误响应的回溯
此模式来自django文档:Python Django测试:请参阅创建错误响应的回溯,python,django,unit-testing,http-response-codes,Python,Django,Unit Testing,Http Response Codes,此模式来自django文档: class SimpleTest(unittest.TestCase): def test_details(self): client = Client() response = client.get('/customer/details/') self.assertEqual(response.status_code, 200) 发件人: 如果测试失败,则错误消息没有多大帮助。例如,如果状态代码为302,则
class SimpleTest(unittest.TestCase):
def test_details(self):
client = Client()
response = client.get('/customer/details/')
self.assertEqual(response.status_code, 200)
发件人:
如果测试失败,则错误消息没有多大帮助。例如,如果状态代码为302,则我看到302!=200
现在的问题是:哪里创建了错误的HTTPResponse
我希望看到解释器的stacktrace,其中创建了错误的HTTPResponse对象
我阅读了文档,但是没有找到匹配的方法
更新
这是一个一般性问题:如果断言失败,如何立即查看所需信息?因为这些断言(self.assertEqual(response.status\u code,200)
)很常见,所以我不想开始调试
2016年更新
我又有了同样的想法,发现目前的答案不是100%容易。我写了一个新的答案,它有一个简单易用的解决方案(django web客户端的子类):
如果断言在没有调试的情况下失败,我如何看到回溯
如果断言失败,则没有回溯。client.get()
没有失败,它只是返回了一个与预期不同的响应
您可以使用来逐步完成client.get()
调用,并查看它返回意外响应的原因
如果断言在没有调试的情况下失败,我如何看到回溯
如果断言失败,则没有回溯。client.get()
没有失败,它只是返回了一个与预期不同的响应
您可以使用一个来逐步完成
client.get()
调用,并查看它返回意外响应的原因。我认为可以通过创建一个TestCase
子类(monkeypatchesdjango.http.response.HttpResponseBase)来实现
记录堆栈跟踪并将其存储在Response
对象上,然后编写AssertResponseCodeQuals(Response,status\u code=200)
方法,在出现故障时打印存储的堆栈跟踪,以显示响应的创建位置
实际上,我自己也可以使用一个解决方案,并可以考虑实现它
更新:
这里是一个v1实现,它可能需要一些改进(例如只打印堆栈跟踪的相关行)
我认为可以通过创建monkeypatchesdjango.http.response.HttpResponseBase.\uuu init\uuu()
记录堆栈跟踪并将其存储在response
对象上,然后编写AssertResponseCodeQuals(响应,状态\u code=200)来实现
方法,该方法在出现故障时打印存储的堆栈跟踪,以显示响应的创建位置
实际上,我自己也可以使用一个解决方案,并可以考虑实现它
更新:
这里是一个v1实现,它可能需要一些改进(例如只打印堆栈跟踪的相关行)
也许这对你有用:
class SimpleTest(unittest.TestCase):
@override_settings(DEBUG=True)
def test_details(self):
client = Client()
response = client.get('/customer/details/')
self.assertEqual(response.status_code, 200, response.content)
使用@override\u settings
使DEBUG=True
具有堆栈跟踪,就像您在DEBUG
模式下运行实例一样
其次,为了提供响应的内容,您需要打印它或使用日志记录
模块记录它,或者将它添加为断言
方法的消息。如果没有调试器,一旦您断言
,打印任何有用的东西(通常)就太晚了
您还可以配置日志记录
,并添加一个处理程序将消息保存在内存中,然后打印所有这些信息;无论是在自定义断言方法中还是在自定义测试运行程序中。这可能适用于您:
class SimpleTest(unittest.TestCase):
@override_settings(DEBUG=True)
def test_details(self):
client = Client()
response = client.get('/customer/details/')
self.assertEqual(response.status_code, 200, response.content)
使用@override\u settings
使DEBUG=True
具有堆栈跟踪,就像您在DEBUG
模式下运行实例一样
其次,为了提供响应的内容,您需要打印它或使用日志记录
模块记录它,或者将它添加为断言
方法的消息。如果没有调试器,一旦您断言
,打印任何有用的东西(通常)就太晚了
您还可以配置日志记录
,并添加一个处理程序将消息保存在内存中,然后打印所有这些信息;无论是在自定义断言方法中还是在自定义测试运行程序中。我受到@Fush提出的解决方案的启发,但我的代码使用的是assertRedirects,这是一种较长的方法,代码太多,无法复制而不会对自己感到不好
我花了一点时间弄清楚如何为每个断言调用super(),并得出了这个结论。我已经包括了两个示例assert方法——它们基本上都是相同的。也许一些聪明的灵魂可以想出一些元类魔法,对所有以“响应”为第一个参数的方法都能做到这一点
from bs4 import BeautifulSoup
from django.test.testcases import TestCase
class ResponseTracebackTestCase(TestCase):
def _display_response_traceback(self, e, content):
soup = BeautifulSoup(content)
assert False, u'\n\nOriginal Traceback:\n\n{}'.format(
soup.find("textarea", {"id": "traceback_area"}).text
)
def assertRedirects(self, response, *args, **kwargs):
try:
super(ResponseTracebackTestCase, self).assertRedirects(response, *args, **kwargs)
except Exception as e:
self._display_response_traceback(e, response.content)
def assertContains(self, response, *args, **kwargs):
try:
super(ResponseTracebackTestCase, self).assertContains(response, *args, **kwargs)
except Exception as e:
self._display_response_traceback(e, response.content)
我受到@Fush提出的解决方案的启发,但我的代码使用了assertRedirects,这是一种较长的方法,代码太多了,无法复制而不会对自己感到不好
我花了一点时间弄清楚如何为每个断言调用super(),并得出了这个结论。我已经包括了两个示例assert方法——它们基本上都是相同的。也许一些聪明的灵魂可以想出一些元类魔法,对所有以“响应”为第一个参数的方法都能做到这一点
from bs4 import BeautifulSoup
from django.test.testcases import TestCase
class ResponseTracebackTestCase(TestCase):
def _display_response_traceback(self, e, content):
soup = BeautifulSoup(content)
assert False, u'\n\nOriginal Traceback:\n\n{}'.format(
soup.find("textarea", {"id": "traceback_area"}).text
)
def assertRedirects(self, response, *args, **kwargs):
try:
super(ResponseTracebackTestCase, self).assertRedirects(response, *args, **kwargs)
except Exception as e:
self._display_response_traceback(e, response.content)
def assertContains(self, response, *args, **kwargs):
try:
super(ResponseTracebackTestCase, self).assertContains(response, *args, **kwargs)
except Exception as e:
self._display_response_traceback(e, response.content)
我对django web客户端进行了子类化,以获得以下结果:
用法
实施
结论
如果创建了状态代码错误的http响应,这将导致一个长异常。如果你不怕长时间的异常,你很快就会发现问题的根源。这就是我想要的,我很高兴
信用
这是基于这个问题的其他答案 我对django web客户端进行了子类化,以获得以下结果:
用法
实施
结论
如果http响应使用错误的sta,则会导致长时间异常
from django.test import Client
class MyClient(Client):
def generic(self, method, path, data='',
content_type='application/octet-stream', secure=False,
assert_status=None,
**extra):
if assert_status:
return self.assert_status(assert_status, super(MyClient, self).generic, method, path, data, content_type, secure, **extra)
return super(MyClient, self).generic(method, path, data, content_type, secure, **extra)
@classmethod
def assert_status(cls, status_code, method_pointer, *args, **kwargs):
assert hasattr(method_pointer, '__call__'), 'Method pointer needed, looks like the result of a method call: %r' % (method_pointer)
def new_init(self, *args, **kwargs):
orig_response_init(self, *args, **kwargs)
if not status_code == self.status_code:
raise HTTPResponseStatusCodeAssertionError('should=%s is=%s' % (status_code, self.status_code))
def reraise_exception(*args, **kwargs):
raise
with mock.patch('django.core.handlers.base.BaseHandler.handle_uncaught_exception', reraise_exception):
with mock.patch.object(HttpResponseBase, '__init__', new_init):
return method_pointer(*args, **kwargs)