djangoでN+1queryのテストを手軽に済ませたい場合にはassertNumQueriesが便利
django1.7移行では assertNumQueries が失敗時にcaptureしたqueryの結果を出力してくれる様になりました。
なので以下のようなコードを書いてあげれば、withで囲った部分で発行されたDBのqueryが分かるようになります。
from django.test import TestCase
class Test(TestCase):
def _callFUT(self):
Model(name="foo").save()
return Model.objects.count()
def test_it(self):
with self.assertNumQueries(3):
self.assertEqual(self._callFUT(), 1)
例えば上のコードでは self._callFUT()
内で実行されたqueryの数を調べる事ができます。
本来は2件なのですが assertNumQueries()
に3を指定してわざと失敗させています。
実行結果
Creating test database for alias 'default'...
F
======================================================================
FAIL: test_it (__main__.Test)
----------------------------------------------------------------------
Traceback (most recent call last):
File "qr_34141zLt.py", line 46, in test_it
self.assertEqual(self._callFUT(), 1)
File "/home/podhmo/vboxshare/venvs/django/lib/python3.3/site-packages/django/test/testcases.py", line 90, in __exit__
query['sql'] for query in self.captured_queries
AssertionError: 2 != 3 : 2 queries executed, 3 expected
Captured queries were:
QUERY = 'INSERT INTO "model" ("name") VALUES (%s)' - PARAMS = ('foo',)
QUERY = 'SELECT COUNT(*) AS "__count" FROM "model"' - PARAMS = ()
----------------------------------------------------------------------
Ran 1 test in 0.005s
FAILED (failures=1)
Destroying test database for alias 'default'...
発行されたqueryが分かるようになります。
test以外で特定の範囲内で発行されたqueryを知りたい場合
django.test.utils.CaptureQueriesContext
が使えるかもしれません。
以下の様な感じでがんばってください
from django.test.utils import CaptureQueriesContext
from django.db import connections
with CaptureQueriesContext(connections["default"]):
do_something()
Wrote by PileMd