pytest-dev / pytest-django

A Django plugin for pytest.
https://pytest-django.readthedocs.io/
Other
1.39k stars 343 forks source link

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

Open feuloren opened 8 years ago

feuloren commented 8 years ago

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.

valignatev commented 8 years ago

I've got same issue simply by simply running my old tests with pytest runner.

george-silva commented 6 years ago

same issue here with a simple test:

class TestFeatureViewSet():

    def test_get_dataset_without_dataset_pk_raises_404(self, mocker):
        viewset = FeatureViewSet()
        viewset.kwargs = {
            'dataset_pk': 1
        }
        with pytest.raises(exceptions.NotFound):
            viewset.get_dataset()

    def test_get_dataset_calls_dataset_manager(self, mocker):
        get_call = mocker.patch.object(
            Dataset.objects,
            'get',
            return_value='foo'
        )
        viewset = FeatureViewSet()
        viewset.kwargs = {
            'dataset_pk': 1
        }
        dataset = viewset.get_dataset()
        assert get_call.called_with(dataset_pk=1)
        assert dataset is not None

    @pytest.mark.django_db(transactional=True)
    def test_get_dataset_without_dataset_pk_raises_404t_existing_dataset(self):
        dataset = Dataset.objects.all()

This fails with transactional=True and without.

blueyed commented 6 years ago

@george-silva How does it fail? With "Database access not allowed, use the "django_db" mark to enable it."?

Can you provide an example that can be run standalone (in pytest-django's test suite)?

meteozond commented 6 years ago

Getting the same issue when working with db within the post_migrate receiver.