pytest-dev / pytest-dev/pytest-django

can't get django_db(transaction=True) to work

Open
#319 4 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
1.5k
Forks
367
PR merge metrics
No merged PRs in 30d

Description

I am trying to test a view that uses a transaction but the test fails with "Failed: Database access not allowed, use the "django_db" mark to enable it."
Here is my test code

import pytest

@pytest.mark.django_db(transaction=True)
def test_udpate_state_invalid(admin_client):
    initial_state_updates = StateUpdate.objects.count()
    r = admin_client.post('/admin/core/update_state/', {})
    assert r.status_code == 400
    assert StateUpdate.objects.count() == initial_state_updates

Here is the full output:

=============================================================================== test session starts ===============================================================================
platform linux -- Python 3.4.4, pytest-2.8.7, py-1.4.31, pluggy-0.3.1
django settings: myapp.settings (from command line option)
rootdir: /code, inifile: 
plugins: django-2.9.1
collected 1 items 

myapp/core/test_simple.py FE

===================================================================================== ERRORS ======================================================================================
_________________________________________________________________ ERROR at teardown of test_udpate_state_invalid __________________________________________________________________

self = <django.test.testcases.TransactionTestCase testMethod=__init__>

    def _post_teardown(self):
        """Performs any post-test things. This includes:

            * Flushing the contents of the database, to leave a clean slate. If
              the class has an 'available_apps' attribute, post_migrate isn't fired.
            * Force-closing the connection, so the next test gets a clean cursor.
            """
        try:
>           self._fixture_teardown()

/usr/local/lib/python3.4/site-packages/django/test/testcases.py:919: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/local/lib/python3.4/site-packages/django/test/testcases.py:955: in _fixture_teardown
    inhibit_post_migrate=inhibit_post_migrate)
/usr/local/lib/python3.4/site-packages/django/core/management/__init__.py:119: in call_command
    return command.execute(*args, **defaults)
/usr/local/lib/python3.4/site-packages/django/core/management/base.py:399: in execute
    output = self.handle(*args, **options)
/usr/local/lib/python3.4/site-packages/django/core/management/commands/flush.py:49: in handle
    allow_cascade=allow_cascade)
/usr/local/lib/python3.4/site-packages/django/core/management/sql.py:15: in sql_flush
    tables = connection.introspection.django_table_names(only_existing=True, include_views=False)
/usr/local/lib/python3.4/site-packages/django/db/backends/base/introspection.py:86: in django_table_names
    existing_tables = self.table_names(include_views=include_views)
/usr/local/lib/python3.4/site-packages/django/db/backends/base/introspection.py:56: in table_names
    with self.connection.cursor() as cursor:
/usr/local/lib/python3.4/site-packages/django/db/backends/base/base.py:233: in cursor
    cursor = self.make_cursor(self._cursor())
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <django.db.backends.postgresql.base.DatabaseWrapper object at 0x7f4d706cd240>, cursor = <cursor object at 0x7f4d6d4a2b88; closed: 0>

    def make_cursor(self, cursor):
        """
            Creates a cursor without debug logging.
            """
>       return utils.CursorWrapper(cursor, self)
E       Failed: Database access not allowed, use the "django_db" mark to enable it.

/usr/local/lib/python3.4/site-packages/django/db/backends/base/base.py:552: Failed
==================================================================================== FAILURES =====================================================================================
____________________________________________________________________________ test_udpate_state_invalid ____________________________________________________________________________

admin_client = <django.test.client.Client object at 0x7f4d6d042630>

    @pytest.mark.django_db(transaction=True)
    def test_udpate_state_invalid(admin_client):
        initial_state_updates = StateUpdate.objects.count()
>       r = admin_client.post('/admin/core/update_state/', {})

mushu/core/test_simple.py:8: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/local/lib/python3.4/site-packages/django/test/client.py:515: in post
    secure=secure, **extra)
/usr/local/lib/python3.4/site-packages/django/test/client.py:314: in post
    secure=secure, **extra)
/usr/local/lib/python3.4/site-packages/django/test/client.py:380: in generic
    return self.request(**r)
/usr/local/lib/python3.4/site-packages/django/test/client.py:467: in request
    six.reraise(*exc_info)
/usr/local/lib/python3.4/site-packages/django/utils/six.py:686: in reraise
    raise value
/usr/local/lib/python3.4/site-packages/django/core/handlers/base.py:149: in get_response
    response = self.process_exception_by_middleware(e, request)
/usr/local/lib/python3.4/site-packages/django/core/handlers/base.py:147: in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
/usr/local/lib/python3.4/site-packages/django/utils/decorators.py:149: in _wrapped_view
    response = view_func(request, *args, **kwargs)
/usr/local/lib/python3.4/site-packages/django/views/decorators/cache.py:57: in _wrapped_view_func
    response = view_func(request, *args, **kwargs)
/usr/local/lib/python3.4/site-packages/django/contrib/admin/sites.py:244: in inner
    return view(request, *args, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

request = <WSGIRequest: POST '/admin/core/update_state/'>

    def update_state_process(request):
>       with transaction.atomic:
E       AttributeError: __exit__

mushu/core/state_update.py:82: AttributeError
======================================================================== 1 failed, 1 error in 3.58 seconds ========================================================================

I'm using django 1.9, pytest 2.8 and postgresql 9.5
Do you know what the problem is ? I made sure to follow the documentation.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the failing test in myapp/core/test_simple.py and the transaction usage at mushu/core/state_update.py:82. Reproduce the failure with the reported Django, pytest, PostgreSQL, and pytest-django versions, then determine whether the database-access error is caused by the test setup or the application transaction call. Done means the test completes without the reported failure and teardown error.

Written by the indexing model from the issue text.

Assessment

Tech stack
django, postgresql, python
Domain
backend, databases, testing-qa
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.