#25406: _create_test_db hides errors like 'source database "template1" is being
accessed by other users' with --keepdb
----------------------------------------------+--------------------
     Reporter:  blueyed                       |      Owner:  nobody
         Type:  Bug                           |     Status:  new
    Component:  Database layer (models, ORM)  |    Version:  master
     Severity:  Normal                        |   Keywords:
 Triage Stage:  Unreviewed                    |  Has patch:  0
Easy pickings:  0                             |      UI/UX:  0
----------------------------------------------+--------------------
 The _create_test_db method will hide errors like 'source database
 "template1" is being accessed by other users', and will assume that the
 test database exists already.

 {{{
 > …/pyenv/project/lib/python3.4/site-
 packages/psycopg2/__init__.py(165)connect()
     164     import ipdb; ipdb.set_trace()
 --> 165     conn = _connect(dsn, connection_factory=connection_factory,
 async=async)
     166     if cursor_factory is not None:

 ipdb> c
 source database "template1" is being accessed by other users
 DETAIL:  There are 3 other sessions using the database.

 > …/pyenv/project/lib/python3.4/site-
 packages/django/db/backends/base/creation.py(458)_create_test_db()
     457                 # just return and skip it all.
 --> 458                 if keepdb:
     459                     return test_database_name
 }}}
 Source reference:
 
https://github.com/blueyed/django/blob/9e530b08d5858d7063d081b60ec86d24173e4df5/django/db/backends/base/creation.py#L146-L165

 This will then result in an error when trying to connect to it, because it
 has not been created:

   psycopg2.OperationalError: FATAL:  database "test_project" does not
 exist


 But instead the initial error should be displayed:

   source database "template1" is being accessed by other users
   DETAIL:  There are 3 other sessions using the database.


 To reproduce this:

  - connect to the "template1" database
  - run Django tests

 I think the SQL could use `CREATE DATABASE IF NOT EXISTS` (in case `IF NOT
 EXISTS`) is supported by all backends (maybe that needs to be subclassed
 then), and then would not assume that an Exception can be ignored with
 `keepdb`.

 An even better way would be to check if it exists, instead of trying to
 create it.

 With pytest-django we're using the following code:
 {{{
 def test_database_exists_from_previous_run(connection):
     # Try to open a cursor to the test database
     test_db_name = connection.creation._get_test_db_name()

     # When using a real SQLite backend (via TEST_NAME), check if the file
     # exists, because it gets created automatically.
     if connection.settings_dict['ENGINE'] == 'django.db.backends.sqlite3':
         if not os.path.exists(test_db_name):
             return False

     orig_db_name = connection.settings_dict['NAME']
     connection.settings_dict['NAME'] = test_db_name

     # With SQLite memory databases the db never exists.
     if connection.settings_dict['NAME'] == ':memory:':
         return False

     try:
         connection.cursor()
         return True
     except Exception:  # TODO: Be more discerning but still DB agnostic.
         return False
     finally:
         connection.close()
         connection.settings_dict['NAME'] = orig_db_name
 }}}
 (Source:
 
https://github.com/blueyed/pytest_django/blob/93fca47feea39016dd93e657a9328450e9b6e891/pytest_django/db_reuse.py#L11-L35)

--
Ticket URL: <https://code.djangoproject.com/ticket/25406>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/050.3041a1731d7fda8c50e1ca41e08396fd%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to