Один из моих модульных тестов приложения django не работает с
DatabaseError: ORA-00942: table or view does not exist
Я хотел бы увидеть реальный SQL-запрос, вызвавший эту ошибку. Вы знаете, как этого добиться?
Один из моих модульных тестов приложения django не работает с
DatabaseError: ORA-00942: table or view does not exist
Я хотел бы увидеть реальный SQL-запрос, вызвавший эту ошибку. Вы знаете, как этого добиться?
Если вы хотите распечатать / записать все запросы 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 = []
Затем используйте LoggingTestCase
вместо TestCase
в качестве базового класса в ваших тестах. Просто не забудьте называть это tearDownClass
, если вы его переопределите.
Вы также можете сделать следующее, чтобы получить запросы (а затем, например, распечатать его или оценить в своем тесте).
На самом деле вы в настоящее время не должны изменять django.conf.settings
, поэтому Я использую override_settings
.
from django.db import connection, reset_queries
from django.test import override_settings, TransactionTestCase
class TransactionTests(TransactionTestCase):
@override_settings(DEBUG=True)
def test_sql(self):
reset_queries()
try:
# Code that uses the ORM goes here
except Exception as e:
pass
self.assertEqual(connection.queries, [])
TestCase
также может подойти, см. Различия в этом ответе.
См. документация Django для получения подробной информации о выводе SQL.
Другой вариант - использовать CaptureQueriesContext
(проверено с pytest
).
from django.db import connection
from django.test.utils import CaptureQueriesContext
def test_foo():
with CaptureQueriesContext(connection) as ctx:
# code that runs SQL queries
print(ctx.captured_queries)
Источники:
Другой вариант - использовать connection.execute_wrapper()
в вашем проверить следующим образом:
from django.db import connection
def logger(execute, sql, params, many, context):
print(sql, params)
return execute(sql, params, many, context)
class GizmoTest(TestCase):
def test_with_sql_logging(self):
with connection.execute_wrapper(logger):
code_that_uses_database()
Протестировано с Django 2.2.
Лучшее решение, которое я нашел до сих пор, - это настраиваемая команда управления django debugsqlshell, предоставляемая django-debugtoolbar.
debugsqlshell
для запуска теста. Это не объясняется в документации django-debugtoolbar.
- person gogognome; 18.07.2019
Это не самое чистое решение, но если вы просто хотите быстро отладить без установки дополнительных пакетов, вы можете поискать метод execute () в django / db.
Для Oracle, я думаю, он находится в:
django / db / backends / oracle / base.py и найдите:
def execute
Для PostgreSQL он находится в:
django / db / backends / postgresql_psycopg2 / base.py
В CursorWrapper есть метод execute ().
Оба отлавливают IntegrityError и DatabaseError, вы можете добавить туда оператор печати.
Для пользователей, которые хотят видеть все запросы sql, поместите оператор печати сразу после вызова функции.
Вы можете изменить уровень консоли на DEBUG в настройках. Он работал на Django 1.9.
LOGGING = {
...
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'simple'
},
}
...
}
В случае 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
Конечно, ваша конфигурация ведения журнала должна разрешать регистрацию запросов, примерно так:
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):
from django.test import TestCase
class TestSomething(TestCase):
@override_settings(DEBUG=True)
def test_something(self):
pass
def tearDown(self):
from django.db import connection
for query in connection.queries:
print(f"✅ {query['sql']}\n")
raise
само по себе, и оно пройдет с неповрежденной трассировкой стека. - person Andrew Gorcester   schedule 31.10.2012