Django 如何在单元测试的时候也打印 SQL 语句

发表于:2021-7-02 09:35

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:ponponon    来源:掘金

  如何输出 SQL 语句
  在项目的 settings.py 文件中添加如下内容就可以将一切对数据库的操作翻译为 SQL 语句,但是注意这个模式只有在 settings.py 中的 DEBUG 开关为 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',
          },
      }
  }
  在单元测试中输出 SQL 语句的需求
  上面的语句在做单元测试的时候就变得不好使!
  根本就不输出 SQL 语句!!!
  我一开始以为是上面代码中的 level 设置的不对,应该将 DEBUG 改为 生产,当然,答案并非如此!
  找寻答案
  为什么会有这个需求呢?其实还是为了调试代码方便嘛,但既然是调试代码,如果涉及数据库的操作却不输出 SQL 语句,就感觉是雾里看花、黑箱操作让人摸不着头脑!!!作为一名优秀的程序员怎么能允许这种事情发生呢?当然不可以!!!
  所以我去通读了 Django 官方文档中相关的内容
  编写并运行测试
  通过阅读改文档可知:做单元测试的时候会以生产模式运行,这就解释了为什么不输出 SQL 语句,因为我们的日志设置的级别是 DEBUG。
  无论配置文件中的 DEBUG 设置值是多少,所有的 Django 测试都以 DEBUG=False 运行。这是为了确保你的代码观察到的输出与生产环境下的输出一致。
  日志管理快速入门
  好的,找到了改进方向了,那就 level 改为生产模式就好了嘛!
  但是通过阅读文档发现只有:
  · DEBUG:排查故障时使用的低级别系统信息
  · INFO:一般的系统信息
  · WARNING:描述系统发生了一些小问题的信息
  · ERROR:描述系统发生了大问题的信息
  · CRITICAL:描述系统发生严重问题的信息
  这五种模式,最低就是 DEBUG,根本没有生产模式啊!!!
  定义测试运行器
  读完该篇文档,我懂了,之前想要修改 level 的想法是错误的,我们可以也应该通过自定义测试器 的方式来让单元测试也输出  SQL 语句!!!
  在根目录下面新建一个 testing 文件夹,然后在其中创建一个 testcases.py 文件,在其中写下如下的代码:
  from django.test.runner import DiscoverRunner
  class DebugDiscoverRunner(DiscoverRunner):
      def __init__(self, *args, **kwargs):
          super().__init__(debug_sql=True, verbosity=2)
  这段代码有几个关键点:
  · 继承 DiscoverRunner
  这个没什么好说的,默认就是 DiscoverRunner,所以我们继承他。
  · debug_sql=True, verbosity=2
  继承它不为别的,就像开启上面的两个参数
  testing 和 testcases.py 这些名字随意,只是我习惯这么放置和取名字,你随意!!!
  然后再 settings.py 文件中的任意位置添加下面的代码:
  TEST_RUNNER = 'testing.testrunner.DebugDiscoverRunner'
  这个时候你只需要再终端输入
  python manage.py test
  就会调用我们的 DebugDiscoverRunner 来做单元测试,执行 __init__.py 传递 debug_sql=True, verbosity=2 ,就会再控制台源源不断的打印 SQL 语句!!!
  一些细节
  你会发现 DebugDiscoverRunner 的 __init__.py 传递给 super().__init__(debug_sql=True, verbosity=2) 的参数没有了 *args, **kwargs
  ,为什么呢?
  因为会报错!!!
  如下:
  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/__init__.py", line 401, in execute_from_command_line
      utility.execute()
    File "/usr/local/lib/python3.6/dist-packages/django/core/management/__init__.py", 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.py", 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.py", 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'

  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号