2013-03-05 60 views
4

我有一個使用mysql作爲後端的django 1.4項目。我測試的設置在內存在內存中運行Django MySQL測試

if 'test' in sys.argv: 
    DATABASES['default'] = {'ENGINE': 'django.db.backends.sqlite3'} 

的問題是我需要使用mysql功能(全文索引)上運行。

有沒有辦法讓django在內存中運行MySQL進行測試?

我的項目依賴於全文索引。當我在SyncDB上開發項目時,使用sql執行.sql文件以創建全文索引。

我想在我測試的函數中使用django orm全文搜索。我試圖手動添加每個測試初始化​​喜歡全文索引:

cursor.execute('alter table mytable add fulltext(one, two)')

使用SQLite(我相信,因爲SQLite不支持全文索引)

上面的SQL時,這不起作用當我刪除內存中的測試時工作嗎?我喜歡內存測試的速度。 有沒有辦法在內存中運行mysql?

人們如何測試依賴於數據庫特定功能的應用程序?如全文索引或gis等等......他們是否必須在文件系統上正常運行測試?

謝謝

+2

確實MySQL支持的表空間?在Linux上,您可以將dbs表空間設置爲放置在RAM磁盤上。 http://www.cyberciti.biz/faq/howto-create-linux-ram-disk-filesystem/ – monkut 2013-03-05 22:10:51

回答

-4

不測試MySQL。 MySQL已經由其開發者進行測試。 您的工作是以這種方式進行編碼,以便您可以用模擬Python對象替換MySQL連接,該模擬Python對象將返回MySQL將返回的任何內容(或者,如果將查詢發送到MySQL是您想要的,則斷言)

+0

這裏唯一的問題是可能有很多方法來訪問數據庫 - 並嘲笑他們都會時間昂貴,而嘲笑太少會限制實施。理想情況下,測試應該是關於意圖而不是實現。 – 2013-12-03 10:20:27

+3

這通常可以是很好的建議......寫作時「你好,世界」風格的節目。任何與數據庫交流的不平凡的事情都取決於數據庫的行爲,所以測試整個事情是必須的 - 否則你很快就會發現,相關數據庫並沒有像你的模擬一樣。 – ayanami 2015-02-21 20:56:15

+1

@ayanami:同樣的事情會發生上比在生產中使用的一個不同的存儲引擎的測試。在某些情況下,MySQL的MEMORY引擎與MyISAM和InnoDB的行爲不同。一旦我們談論集成測試(這好像我們是在這種情況下),他們應在目標配置中運行。這意味着這些測試有時會很慢。 – Mchl 2015-10-02 10:37:44

12

MySQL有一個MEMORY存儲引擎。您可以激活使用OPTIONS關鍵是:根據documentation

if 'test' in sys.argv: 
    DATABASES = { 
     'default': { 
      'ENGINE': 'django.db.backends.mysql', 
      'HOST': 'localhost', 
      'NAME': 'foo', 
      'USER': 'bar', 
      'PASSWORD': 'baz', 
      'OPTIONS': { 
       'init_command': 'SET storage_engine=MEMORY' 
      } 
     } 
    } 

MEMORY tables cannot contain BLOB or TEXT columns. 

所以我想這是你的(和許多其他)相當無用的用例。

我在this thread中發現了一些加速MySQL測試的其他技巧。請務必閱讀Daniel Roseman關於使用INNODB引擎的回答。

3

正如monkut在問題評論中提出的那樣,您可以通過將測試數據庫存儲在RAM驅動器上來獲得一些MySql加速。如果在Linux上運行,則爲tmpfs文件系統。但是,如果您在測試期間擔心速度,這可能無法提供很大的速度提升,因爲MySql通常會將其數據緩存在內存中。

我使用的方法是編寫一個測試裝飾器,它將跳過不支持給定數據庫後端的測試,然後使用不同的settings.py文件來測試不同的後端。

在這裏,我用django-nose功能幫忙寫一個裝飾,如果任何測試數據庫使用使用SQLite跳過測試。

from nose import SkipTest 
from django.conf import settings 

def skip_if_sqlite(test_fn): 
    """Nose test decorator to skip test if testing using sqlite databases. 

    This may be useful when we know that a test will fail when using sqlite, 
    possibly because the test uses functionality not supported on sqlite such 
    as database views or full text indexes. 

    This decorator can be used as follows: 
    @skip_if_sqlite 
    def my_test_that_shouldnt_run_if_sqlite_database(self): 
     pass 
    """ 

    @functools.wraps(test_fn) 
    def wrapper(*args, **kwargs): 
     # Skip test if any database contain a sqlite engine. 
     for alias, db_settings in settings.DATABASES.iteritems(): 
      if 'sqlite' in db_settings['ENGINE']: 
       raise SkipTest() 
      return test_fn(*args, **kwargs) 

    return wrapper 

然後,設置settings.test.mysqlsettings.test.sqlite不同DATABASE設置。如果用settings.test.sqlite執行你的測試,這依賴於MySQL的特定功能測試將被跳過,但如果你正在運行測試對settings.test.mysql,測試將被執行。

該方法允許您專門針對特定數據庫後端的測試,但仍然提供了在開發期間針對更快的SQLite數據庫運行大部分測試的靈活性。