加速Django测试

时间:2010-09-26 17:51:02

标签: python django unit-testing

我希望通过Django了解有关您的测试流程的更多信息。

背景资料 http://docs.djangoproject.com/en/dev/topics/testing/

使用测试驱动开发时遇到困难。 Django的测试运行器在启动时不断在测试数据库中创建所有数据库模型。 对于我们当前的项目(40到240个型号),这意味着测试开始需要20秒。

这使得经常测试新功能完全不可行。 我的问题是,你们是如何解决这个问题的?

我过去曾尝试过一些事情 a。) - 更改testloader以每次重用相同的测试数据库,并在需要时应用迁移 b。) - 从__main__ python文件流中运行我的单元测试

选项b对于sys.path很尴尬,选项a是可行的,但似乎不是django方式。

更新: 选项A确实不是一个糟糕的解决方案。它只是相当多的努力。这让我相信人们使用不同的解决方法。 SQL lite可能就是那种解决方法。但我猜还有更多。

8 个答案:

答案 0 :(得分:9)

在测试期间使用内存中的SQLite数据库肯定会加快速度。

答案 1 :(得分:9)

  

每次都更改testloader以重用相同的测试数据库,并在需要时应用迁移

  1. 在编写自己的测试运行器时,我没有看到任何错误,只是截断表而不是删除和创建数据库。这是djangoic,因为它解决了一个特定的问题。有ticket开放允许将测试用例分组到测试套件中。修复后,您应该能够将测试用例分组到套件中以便于管理。您还可以检查附加到故障单的补丁,看它是否适合您的目的。

  2. 作为Ned suggested,您可以使用内存数据库。这在很大程度上取决于您的数据模型和可跨数据库移植的查询。

  3. 如果您尚未尝试重新组织测试用例。根据我的经验,并非所有测试类都需要子类django.test.TestCase。找出那些可以使用子类unittest.TestCase进行测试的测试类。这将加速 little 位。

  4. 重新组织灯具。将常用夹具移动到单个文件并在测试运行之前加载它,而不是在每个测试类中加载(使用fixtures = [...])。

答案 2 :(得分:8)

我不喜欢使用不同的数据库(SQLite)进行测试,所以我的单元测试使用与生产应用程序相同的数据库 - postgres。

开箱即用,这使得创建/销毁数据库成为运行测试的最慢步骤。

Django 1.8将使用--keepdb flag

解决此问题

但我们还没有,所以我们必须用其他方法。

解决方案1)使用pytest-django

您可以使用它来运行测试而无需重新创建数据库。有用。 如果你只关心在命令行上运行测试,我建议你这样做。

在我的情况下,我喜欢使用PyCharm IDE,能够通过右键单击文件/方法来运行测试对我来说绝对是一个加分,所以我不得不一起去...

解决方案2)TEST_MIRROR技巧。

settings.py文件中,配置数据库,如:

if os.getenv('USE_TEST_DB') == '1':
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': 'mydbtesting',
            'USER': 'mydb',
            'PASSWORD': 'mydb',
            'HOST': 'localhost',
            'PORT': '5432',
            'TEST_MIRROR': 'default',
        }
    }
else:
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': 'mydb',
            'USER': 'mydb',
            'PASSWORD': 'mydb',
            'HOST': 'localhost',
            'PORT': '5432',
        }
    }

因此,“mydb”是用于正常执行的数据库,“mydbtesting”用于测试。

TEST_MIRROR设置实际上并不意味着这个,但事实是如果你使用这样配置的数据库运行测试,Django将不会重新创建/销毁我们想要的东西。

但首先我们必须使用以下内容创建该数据库:

export USE_TEST_DB=1
./manage.py syncdb --migrate

然后,只要您想快速运行测试,只需将USE_TEST_DB环境变量设置为“1”即可。 要在Pycharm上获得相同的好处,您可以转到运行/调试配置,默认值/ Django测试,然后在环境变量上添加USE_TEST_DB = 1


更新:

示例应用程序在Github上:https://github.com/freedomsponsors/www.freedomsponsors.org/blob/099ec1a7a1c404eba287d4c93d58c8cf600b2769

答案 3 :(得分:2)

您只能运行您特别感兴趣的测试,请查看此处:http://docs.djangoproject.com/en/dev/topics/testing/?from=olddocs#running-tests

就像在这个例子中一样 - 运行specyfic TestCase:

$ ./manage.py test animals.AnimalTest

对于测试数据库 - 每次测试运行时都会创建并销毁它:( 同样,对于测试,如果可以在您的工作流程中使用sqlite数据库。

答案 4 :(得分:2)

我找到了另一种加速测试的方法。如果您的测试模型是auth用户(User型号),并且您为它们设置了密码,则散列函数需要相当多的毫秒才能完成。我所做的是将其添加到我的测试设置中:

PASSWORD_HASHERS = (
    'django.contrib.auth.hashers.MD5PasswordHasher',
)

这会对密码强制执行MD5哈希,这比默认密码要快得多。 在我的例子中,这改进了12个测试,每个测试创建7个用户,从4.5秒到500毫秒。

小心不要将其添加到您的生产设置中!

答案 5 :(得分:1)

我找到了另一种加速测试的方法。最耗时的操作是写入/读取硬盘驱动器(我正在使用sqlite进行测试)。解决方案是创建ramdisk,并将sqlite数据库文件放在那里。我将测试时间缩短了10倍。

创建ramdisk:

#!/bin/sh

mkdir -p /tmp/ramdisk; chmod 777 /tmp/ramdisk
mount -t tmpfs -o size=256M tmpfs /tmp/ramdisk/

更改数据库文件路径:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': '/tmp/ramdisk/test.db',
        'TEST_NAME': '/tmp/ramdisk/test.db',
    }
}

答案 6 :(得分:1)

从Django 1.8开始,您可以保留测试数据库,以便每次测试时都不会重建它。只需添加--keepdb标志。

var count = 1;

function setColor() {
  var property = document.getElementById('buttonclick');
  if (count == 0) {
    property.style.backgroundColor = "#4f8ff7"
    property.innerHTML = "<span>Enable control</span>"
    alert("Disabled");
    count = 1;
  } else {
    property.style.backgroundColor = "#a84237"
    property.innerHTML = "<span>Disable control</span>"
    alert("Enabled");
    count = 0;
  }
}

当您进行新的迁移时,请排除--keepdb标志,并且将从头开始构建测试数据库。

答案 7 :(得分:0)

以下是简单的测试工具,它们提供无重载数据库和信号,因此您无需关心测试数据库https://github.com/plus500s/django-test-tools