django在运行测试时如何查看sql查询?
我的一个django应用程序单元测试失败django在运行测试时如何查看sql查询?,sql,django,oracle,unit-testing,django-testing,Sql,Django,Oracle,Unit Testing,Django Testing,我的一个django应用程序单元测试失败 DatabaseError: ORA-00942: table or view does not exist 我希望看到导致此错误的实际SQL查询。您知道如何实现这一点吗?到目前为止,我找到的最佳解决方案是django debugtoolbar提供的debugsqlshell自定义django管理命令。如果您想打印/记录测试中的所有SQL查询,请尝试如下子类化TestCase: from django.conf import settings from
DatabaseError: ORA-00942: table or view does not exist
我希望看到导致此错误的实际SQL查询。您知道如何实现这一点吗?到目前为止,我找到的最佳解决方案是django debugtoolbar提供的debugsqlshell自定义django管理命令。如果您想打印/记录测试中的所有SQL查询,请尝试如下子类化
TestCase
:
from django.conf import settings
from django.template import Template, Context
import sys
from django.db import connection
from django.test import TestCase
class LoggingTestCase(TestCase):
@staticmethod
def setUpClass():
# The test runner sets DEBUG to False. Set to True to enable SQL logging.
settings.DEBUG = True
super(LoggingTestCase, LoggingTestCase).setUpClass()
@staticmethod
def tearDownClass():
super(LoggingTestCase, LoggingTestCase).tearDownClass()
time = sum([float(q['time']) for q in connection.queries])
t = Template("{{count}} quer{{count|pluralize:\"y,ies\"}} in {{time}} seconds:\n\n{% for sql in sqllog %}[{{forloop.counter}}] {{sql.time}}s: {{sql.sql|safe}}{% if not forloop.last %}\n\n{% endif %}{% endfor %}")
print >> sys.stderr, t.render(Context({'sqllog': connection.queries, 'count': len(connection.queries), 'time': time}))
# Empty the query list between TestCases.
connection.queries = []
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'standard': {
'format': '%(asctime)s - %(levelname)s - %(name)s - %(message)s',
},
},
'handlers': {
'default': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'standard',
'stream': 'ext://sys.stdout',
},
},
'loggers': {
'django.db.backends': {
'level': 'DEBUG',
'handlers': ['default'],
'propagate': False,
},
}
}
然后使用
LoggingTestCase
而不是TestCase
作为测试中的基类。如果重写它,请记住调用这个tearDownClass
。这不是最干净的解决方案,但是如果您只是想快速地进行调试,而不需要安装额外的软件包,那么可以在django/db中查找execute()方法
对于Oracle我想它是在:
django/db/backends/oracle/base.py并查找:
def execute
对于PostgreSQL,它位于:
django/db/backends/postgresql\u psycopg2/base.py
在CursorWrapper中有一个execute()方法
两者都捕获IntegrityError和DatabaseError,您可以在其中添加一条打印语句
对于希望查看所有sql查询的ppl,请将print语句放在函数调用之后。您可以在设置中将控制台级别更改为DEBUG。它在Django 1.9上运行
LOGGING = {
...
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'simple'
},
}
...
}
您还可以执行以下操作来获取查询(例如,在测试中打印或评估查询) 其实你现在,所以我用
TestCase
可能也适用,请参见此处的差异
有关SQL输出的详细信息,请参阅。另一个选项是在测试中使用,如下所示:
从django.db导入连接
def记录器(执行、sql、参数、多个、上下文):
打印(sql、参数)
返回执行(sql、参数、多个、上下文)
类GizmoTest(测试用例):
def test_与_sql_日志记录(自):
使用connection.execute_包装器(记录器):
使用数据库()的代码
使用Django 2.2进行测试。另一个选项是使用
CaptureQueriesContext
(使用pytest
进行测试)
从django.db导入连接
从django.test.utils导入CaptureQueriesContext
def test_foo():
CaptureQueriesContext(连接)作为ctx时:
#运行SQL查询的代码
打印(ctx.captured\u查询)
资料来源:
pytest
和pytest django
只需为其创建一个夹具即可
@pytest.fixture
def debug_queries(db):
""" Because pytest run tests with DEBUG=False
the regular query logging will not work, use this fixture instead
"""
from django.db import connection
from django.test.utils import CaptureQueriesContext
with CaptureQueriesContext(connection):
yield connection
然后在你的测试中
@pytest.mark.django_db
def test__queries(debug_queries):
# run your queries here
当然,您的日志配置应该启用查询日志记录,如下所示:
from django.conf import settings
from django.template import Template, Context
import sys
from django.db import connection
from django.test import TestCase
class LoggingTestCase(TestCase):
@staticmethod
def setUpClass():
# The test runner sets DEBUG to False. Set to True to enable SQL logging.
settings.DEBUG = True
super(LoggingTestCase, LoggingTestCase).setUpClass()
@staticmethod
def tearDownClass():
super(LoggingTestCase, LoggingTestCase).tearDownClass()
time = sum([float(q['time']) for q in connection.queries])
t = Template("{{count}} quer{{count|pluralize:\"y,ies\"}} in {{time}} seconds:\n\n{% for sql in sqllog %}[{{forloop.counter}}] {{sql.time}}s: {{sql.sql|safe}}{% if not forloop.last %}\n\n{% endif %}{% endfor %}")
print >> sys.stderr, t.render(Context({'sqllog': connection.queries, 'count': len(connection.queries), 'time': time}))
# Empty the query list between TestCases.
connection.queries = []
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'standard': {
'format': '%(asctime)s - %(levelname)s - %(name)s - %(message)s',
},
},
'handlers': {
'default': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'standard',
'stream': 'ext://sys.stdout',
},
},
'loggers': {
'django.db.backends': {
'level': 'DEBUG',
'handlers': ['default'],
'propagate': False,
},
}
}
这就是对我有效的解决方案(Django 3.1): 来自django.test的
导入测试用例
类TestSomething(TestCase):
@覆盖\u设置(调试=真)
def测试(自我):
通过
def拆卸(自):
从django.db导入连接
对于connection.querys中的查询:
打印(f)✅ {query['sql']}\n“
这有帮助吗?不完全是。我不想在测试用例中包含“print connection.querys”,因为为了执行该行,我首先需要捕获一个异常。如果我发现这个异常,测试就会通过,这是不好的。重新引发此异常不是很优雅,我正在寻找更好的解决方案。另一件事是“打印”不适用于测试-至少对我来说…无论如何,您必须捕获异常,以便在出错时显示任何信息。我看不出任何与重新调用异常不一致的地方——只需单独使用
raise
关键字,它就会完整地通过堆栈跟踪。哦,实际上,我想还有另一种解决方案——您可以在调试级别登录,并配置日志记录器,以便在发生SQL查询时将所有SQL查询写入日志。请看,您也应该调用super setUpClass。如果不这样做,就会丢失一些东西,例如夹具加载。@bonbonbon good point,现已修复。如果你否决了,请考虑联合国的投票,看看:Django真的不允许你设置一些环境变量来打印所有的查询吗?你能详细说明如何使用<代码> Debug gSqsBase<代码>命令来运行测试吗?django Debugger的文档中没有解释这一点。@gogognome我认为mnowotka误解了这个问题。事实上,我刚刚知道他是TS,所以这里是-1表示错误的接受应答不起作用“出于性能原因,SQL日志记录仅在settings.DEBUG设置为True时启用,而不管安装的日志记录级别或处理程序如何。”SQL查询不会打印出来。这是最简单、最干净的答案,因为它可以让您捕获任意小部分代码的查询,如果您希望解决问题或优化查询,这正是您所需要的。