From 668d432d0a25ef68e101f2c6492dc4d75da931bd Mon Sep 17 00:00:00 2001 From: Moayad Mardini Date: Sun, 27 Jul 2014 11:12:39 +0300 Subject: [PATCH] Fixed #22491 -- documented how select_for_update() should be tested. Thanks Andreas Pelme for the report. --- docs/ref/models/querysets.txt | 23 +++++++++++++++++------ docs/topics/testing/tools.txt | 5 ++++- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt index 74fd813215..018c0f06fe 100644 --- a/docs/ref/models/querysets.txt +++ b/docs/ref/models/querysets.txt @@ -1415,17 +1415,18 @@ backends support ``select_for_update()``. However, MySQL has no support for the ``nowait`` argument. Obviously, users of external third-party backends should check with their backend's documentation for specifics in those cases. -Passing ``nowait=True`` to ``select_for_update`` using database backends that +Passing ``nowait=True`` to ``select_for_update()`` using database backends that do not support ``nowait``, such as MySQL, will cause a :exc:`~django.db.DatabaseError` to be raised. This is in order to prevent code unexpectedly blocking. -Evaluating a queryset with ``select_for_update`` in autocommit mode is -an error because the rows are then not locked. If allowed, this would -facilitate data corruption, and could easily be caused by calling, -outside of any transaction, code that expects to be run in one. +Evaluating a queryset with ``select_for_update()`` in autocommit mode is +a :exc:`~django.db.transaction.TransactionManagementError` error because the +rows are not locked in that case. If allowed, this would facilitate data +corruption and could easily be caused by calling code that expects to be run in +a transaction outside of one. -Using ``select_for_update`` on backends which do not support +Using ``select_for_update()`` on backends which do not support ``SELECT ... FOR UPDATE`` (such as SQLite) will have no effect. .. versionchanged:: 1.6.3 @@ -1433,6 +1434,16 @@ Using ``select_for_update`` on backends which do not support It is now an error to execute a query with ``select_for_update()`` in autocommit mode. With earlier releases in the 1.6 series it was a no-op. +.. warning:: + + Although ``select_for_update()`` normally fails in autocommit mode, since + :class:`~django.test.TestCase` automatically wraps each test in a + transaction, calling ``select_for_update()`` in a ``TestCase`` even outside + an :func:`~django.db.transaction.atomic()` block will (perhaps unexpectedly) + pass without raising a ``TransactionManagementError``. To properly test + ``select_for_update()`` you should use + :class:`~django.test.TransactionTestCase`. + raw ~~~ diff --git a/docs/topics/testing/tools.txt b/docs/topics/testing/tools.txt index ecff777263..9f671044a8 100644 --- a/docs/topics/testing/tools.txt +++ b/docs/topics/testing/tools.txt @@ -636,7 +636,10 @@ to test the effects of commit and rollback: While ``commit`` and ``rollback`` operations still *appear* to work when used in ``TestCase``, no actual commit or rollback will be performed by the database. This can cause your tests to pass or fail unexpectedly. Always - use ``TransactionTestCase`` when testing transactional behavior. + use ``TransactionTestCase`` when testing transactional behavior or any code + that can't normally be excuted in autocommit mode + (:meth:`~django.db.models.query.QuerySet.select_for_update()` is an + example). ``TransactionTestCase`` inherits from :class:`~django.test.SimpleTestCase`.