【问题标题】:Mocking Django Storages Model ImageField backend S3模拟 Django 存储模型 ImageField 后端 S3
【发布时间】:2012-08-22 10:11:10
【问题描述】:

我有一个由 django-storages 的 S3Boto 支持的带有 ImageField 的模型。我对“上传图片”视图的练习进行了测试,但是将图片上传到 S3 的事实正在减慢我的测试套件的速度。

为了加快我的测试速度,处理此问题的最佳做法是什么?我应该模拟 S3Boto 吗?也许有一个内存支持的存储后端非常适合测试(自动清理会很好!)?

【问题讨论】:

    标签: django unit-testing mocking


    【解决方案1】:

    我也遇到了这个问题。通过使用dj-inmemorystorage,我得到了更快的测试。

    快速设置方法是在与您的设置相同的文件夹中创建test_settings.py

    from settings import *
    DEFAULT_FILE_STORAGE = 'inmemorystorage.InMemoryStorage'
    

    ...并调用./manage.py test --settings=project.test_settings 运行测试。

    我的首选方式是设置自定义测试运行器:

    project/test_runner.py:

    from django.conf import settings
    from django.test.runner import DiscoverRunner
    
    class FastTestRunner(DiscoverRunner):
        def setup_test_environment(self):
            super(FastTestRunner, self).setup_test_environment()
            # Don't write files
            settings.DEFAULT_FILE_STORAGE = 'inmemorystorage.InMemoryStorage'
            # Bonus: Use a faster password hasher. This REALLY helps.
            settings.PASSWORD_HASHERS = (
                'django.contrib.auth.hashers.MD5PasswordHasher',
            )
    

    注意:这也设置了PASSWORD_HASHER,因为它是significantly improves User creation time这不应该在生产中设置。

    project/settings.py:

    TEST_RUNNER = 'project.test_runner.FastTestRunner'
    

    要求:

    pip install dj-inmemorystorage
    

    更新:从django-inmemorystorage更改为dj-inmemorystorage.

    更新 2:删除了 django-discover-runner,因为它现在是 django 中的默认测试运行程序,并修复了指向 PASSWORD_HASHER 相关博客文章的链接。

    【讨论】:

      【解决方案2】:

      我也遇到了这个问题,所以我想我应该提出我的解决方案。我的解决方案使用Mock

      import mock
      from django.core.files.storage import FileSystemStorage
      from django.test import TestCase
      
      class ATestCase(TestCase):
          def setUp(self):
              # Stuff Happens
      
          def tearDown(self):
              # more Stuff
      
          @mock.patch('storages.backends.s3boto.S3BotoStorage', FileSystemStorage)
          def test_file_stuff(self):
              self.assertMagicPonies(True)
      

      一些陷阱 - 确保你在设置中有一个健全的MEDIA_ROOT 设置。从 django 1.4 开始,您不能使用测试上下文管理器覆盖 MEDIA_ROOT,因此您需要为其单独设置配置 (https://code.djangoproject.com/ticket/17787) 这已在 1.6 中修复。另外,请确保您的 upload_to 在正常的文件系统中工作,否则您将收到权限错误。

      【讨论】:

      • 这对我不起作用,FileField 中的存储仍设置为原始定义,而不是 FileSystemStorage
      【解决方案3】:

      我也使用 S3Boto,但为了测试,我更喜欢自定义设置,包括使用文件系统存储。您可以在一个文件中声明您的自定义设置,然后您可以将其导入并在您的测试用例中使用。即使这样,您也可以模拟文件存储,以便文件不会实际写入磁盘。

      这是一个示例test_settings.py

      # myproject/myproject/test_settings.py
      
      from django.test import override_settings
      
      common_settings = override_settings(
          DEFAULT_FILE_STORAGE='django.core.files.storage.FileSystemStorage',
          PASSWORD_HASHERS=(
              'django.contrib.auth.hashers.UnsaltedMD5PasswordHasher',
          ),
      )
      

      用法:

      
      from django.test import TestCase
      
      from myproject.test_settings import common_settings
      
      @common_settings
      class MyTestCase(TestCase):
          """Tests go here"""
      

      关于模拟文件系统存储,您可以查看我的答案here on SO

      【讨论】:

      • 一个非常有用的例子,谢谢!,在我的情况下,我还覆盖了参数MEDIA_ROOT 设置这样的路径:os.path.join(os.path.dirname(settings.BASE_DIR), 'media_test')(之前导入:django.conf import settings),基于该特定存储配置的必填字段:docs.djangoproject.com/en/3.1/ref/files/storage/…
      【解决方案4】:

      我建议使用标准的 Django 存储进行测试,您可以在其中定义自定义存储路径,并在完成后清理测试套件中的路径。存储和路径都可以在设置中设置并覆盖进行测试。

      【讨论】:

      • 我应该在上面提到,我正在使用自定义存储类并在字段中为该模型设置它:models.FileField(storage=CustomS3Storage(...)) - 所以交换设置不会真正起作用。
      • @erikcw :您仍然可以在 TestCase 设置(或测试模块级别等)中覆盖模型的 FileField 存储。
      • @brunodesthuilliers 怎么样?
      • @NickBrady 文件存储是模型 FileField 的一个属性,你只需要将另一个存储实例重新分配给模型的 FileField,即MyModel.file.storage = SomeOtherStorage()
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-30
      • 1970-01-01
      • 2014-12-05
      • 1970-01-01
      • 1970-01-01
      • 2017-07-05
      • 1970-01-01
      相关资源
      最近更新 更多