preface
Do it yourself
Before in the sifu raised this question, but no one answered ah, that can only solve their own!
How does Django print SQL statements even when unit testing
Not only think no, stackOverflow but no one answered
How do I output SQL statements
Add the following to your project’s settings.py file to translate all database operations into SQL statements, but note that this mode only works if the DEBUG in settings.py is True!
LOGGING = {
'version': 1.'disable_existing_loggers': False.'handlers': {
'console': {'level':'DEBUG'.'class':'logging.StreamHandler',}},'loggers': {
'django.db.backends': {
'handlers': ['console'].'propagate': True.'level':'DEBUG',}}}Copy the code
Output requirements for SQL statements in unit tests
The above statement does not work well when doing unit tests!
No SQL statement output at all!!
At first, I thought the level setting in the above code was wrong, and I should change DEBUG to production. Of course, the answer is not so!
To find the answer
Why is there a need? In fact, it is for the convenience of debugging code, but since it is debugging code, if the operation of the database does not output SQL statements, it feels like a fog, black box operation makes people feel confused!! How can a good programmer allow this to happen? Of course not!!
So I went through the official Django documentation
-
Write and run tests
From reading the documentation, you can see that unit tests are run in production mode, which explains why SQL statements are not output because our log level is set to DEBUG
Regardless of the DEBUG setting in the configuration file, all Django tests are run with DEBUG=False. This is to ensure that the output observed by your code is consistent with the output in production.
-
Log management Quick Start
Ok, the direction of improvement has been found, so level should be changed to production mode.
But after reading the document, I found only:
DEBUG
: Indicates low-level system information used for troubleshootingINFO
: Indicates general system informationWARNING
: Describes minor problems that occur in the systemERROR
: Indicates that a major system problem occursCRITICAL
: Indicates the information about a serious system problem
Of these five modes, the lowest is DEBUG, there is no production mode at all!!
-
Define the test runner
After reading this document, I understand that the previous idea to modify level is wrong, we can and should customize the tester to make the unit test output SQL statements!!
Just do it!
To start
Create a new Testing folder under the root directory, then create a testcases.py file in it and write the following code:
from django.test.runner import DiscoverRunner
class DebugDiscoverRunner(DiscoverRunner) :
def __init__(self, *args, **kwargs) :
super().__init__(debug_sql=True, verbosity=2)
Copy the code
This code has several key points
-
Inheritance DiscoverRunner
There’s nothing to say about that, the default is DiscoverRunner, so we inherit it, right
-
debug_sql=True, verbosity=2
Inherit it for nothing, just like turning on the two arguments above
The names of testing and testcases.py are optional, but I am used to placing and naming them this way, you are optional!!
Then add the following code anywhere in settings.py:
TEST_RUNNER = 'testing.testrunner.DebugDiscoverRunner'
Copy the code
At this point, all you need is terminal input
python manage.py test
Copy the code
We will call our DebugDiscoverRunner to do unit test, execute __init__.py to pass debug_SQL =True, verbosity=2, and then the console will print SQL statements continuously!!
Some of the details
You will notice that the __init__.py of the DebugDiscoverRunner passed to super().__init__(debug_SQL =True, Verbosity =2) arguments are missing *args, **kwargs
Why?
Because of the error!!
As follows:
vagrant@vagrant:/vagrant$ python manage.py test comments
Traceback (most recent call last):
File "manage.py", line 22, in <module>
main()
File "manage.py", line 18, in main
execute_from_command_line(sys.argv)
File "/ usr/local/lib/python3.6 / dist - packages/django/core/management/set p y", line 401, in execute_from_command_line
utility.execute()
File "/ usr/local/lib/python3.6 / dist - packages/django/core/management/set p y", line 395, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/ usr/local/lib/python3.6 / dist - packages/django/core/management/commands/test. The p y", line 23, in run_from_argv
super().run_from_argv(argv)
File "/ usr/local/lib/python3.6 / dist - packages/django/core/management/base. Py." ", line 330, in run_from_argv
self.execute(*args, **cmd_options)
File "/ usr/local/lib/python3.6 / dist - packages/django/core/management/base. Py." ", line 371, in execute
output = self.handle(*args, **options)
File "/ usr/local/lib/python3.6 / dist - packages/django/core/management/commands/test. The p y", line 52, in handle
test_runner = TestRunner(**options)
File "/vagrant/testing/testrunner.py", line 6, in __init__
super(DebugDiscoverRunner, self).__init__(debug_sql=True, verbosity=2, *args, **kwargs)
TypeError: __init__() got multiple values for keyword argument 'verbosity'
Copy the code
Reference article: Django: DiscoverRunner override throws errors
Reference to reference, but this person’s handling is not good
So we got rid of *args, **kwargs