Django SQLite在测试时试图覆盖数据库

时间:2013-02-24 21:32:37

标签: python django

我遇到了一个奇怪的问题,Django的测试套件让我陷入困境,所以我正在寻找一些关于如何解决它或至少在哪里看的洞察力。

当我运行以下内容来测试我的泰迪熊应用程序时:

python manage.py test teddybears

我收到此错误:

...django/db/backends/sqlite3/base.py", line 344, in execute
return Database.Cursor.execute(self, query, params)
django.db.utils.DatabaseError: table "teddybears_teddybear" already exists

不应该在数据库前面加上"测试"默认情况下避免名称冲突?我将数据库重命名为":memory:"试图避免这种情况,但仍然是同样的错误。

开发工作正常,一切都按预期运行,我无法让测试套件工作。任何洞察可能导致这种或在哪里看的内容都将非常感激。

我正在使用SQLite进行本地开发工作并使用Django 1.4.3

这是完整的堆栈跟踪:

> python manage.py test teadybears
Creating test database for alias 'default'...
Traceback (most recent call last):
  File "manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/Work/projects/teadybears/venv/lib/python2.7/site-packages/django/core/management/__init__.py", line 443, in execute_from_command_line
    utility.execute()
  File "/Work/projects/teadybears/venv/lib/python2.7/site-packages/django/core/management/__init__.py", line 382, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/Work/projects/teadybears/venv/lib/python2.7/site-packages/django/core/management/commands/test.py", line 49, in run_from_argv
    super(Command, self).run_from_argv(argv)
  File "/Work/projects/teadybears/venv/lib/python2.7/site-packages/django/core/management/base.py", line 196, in run_from_argv
    self.execute(*args, **options.__dict__)
  File "/Work/projects/teadybears/venv/lib/python2.7/site-packages/django/core/management/base.py", line 232, in execute
    output = self.handle(*args, **options)
  File "/Work/projects/teadybears/venv/lib/python2.7/site-packages/django/core/management/commands/test.py", line 72, in handle
    failures = test_runner.run_tests(test_labels)
  File "/Work/projects/teadybears/venv/lib/python2.7/site-packages/django/test/simple.py", line 381, in run_tests
    old_config = self.setup_databases()
  File "/Work/projects/teadybears/venv/lib/python2.7/site-packages/django/test/simple.py", line 317, in setup_databases
    self.verbosity, autoclobber=not self.interactive)
  File "/Work/projects/teadybears/venv/lib/python2.7/site-packages/django/db/backends/creation.py", line 271, in create_test_db
    load_initial_data=False)
  File "/Work/projects/teadybears/venv/lib/python2.7/site-packages/django/core/management/__init__.py", line 150, in call_command
    return klass.execute(*args, **defaults)
  File "/Work/projects/teadybears/venv/lib/python2.7/site-packages/django/core/management/base.py", line 232, in execute
    output = self.handle(*args, **options)
  File "/Work/projects/teadybears/venv/lib/python2.7/site-packages/django/core/management/base.py", line 371, in handle
    return self.handle_noargs(**options)
  File "/Work/projects/teadybears/venv/lib/python2.7/site-packages/django/core/management/commands/syncdb.py", line 102, in handle_noargs
    cursor.execute(statement)
  File "/Work/projects/teadybears/venv/lib/python2.7/site-packages/django/db/backends/sqlite3/base.py", line 344, in execute
    return Database.Cursor.execute(self, query, params)
django.db.utils.DatabaseError: table "teadybears_teadybear" already exists

REPLY:

以下是我的数据库设置:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': 'database.sqlite',                      # Or path to database file if using sqlite3.
        'USER': '',                      # Not used with sqlite3.
        'PASSWORD': '',                  # Not used with sqlite3.
        'HOST': '',                      # Set to empty string for localhost. Not used with sqlite3.
        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
    }
}

我确实在那里有这个,但没有区别:

if 'test' in sys.argv:
    DATABASES['default']['NAME'] = ':memory:'

2 X Grrr ....

不幸的是,没有解决这个问题。我已经尝试了所有建议,除了更改数据库名称,但也没有修复它。

我做了所有的建议,包括:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': 'database.sqlite',                      # Or path to database file if using sqlite3.
        'USER': '',                      # Not used with sqlite3.
        'PASSWORD': '',                  # Not used with sqlite3.
        'HOST': '',                      # Set to empty string for localhost. Not used with sqlite3.
        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
        'TEST_NAME': 'mud',
    }
}

现在问我:

python manage.py test teddybears
Creating test database for alias 'default'...
Destroying old test database 'default'...
Type 'yes' if you would like to try deleting the test database 'mud', or 'no' to cancel:

仍然会产生相同的错误。

不愿将其转移到另一个干净的项目,只是为了解决这个问题,但它仍然很烦人。


我已经弄清楚是什么让我沮丧。该项目的一个模型在Meta Class上设置了一个值,导致测试中断。

class TeddybearExtra(Teddybear):

    class Meta:
        db_table = 'teddybears_teddybear'

正如您所看到的,它是原始模型的子类,因为&#34; db_table&#34;属性是显式设置的,它覆盖了自动生成的表名。这里学到的经验是,在Meta对象上设置db_table属性会导致测试工具出现问题。只有在你绝对需要这样处理时才这样做。

2 个答案:

答案 0 :(得分:4)

文档中有两个部分可能与您遇到的问题有关:

https://docs.djangoproject.com/en/dev/topics/testing/overview/#the-test-database

  

默认情况下,测试数据库通过将test_前置为DATABASES中定义的数据库的NAME设置值来获取其名称。当使用SQLite数据库引擎时,测试将默认使用内存数据库(即数据库将在内存中创建,完全绕过文件系统!)。如果要使用其他数据库名称,请在字典中为DATABASES中的任何给定数据库指定TEST_NAME。

和..

  

如果您的测试依赖于数据库访问,例如创建或查询模型,请确保将测试类创建为django.test.TestCase的子类,而不是unittest.TestCase。

     

在上面的示例中,我们实例化了一些模型,但没有将它们保存到数据库中。使用unittest.TestCase可以避免在事务中运行每个测试并刷新数据库的成本,但对于大多数应用程序,您将能够以这种方式编写的测试范围将相当有限,因此最简单的方法是使用django.test.TestCase

首先,请确保您的测试是django.test.TestCase的子类。其次,尝试将TEST_NAME设置为testdb.sqlite,看看是否能解决您的问题。您可能还想在/Work/database.sqlite中指定数据库的路径,否则(我认为)将在您正在执行manage.py的目录中创建数据库,这可能并非总是如此你想要什么。

最后,请确保为测试加载了正确的settings文件。

答案 1 :(得分:2)

您是否指向正确的设置模块?尝试:

python manage.py test teddybears --settings=myproject.settings.test