Jim
Jim

Reputation: 14270

Why isn't Django creating blank a database during test?

When I run a unit test, Django 1.6 doesn't seem to be creating a blank database to test from and I don't understand why. The Django docs say that Django doesn't use your production database but instead creates a separate, blank database for testing. However, when I debug my test 'test_get_user_ids' and run the command 'UserProxy.objects.all()', I see all the users in my production database. Now I understand that this particular test will fail due to the fact that I'm not saving each UserProxy instance to the database and am therefore not generating ids to test for. But the fact remains that when I query UserProxy, I can still see all the users in my production database which I would expect to be empty. Why is this happening?

BTW, I'm running the test using nosetest: "nosetests -s apps.profile.tests.model_tests.py:UserProxyUT"

Thanks.

# settings.py
DATABASES = {
    'default': {
        # Enable PostGIS extensions
        'ENGINE'  : 'django.contrib.gis.db.backends.postgis',
        'NAME'    : 'myapp',
        'USER'    : 'myappuser',
        'PASSWORD': 'myapppw',
        'HOST'    : 'localhost',
        'PORT'    : '',
    }
}

# apps/profile/models.py
from django.contrib.auth.models import User

class UserProxy(User):
    """Proxy for the auth.models User class."""
    class Meta:
        proxy = True

    @staticmethod
        def get_user_ids(usernames):
            """Return the user ID of each username in a list."""
            user_ids = []
            for name in usernames:
                try:
                    u = User.objects.get(username__exact=name)
                    user_ids.append(u.id)
                except ObjectDoesNotExist:
                    logger.error("We were unable to find '%s' in a list of usernames." % name)
            return user_ids

# apps/profile/tests/model_tests.py
from django.contrib.auth.models import User
from django.test import TestCase
from apps.profile.models import UserProxy

class UserProxyUT(TestCase):
    def test_get_user_ids(self):
        debug()   
        # UserProxy.objects.all() shows usernames from my production database!
        u1 = UserProxy(username='user1')
        u2 = UserProxy(username='user2')
        u3 = UserProxy(username='user3')
        usernames = [u1, u2, u3]
        expected = [u1.id, u2.id, u3.id]
        actual = UserProxy.get_user_ids(usernames)
        self.assertEqual(expected, actual)

Upvotes: 4

Views: 1117

Answers (1)

user764357
user764357

Reputation:

I'm going to take a stab and say that its because you are using nosetests instead of the Django test runner. Because you are using nosetests, Django's setup_test_environment isn't being called, which means the code doesn't know to use the test database correctly.

Here are the relevant parts of the Django documentation that shoudl help:

Finding data from your production database when running tests?

If your code attempts to access the database when its modules are compiled, this will occur before the test database is set up, with potentially unexpected results. For example, if you have a database query in module-level code and a real database exists, production data could pollute your tests. It is a bad idea to have such import-time database queries in your code anyway - rewrite your code so that it doesn’t do this.

And:

Running tests outside the test runner

If you want to run tests outside of ./manage.py test – for example, from a shell prompt – you will need to set up the test environment first. Django provides a convenience method to do this:

>>> from django.test.utils import setup_test_environment
>>> setup_test_environment()

Upvotes: 4

Related Questions