ユーティリティ関数によって実行されたクエリの数を調べようとしています。この関数の単体テストを作成しましたが、関数は正常に機能しています。私がやりたいのは、関数によって実行されたSQLクエリの数を追跡して、リファクタリング後に改善があったかどうかを確認できるようにすることです。
def do_something_in_the_database():
# Does something in the database
# return result
class DoSomethingTests(Django.test.TestCase):
def test_function_returns_correct_values(self):
self.assertEqual(n, <number of SQL queries executed>)
編集:これには保留中のDjango 機能リクエスト があることがわかりました。しかし、チケットはまだ開いています。それまでの間、これを回避する別の方法があります?
Django 1.3なので、この目的のために正確に利用できる assertNumQueries があります。
Vinayの応答は正しいですが、マイナーな追加が1つあります。
Djangoの単体テストフレームワークは、実行時にDEBUGを実際にFalseに設定するため、settings.py
に何があっても、デバッグモードを再度有効にしない限り、単体テストのconnection.queries
には何も入力されません。 Djangoドキュメントは この理由 を次のように説明しています:
構成ファイルのDEBUG設定の値に関係なく、すべてのDjangoテストはDEBUG = Falseで実行されます。これは、コードの観察された出力が本番環境で見られるものと一致することを確認するためです。設定。
デバッグを有効にしてもテストに影響がないことが確実な場合(DBヒットを具体的にテストしている場合など)、解決策は、単体テストでデバッグを一時的に再度有効にしてから設定することです。後で戻る:
def test_myself(self):
from Django.conf import settings
from Django.db import connection
settings.DEBUG = True
connection.queries = []
# Test code as normal
self.assert_(connection.queries)
settings.DEBUG = False
pytest
を使用している場合、pytest-Django
has Django_assert_num_queries この目的のためのフィクスチャ:
def test_queries(Django_assert_num_queries):
with Django_assert_num_queries(3):
Item.objects.create('foo')
Item.objects.create('bar')
Item.objects.create('baz')
settings.py
でDEBUG
をTrueに設定している場合(おそらくテスト環境ではそうです)、テストで実行されたクエリを次のようにカウントできます。
from Django.db import connection
class DoSomethingTests(Django.test.TestCase):
def test_something_or_other(self):
num_queries_old = len(connection.queries)
do_something_in_the_database()
num_queries_new = len(connection.queries)
self.assertEqual(n, num_queries_new - num_queries_old)
最新のDjango(> = 1.8)では十分に文書化されています(1.7でも文書化されています) ここ 、メソッドreset_queriesがありますconnection.queries = []を割り当てる代わりに、実際にエラーが発生します。Django> = 1.8で機能するようなものです。
class QueriesTests(Django.test.TestCase):
def test_queries(self):
from Django.conf import settings
from Django.db import connection, reset_queries
try:
settings.DEBUG = True
# [... your ORM code ...]
self.assertEquals(len(connection.queries), num_of_expected_queries)
finally:
settings.DEBUG = False
reset_queries()
また、setUp/tearDownでクエリをリセットして、finally句で行うのではなく、テストごとにクエリがリセットされるようにすることも検討できますが、この方法はより明示的です(ただし、より冗長です)。または、を使用できます。 )reset_queriesは、0から数えてクエリを評価するために必要な回数だけtry句に入力します。
TestCase( assertNumQueries を使用)を使用したくない場合、または設定をDEBUG = Trueに変更したくない場合は、コンテキストマネージャーCaptureQueriesContext( assertNumQueries usingと同じ)を使用できます。
from Django.db import ConnectionHandler
from Django.test.utils import CaptureQueriesContext
DB_NAME = "default" # name of db configured in settings you want to use - "default" is standard
connection = ConnectionHandler()[DB_NAME]
with CaptureQueriesContext(connection) as context:
... # do your thing
num_queries = context.initial_queries - context.final_queries
assert num_queries == expected_num_queries