Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Django单元测试需要很长时间来创建测试数据库_Python_Django_Django Unittest_Django Nose - Fatal编程技术网

Python Django单元测试需要很长时间来创建测试数据库

Python Django单元测试需要很长时间来创建测试数据库,python,django,django-unittest,django-nose,Python,Django,Django Unittest,Django Nose,一段时间以来,我的单元测试花费的时间比预期的要长。我试过几次调试它,但都没有成功,因为延迟甚至在我的测试开始运行之前。这影响了我做任何远程接近测试驱动开发的事情的能力(可能我的期望太高了),所以我想看看是否能一劳永逸地解决这个问题 运行测试时,测试的开始和实际开始之间有70到80秒的延迟。例如,如果我运行一个小模块的测试(使用time python manage.py test myapp),我会得到 和 ....... 线路。换句话说,测试在3sec以下进行,但数据库初始化似乎需要1:18分

一段时间以来,我的单元测试花费的时间比预期的要长。我试过几次调试它,但都没有成功,因为延迟甚至在我的测试开始运行之前。这影响了我做任何远程接近测试驱动开发的事情的能力(可能我的期望太高了),所以我想看看是否能一劳永逸地解决这个问题

运行测试时,测试的开始和实际开始之间有70到80秒的延迟。例如,如果我运行一个小模块的测试(使用
time python manage.py test myapp
),我会得到

.......
线路。换句话说,测试在3sec以下进行,但数据库初始化似乎需要1:18分钟

我有大约30个应用程序,大多数都有1到3个数据库模型,所以这应该能让我了解项目的规模。我使用SQLite进行单元测试,并实现了一些建议的改进。我不能发布我的整个设置文件,但很乐意添加所需的任何信息

我确实需要跑步者

from django.test.runner import DiscoverRunner
from django.conf import settings

class ExcludeAppsTestSuiteRunner(DiscoverRunner):
    """Override the default django 'test' command, exclude from testing
    apps which we know will fail."""

    def run_tests(self, test_labels, extra_tests=None, **kwargs):
        if not test_labels:
            # No appnames specified on the command line, so we run all
            # tests, but remove those which we know are troublesome.
            test_labels = (
                'app1',
                'app2',
                ....
                )
            print ('Testing: ' + str(test_labels))

        return super(ExcludeAppsTestSuiteRunner, self).run_tests(
                test_labels, extra_tests, **kwargs)
在我的设置中:

TEST_RUNNER = 'config.test_runner.ExcludeAppsTestSuiteRunner'
我还尝试过将
django nose
django nose exclude

我已经阅读了很多关于如何加速测试本身的文章,但是没有找到任何关于如何优化或避免数据库初始化的线索。我已经看到了关于尝试不使用数据库进行测试的建议,但我无法或不知道如何完全避免这种情况

