Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
django在运行测试时如何查看sql查询?_Sql_Django_Oracle_Unit Testing_Django Testing - Fatal编程技术网

django在运行测试时如何查看sql查询?

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

我的一个django应用程序单元测试失败

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查询不会打印出来。这是最简单、最干净的答案,因为它可以让您捕获任意小部分代码的查询,如果您希望解决问题或优化查询,这正是您所需要的。