4

我有一个使用 mysql 作为后端的 django 1.4 项目。我有测试设置在内存中运行

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 等...他们必须在文件系统上正常运行测试吗?

谢谢

4

3 回答 3

14

MySQL 有一个MEMORY存储引擎。您可以OPTIONS使用以下密钥激活它:

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.

因此,我认为这对您(和许多其他)用例来说毫无用处。

我在这个线程中发现了一些加速 MySQL 测试的其他技巧。请务必阅读 Daniel Roseman 关于使用INNODB引擎的回答。

于 2013-03-05T23:06:38.123 回答
3

正如在问题评论中所建议的那样,您可以通过将测试数据库存储在 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 数据库运行大多数测试的灵活性。

于 2013-03-06T00:05:08.207 回答
-4

不要测试 MySQL。MySQL 已经过其开发人员的测试。您的工作是以这种方式编写代码,以便您可以用一个模拟 Python 对象替换 MySQL 连接,该对象将返回 MySQL 将返回的任何内容(或断言发送到 MySQL 的查询是否是您想要的)

于 2013-03-05T23:33:17.777 回答