如果需要,请告诉我

  • 这是正常的,也是意料之中的
  • 没有预料到(希望有一个解决方案或线索)
  • 同样,我不需要关于如何加速测试本身的帮助,只需要初始化(或开销)。我希望上面的例子需要10秒而不是80秒

    非常感谢

    我使用
    --verbose 3
    运行测试(针对单个应用程序),发现这一切都与迁移有关:

      Rendering model states... DONE (40.500s)
      Applying authentication.0001_initial... OK (0.005s)
      Applying account.0001_initial... OK (0.022s)
      Applying account.0002_email_max_length... OK (0.016s)
      Applying contenttypes.0001_initial... OK (0.024s)
      Applying contenttypes.0002_remove_content_type_name... OK (0.048s)
      Applying s3video.0001_initial... OK (0.021s)
      Applying s3picture.0001_initial... OK (0.052s)
      ... Many more like this
    

    我压缩了所有迁移,但仍然很慢。

    数据库初始化确实需要太长时间

    我有一个项目,有大约相同数量的模型/表格(大约77个),大约350个测试,总共需要1分钟来运行所有东西。在一台分配了2个CPU和2GB ram的流浪机器中进行设备隔离。我还使用pytest.test和pytest xdist插件并行运行多个测试

    您可以做的另一件事是告诉django重用测试数据库,并且只在模式发生更改时重新创建它。您还可以使用SQLite,以便测试将使用内存中的数据库。这里解释了两种方法:

    编辑:如果上述选项都不起作用,另一个选项是让您的单元测试从django SimpleTestCase继承,或者使用自定义测试运行程序,该测试运行程序不创建数据库,如下面的回答所述:

    然后,您可以使用这样的库(我承认是这样写的)来模拟django对数据库的调用:


    这样,您可以在本地快速运行单元测试,让CI服务器在将代码合并到非生产分支的稳定开发/主分支之前,担心运行需要数据库的集成测试。

    解决我的问题的最终解决方案是强制Django在测试期间禁用迁移,这可以通过如下设置完成

    TESTING = 'test' in sys.argv[1:]
    if TESTING:
        print('=========================')
        print('In TEST Mode - Disableling Migrations')
        print('=========================')
    
        class DisableMigrations(object):
    
            def __contains__(self, item):
                return True
    
            def __getitem__(self, item):
                return "notmigrations"
    
        MIGRATION_MODULES = DisableMigrations()
    
    或使用

    我的整个测试现在大约需要1分钟,一个小应用程序需要5秒钟

    在我的情况下,测试不需要迁移,因为我在迁移时更新测试,并且不使用迁移添加数据。这对每个人都不起作用

    总结 使用
    pytest

    操作
  • pip安装pytest-django
  • pytest——命名
    而不是
    /manage.py测试
  • 结果
    • /manage.py测试
      花费2分钟11.86秒
    • pytest——命名花费2.18秒
    提示
    • 您可以在项目根目录中创建名为
      pytest.ini
      的文件,并在其中指定和/或

      现在,您可以简单地使用
      pytest
      运行测试,并节省一点键入时间

    • 通过添加到默认命令行选项,可以进一步加快后续测试的速度

      [pytest]
      addopts = --nomigrations --reuse-db
      
      但是,一旦更改了数据库模型,就必须运行一次
      pytest--create db

    • 如果需要在测试期间启用,可以在项目根目录中创建名为
      pytest
      的文件,其中包含以下内容,将执行位强制转换为它(
      chmod+x pytest
      ),然后运行
      /pytest
      进行测试,而不是
      pytest

      #/usr/bin/env python
      #-*-编码:utf-8-*-
      #测试内容
      从gevent导入猴子
      猴子
      导入操作系统
      os.environ.setdefault(“DJANGO\u设置\u模块”、“yourproject.SETTINGS”)
      从django.db导入连接
      connection.allow\u thread\u sharing=True
      进口稀土
      导入系统
      从pytest导入main
      如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
      sys.argv[0]=re.sub(r'(-script\.pyw\.exe)?$,'',sys.argv[0])
      sys.exit(main())
      
      您可以创建一个
      test\u gevent.py
      文件来测试gevent monkey补丁是否成功:

      #-*-编码:utf-8-*-
      #测试内容_gevent.py
      导入时间
      从django.test导入TestCase
      从django.db导入连接
      导入gevent
      def f(n):
      cur=connection.cursor()
      当前执行(“选择睡眠(%s)”,(n,)
      当前执行(“选择%s”,(n,))
      cur.fetchall()
      连接。关闭()
      类GeventTestCase(测试用例):
      longMessage=True
      def测试_gevent_繁殖(自身):
      timer=time.time()
      d1,d2,d3=1,2,3
      t1=gevent.spawn(f,d1)
      t2=gevent.spawn(f,d2)
      t3=gevent.spawn(f,d3)
      gevent.joinall([t1,t2,t3])
      成本=时间。时间()-计时器
      自评资产质量(成本,最大值(d1、d2、d3),增量=1.0,
      msg='gevent spawn未按预期工作')
      
    <
    TESTING = 'test' in sys.argv[1:]
    if TESTING:
        print('=========================')
        print('In TEST Mode - Disableling Migrations')
        print('=========================')
    
        class DisableMigrations(object):
    
            def __contains__(self, item):
                return True
    
            def __getitem__(self, item):
                return "notmigrations"
    
        MIGRATION_MODULES = DisableMigrations()
    
    # content of pytest.ini
    [pytest]
    addopts = --nomigrations
    DJANGO_SETTINGS_MODULE = yourproject.settings
    
    [pytest]
    addopts = --nomigrations --reuse-db