加速Django测试

44u64gxh  于 2022-11-26  发布在  Go
关注(0)|答案(8)|浏览(130)

我希望了解更多关于Django的测试流程。
背景信息http://docs.djangoproject.com/en/dev/topics/testing/
我在使用测试驱动开发时遇到了一些困难。Django的测试运行程序在启动时会不断地在一个测试数据库中创建所有的数据库模型。对于我们目前的项目(40到240个模型),这意味着测试启动需要20秒。
这使得经常测试一个新特性完全不可行。我的问题是,你们是如何解决这个问题的?
我在过去尝试了一些方法a.)-更改testloader,以便每次都重用相同的测试数据库,并在需要时应用迁移b.)-从python文件的__main__流中运行我的单元测试
选项B对于sys.path来说很笨拙,选项a是可行的,但似乎不是django的方式。
更新:选项A确实不是一个糟糕的解决方案。它只是相当多的努力。这使我相信人们使用不同的解决方案。SQL lite可能是解决方案。但我猜还有更多。

pxiryf3j

pxiryf3j1#

更改测试加载程序,以便每次都重用相同的测试数据库,并在需要时应用迁移
1.我看不出编写自己的测试运行程序有什么不对,它只是截断表,而不是删除和创建数据库。这是djangoic,因为它解决了一个特定的问题。有一个ticket开放,允许将测试用例分组到测试套件中。一旦它被修复,你应该能够将你的测试用例分组到套件中,以便于管理。您还可以检查附加到票证的补丁程序,看看它是否适合您的目的。
1.正如Ned所建议的,你可以使用内存中的数据库,这在很大程度上取决于你的数据模型和查询是否可以跨数据库移植。
1.如果你还没有尝试重新组织你的测试用例。根据我的经验,并不是所有的测试类都需要子类django.test.TestCase。找出那些可以子类unittest.TestCase的测试类。这会稍微加快一些速度。
1.重新组织fixture。将公共fixture移动到单个文件中,并在测试运行之前加载它,而不是在每个测试类中加载它(使用fixtures = [...])。

fwzugrvs

fwzugrvs2#

在测试过程中使用内存中的SQLite数据库无疑会加快速度。

s4chpxco

s4chpxco3#

我不喜欢使用不同的数据库(SQLite)进行测试的想法,所以我的单元测试使用与生产应用程序相同的数据库-postgres。
开箱即用,这使得创建/销毁数据库成为运行测试中最慢的步骤。
Django1.8将使用--keepdb标志来解决这个问题
但我们还没有做到这一点,所以我们必须用其他手段来应付。

解决方案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上获得同样的好处,你可以转到Run/Debug Configurations,Defaults/Django tests,然后在环境变量上添加USE_TEST_DB = 1
最新消息:
示例应用程序位于Github上:https://github.com/freedomsponsors/www.freedomsponsors.org/blob/099ec1a7a1c404eba287d4c93d58c8cf600b2769

aiazj4mn

aiazj4mn4#

我发现了另一种加快测试速度的方法。如果你的测试模型是auth用户(User模型),并且你为他们设置了密码,那么哈希函数需要几毫秒的时间才能完成。我所做的就是把这个添加到我的测试设置中:

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

在我的例子中,这改进了12个测试,每个测试创建7个用户,从4.5秒到500毫秒。

请注意不要将此添加到生产设置中!

dddzy1tm

dddzy1tm5#

您可以只运行您特别感兴趣的测试,请查看此处:http://docs.djangoproject.com/en/dev/topics/testing/?from=olddocs#running-tests
就像在这个例子中--只运行特定的TestCase:

$ ./manage.py test animals.AnimalTest

至于测试数据库-它是创建和销毁每次测试运行:(同样,为了测试,你可以使用sqlite数据库,如果它在您的工作流程中是可能的。

w8rqjzmb

w8rqjzmb6#

从Django 1.8开始,你可以保留测试数据库,这样你就不用在每次测试的时候都重建它了,只需要添加--keepdb标志。

python manage.py test --keepdb

排除--keepdb标志以从头开始重建测试数据库。

dsekswqp

dsekswqp7#

我发现了另一种加快测试速度的方法。最耗时的操作是写入/阅读硬盘(我使用sqlite进行测试)。解决方案是创建ramdisk,并将sqlite数据库文件放在那里。我将测试时间缩短了10倍。
正在创建内存磁盘:

#!/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',
    }
}
bvpmtnay

bvpmtnay8#

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

相关问题