22

Django では、単体テストで新しい N+1 クエリの問題をキャッチするために、作成する必要があるクエリの数をアサートすることがよくあります。

from django import db
from django.conf import settings
settings.DEBUG=True

class SendData(TestCase):
    def test_send(self):
        db.connection.queries = []
        event = Events.objects.all()[1:]
        s = str(event) # QuerySet is lazy, force retrieval
        self.assertEquals(len(db.connection.queries), 2)

echoSQLAlchemy では、エンジンにフラグを設定することで、STDOUT へのトレースが有効になります。

engine.echo=True

SQLAlchemy によって作成されたクエリの数をカウントするテストを作成する最良の方法は何ですか?

class SendData(TestCase):
    def test_send(self):
        event = session.query(Events).first()
        s = str(event)
        self.assertEquals( ... , 2)
4

4 に答える 4

14

SQLAlchemy Core Eventsを使用して、実行されたクエリを記録/追跡します (単体テストからアタッチして、実際のアプリケーションのパフォーマンスに影響を与えないようにすることができます:

event.listen(engine, "before_cursor_execute", catch_queries)

ここで、関数 を記述しますcatch_queries。方法は、テスト方法によって異なります。たとえば、テスト ステートメントで次の関数を定義できます。

def test_something(self):
    stmts = []
    def catch_queries(conn, cursor, statement, ...):
        stmts.append(statement)
    # Now attach it as a listener and work with the collected events after running your test

上記の方法は単なるインスピレーションです。拡張されたケースでは、各テストの後に空にするイベントのグローバル キャッシュが必要になる場合があります。その理由は、0.9 (現在の開発) より前は、イベント リスナーを削除する API がないためです。したがって、グローバル リストにアクセスする 1 つのグローバル リスナーを作成します。

于 2013-09-30T08:29:42.860 に答える
0

コンテキストを終了するときにイベントリスナーを削除する@omar-tarabai のソリューションのわずかに変更されたバージョン:

from sqlalchemy import event

class QueryCounter(object):
    """Context manager to count SQLALchemy queries."""

    def __init__(self, connection):
        self.connection = connection.engine
        self.count = 0

    def __enter__(self):
        event.listen(self.connection, "before_cursor_execute", self.callback)
        return self

    def __exit__(self, *args, **kwargs):
        event.remove(self.connection, "before_cursor_execute", self.callback)

    def callback(self, *args, **kwargs):
        self.count += 1

使用法:

with QueryCounter(session.connection()) as counter:
     session.query(XXX).all()
     session.query(YYY).all()

print(counter.count)  # 2
于 2022-03-03T13:11:45.963 に答える