繁体   English   中英

如何在 Django 中测试 postgres statement_timeout

[英]How to test postgres statement_timeout in django

我在我的 Django 服务中为 postgres 数据库添加了连接和语句超时。 所以相关的 django 设置看起来像;

_CONN_TIMEOUT = 5
_STATEMENT_TIMEOUT = 3000 # millisecond
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.postgresql",
        "NAME": "some_database",
        # ...,
        "OPTIONS": {
            "connect_timeout": _CONN_TIMEOUT,
            "options": "-c statement_timeout={0}ms".format(_STATEMENT_TIMEOUT),
        },
    }
}

然后,我正在编写这样的测试;

class DbTimeoutTest(TestCase):
    def test_db_statement_timeout(self):
        """
        test carrying out an SQL query that takes longer than the configured
        postgres `statement_timeout` value
        """
        # set statement_timeout to 1 millisecond
        mock_s_timeout = 1
        with self.settings(_CONN_TIMEOUT=5, _STATEMENT_TIMEOUT=mock_s_timeout):
            self.assertEqual(
                settings.DATABASES["default"]["OPTIONS"]["options"],
                "-c statement_timeout={0}ms".format(mock_s_timeout),
            )
            Book.objects.create(name="Hello")

但是,该测试不起作用。

  • assert self.assertEqual没有通过,这意味着设置覆盖不起作用。
  • 我希望Book.objects.create语句因超时而失败,但事实并非如此。

所以问题;

  1. 我如何测试 postgres statement_timeout?(能够测试连接超时也是一个加分项)
  2. 如何捕获代码中的语句超时错误?

看一下 django 项目的测试用例

他们将超时设置为 1ms 并assertRaises(OperationalError)

完整代码:

def test_statement_timeout(self):
    databases = copy.deepcopy(settings.DATABASES)
    # Set timeout to 1ms and execute a 1s query.
    databases[DEFAULT_DB_ALIAS]['STATEMENT_TIMEOUT'] = 1
    new_connections = ConnectionHandler(databases)
    new_connection = new_connections[DEFAULT_DB_ALIAS]
    try:
        with new_connection.cursor() as cursor:
            with self.assertRaises(OperationalError):
                cursor.execute("SELECT pg_sleep(1)")
    finally:
        new_connection.close()

这就是我最终要做的;

在您的settings.py文件中:

CONNECTION_TIMEOUT = 5 # seconds
STATEMENT_TIMEOUT = 3000 # milliseconds
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.postgresql",
        "NAME": "some_database",
        # ...,
        "OPTIONS": {
            "connect_timeout": CONNECTION_TIMEOUT,
            "options": "-c statement_timeout={0}ms".format(STATEMENT_TIMEOUT),
        },
    }
}

在您的test_database.py文件中:

from django.conf import settings
from django.test import TestCase
from django.db import connection
from django.db.utils import OperationalError


class DatabaseTest(TestCase):
    def test_timeout(self):
        statement_timeout_seconds = settings.STATEMENT_TIMEOUT / 1000
        cursor = connection.cursor()
        with self.assertRaises(OperationalError) as raised_exception:
            cursor.execute(
                # sql query that takes 3 times longer than the configured statement_timeout
                "SELECT pg_sleep({0})".format((statement_timeout_seconds) * 3)
            )
            cursor.fetchall()
        cursor.close()

        self.assertIn(
            "canceling statement due to statement timeout", str(raised_exception.exception)
        )

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM