LoginSignup
8
7

More than 5 years have passed since last update.

djangoでN+1queryのテストを手軽に済ませたい場合にはassertNumQueriesが便利

Last updated at Posted at 2016-04-16

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

参考

8
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
7