2013-02-24 40 views
1

我遇到了Django測試套件中的一個奇怪問題我陷入困境,所以我正在尋找一些有關如何解決它或至少在哪裏尋找的見解。Django SQLite試圖在測試時覆蓋數據庫

當我運行下面的測試我特迪比爾斯應用:

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 

不應在DB被默認與「測試」一詞的前綴避免名稱衝突?我將數據庫重命名爲「: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 

答覆:

這裏是我的DB設置:

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×哎呀....

它unfortuneately不固定的問題。我曾嘗試過所有建議,除了更改數據庫名稱,但沒有解決它。

我做了所有的建議包括:

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' 

正如你可以看到它是原始模型的一個子類,因爲「db_table」屬性設置明確它推翻了自動生成的表名。這裏學到的教訓是,在Meta對象上設置db_table屬性會導致測試工具發生不好的事情。只有在絕對需要這樣處理時才能做到這一點。

+0

首先,檢查你是否沒有意外地用'db_table ='teadybeaers_teadybear''定義兩個模型。並確保你只是爲了測試而更改數據庫:'如果'test'在sys.argv中:DATABASES ['default'] = {'ENGINE':'django.db.backends.sqlite3'}' – 2013-02-24 22:33:42

+0

請包括你的在你的問題中'settings.py'的'DATABASES'條目。 – 2013-02-24 22:36:03

回答

4

有在文檔中的兩個部分,可能涉及到您所遇到的問題:

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

By default the test databases get their names by prepending test_ to the value of the NAME settings for the databases defined in DATABASES. When using the SQLite database engine the tests will by default use an in-memory database (i.e., the database will be created in memory, bypassing the filesystem entirely!). If you want to use a different database name, specify TEST_NAME in the dictionary for any given database in DATABASES.

和..

If your tests rely on database access such as creating or querying models, be sure to create your test classes as subclasses of django.test.TestCase rather than unittest.TestCase.

In the example above, we instantiate some models but do not save them to the database. Using unittest.TestCase avoids the cost of running each test in a transaction and flushing the database, but for most applications the scope of tests you will be able to write this way will be fairly limited, so it’s easiest to use django.test.TestCase.

所以首先,確保您的測試是從django.test.TestCase繼承。其次,嘗試將TEST_NAME設置爲testdb.sqlite,看看是否可以解決您的問題。您可能還想指定數據庫的路徑,如/Work/database.sqlite,否則(我認爲)數據庫將在執行manage.py的目錄中創建,而這可能並不總是您想要的。

最後,請確保您正在爲您的測試加載正確的settings文件。

+0

加載正確的設置文件 – renderbox 2013-02-26 23:07:09

+0

Grrr,在我輸入完成之前發送 – renderbox 2013-02-26 23:07:37

+0

我把defualt test.py放在那裏,並且刪除了所有的測試我只是爲了確保我能夠得到這個工作,但沒有運氣 – renderbox 2013-02-26 23:15:51

2

您是否指向正確的設置模塊?嘗試:

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

試過這個沒有運氣。同樣的錯誤。 :( – renderbox 2013-02-24 23:00:19