簡體   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