为什么 Django 在测试期间不创建空白数据库?

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

当我运行单元测试时,Django 1.6 似乎没有创建空白数据库来进行测试,我不明白为什么。 Django docs 说 Django 不使用您的生产数据库,而是创建一个单独的空白数据库用于测试。但是,当我调试我的测试 'test_get_user_ids' 并运行命令 'UserProxy.objects.all()' 时,我看到我的生产数据库中的所有用户。现在我知道这个特定的测试将失败,因为我没有将每个 UserProxy 实例保存到数据库中,因此没有生成要测试的 ID。但事实是,当我查询 UserProxy 时,我仍然可以看到我的生产数据库中的所有用户,我希望这些用户是空的。为什么会这样?

顺便说一句,我正在使用 nosetest 运行测试:"nosetests -s apps.profile.tests.model_tests.py:UserProxyUT"

谢谢。

# 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)

我要试探一下,这是因为您使用的是 nosetests 而不是 Django 测试运行程序。因为你正在使用 nosetests,Django 的 setup_test_environment 没有被调用,这意味着代码不知道正确使用测试数据库。

以下是 Django 文档中应该有所帮助的相关部分:

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.

并且:

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()