pytest-django icon indicating copy to clipboard operation
pytest-django copied to clipboard

Doctest intermittently getting "Failed: Database access not allowed, use the "django_db" mark to enable"

Open scherrey opened this issue 9 years ago • 6 comments
trafficstars

Using Python 3.4, pytest-django 2.8.0, pytest 2.7.0, django 1.7.6, & Postgresql 9.3.9

When running my unit tests I have an intermittent error returning from my one and only Doctest. All my unit tests pass just fine and many use the database. Here's my test invocation: time py.test -n 7 -s -v --durations=10

273 Goals must be created within the context of a Portfolio. 274 >>> import pytest 275 >>> pytestmark = pytest.mark.django_db() 276 >>> from portfolio.models import Portfolio 277 >>> p, new = Portfolio.objects.get_or_create(name="Sample Goals") UNEXPECTED EXCEPTION: Database access not allowed, use the "django_db" mark to enable

Removing lines 274 & 275 have no impact.

scherrey avatar Dec 22 '15 18:12 scherrey

Sorry, doctests and pytest fixtures (which is used to get the database ready for use) does not really play well together. The error message is misleading, but doing database operations within a doctest is not supported by pytest-django.

doctests called from Django's test runner never cleaned up the database AFAIK, and starting from Django 1.6, Django's own test runner does not automatically run doctests, therefore it is not something that is likely to be directly supported by pytest-django, either.

I think your best bet is to rewrite your single doctest to an ordinary test case.

pelme avatar Dec 23 '15 17:12 pelme

@scherrey

i have found the following fixture allows db access in my doctests

@pytest.fixture
def db_doctest(request, _django_cursor_wrapper):
    from django.test import TestCase as django_case
    _django_cursor_wrapper.enable()
    request.addfinalizer(_django_cursor_wrapper.disable)
    case = django_case(methodName='__init__')
    case._pre_setup()
    request.addfinalizer(case._post_teardown)

@pelme i would be happy to create a PR if its useful to. I find doctests can be very useful as a form of testable documentation, as opposed to a replacement for unit testing

phlax avatar May 12 '16 10:05 phlax

@phlax Yes, I think it would be good to have, but should be covered by tests, of course. Thanks for digging into this and suggesting a fix!

blueyed avatar May 12 '16 21:05 blueyed

@phlax How do you use this fixture? I mean, what code goes where in the doctest file?

alanjds avatar May 09 '17 21:05 alanjds

@alanjds sorry it took 3 years to answer 8/ - just noticed the question when i was re-discovering the solution.

You can include fixtures in doctests with eg

>>> get_fixture('db_doctest')

but the above solution has also changed - this seems to be enough for the doctest fixture:

import pytest

@pytest.fixture
def db_doctest(db):
    pass

phlax avatar Jan 20 '18 12:01 phlax

As of July 2020, getfixture('db') at the top of your doctest works.

pandichef avatar Jul 14 '20 02:07 pandichef