[Django]-Why django checks whether settings.DATABASE_NAME db actually exists for running testcases?

3👍

Neat question… you know, this had never occurred to me. The short answer is that Django itself doesn’t need to verify that the DATABASE_NAME actually exists, but it does need to connect to the database in order to create the test database. Most databases accept (and some require) the DATABASE_NAME in order to formulate the connection string; often this is because the database name to which you’re connecting contributes to the permissions for your connection session.

Because the test database doesn’t exist yet, django has to first connect using the normal settings.DATABASE_NAME in order to create the test database.

So, it works like this:

  • Django’s test runner passes off to the backend-specific database handler
  • The backend-specific database handler has a function called create_test_db which will use the normal settings to connect to the database. It does this using a plain cursor = self.connection.cursor() command, which obviously uses the normal settings values because that’s all it knows to be in existence at this point.
  • Once connected to the database, the backend-specific handler will issue a CREATE DATABASE command with the name of the new test database.
  • The backend-specific handler closes the connection, then returns to the test runner, which swaps the normal settings.DATABASE_NAME for the test_database_name
  • The test will then run as normal. All subsequent calls to connection.cursor() will use the normal settings module, but now that module has the swapped out database name
  • At the end, the test runner restores the old database name after calling the backend-specific handler’s destroy_test_db function.

If you’re interested, the relevant code for the main part is in django.db.backends.creation. Have a look at the _create_test_db function.

I suppose that it would be possible for the Django designers to make exceptions on a db-by-db basis since not every DB needs the current database name in the connection string, but that would require a bit of refactoring. Right now, the create_test_db function is actually in one of the backend base classes, and most actual backend handlers don’t override it, so there’s be a fair amount of code to push downstream and to duplicate in each backend.

Leave a comment