【问题标题】:How do I run a test in Django using production data (Read only)?如何使用生产数据在 Django 中运行测试(只读)?
【发布时间】:2019-02-13 07:00:33
【问题描述】:

我想在 Django 中运行测试,但为了运行测试,我需要访问生产数据库中的数据(我不想设置一个全新的数据库进行测试)。

如何使用生产数据库中的这些数据而不允许在我的脚本中进行写访问?我不希望此测试产生任何影响,但我需要访问此数据才能运行此测试。仅仅为了获取几行数据就必须启动(并支付费用)一个全新的数据库似乎很荒谬,有什么建议吗?

【问题讨论】:

  • 为什么不想建立一个测试数据库?
  • 支付和维护两个数据库并使它们保持同步似乎很奇怪,如果这就是我所需要的,从生产中读取不是更容易吗?
  • 如果您不关心您的生产数据,那么作为开发人员可能会更容易,但没有组织会故意让开发人员针对生产运行测试。如果您的数据库包含欧盟公民的 PII,这样做也是违法的……设置测试环境非常基础,不是吗?
  • 使用您的产品数据库中的固定装置,并将它们加载到测试机本地 sqlite 测试数据库中。这不是更安全吗?

标签: python django python-3.x unit-testing


【解决方案1】:

我建议不要这样做。运行测试时,您将无法完全控制数据库的状态,并且测试的通过可能取决于生产数据库的内容。并且不可能在边缘情况发生之前对其进行测试。更不用说如果你搞砸了,你会冒着用测试数据填充生产数据库或破坏生产数据库中的记录的风险。

Django 使创建测试数据库变得非常简单。使用命令python manage.py test [app_name] 时,将为您创建一个测试数据库,其设置与您的生产/开发数据库相同。

要获得此功能,Django 测试文档说明:

如果您的测试依赖于数据库访问,例如创建或查询模型,请务必将您的测试类创建为 django.test.TestCase 的子类,而不是 unittest.TestCase。

这里有更多关于 Django 测试数据库的信息:https://docs.djangoproject.com/en/2.1/topics/testing/overview/#the-test-database

关于维护测试数据库的问题,Django 在测试运行之前启动数据库,并在测试完成后销毁数据库。测试数据库也在您的本地机器上创建(假设您在本地机器上运行它)。所以我认为定价应该不是问题。

编辑: 在测试之前填充测试数据库:

1. 在测试逻辑开始之前在测试中创建实例。这些将在测试完成时被销毁。示例:

class Tester(TestCase):
    def test_works(self):
        instance = Model.create(data=data)
        # then run your test logic

2. 在测试类的setUp 方法中创建实例。 setUp 中的所有内容都将在类的每个测试方法之前(重新)创建,并在每个测试完成后销毁。示例:

class Tester(TestCase):
    def setUp(self):
        self.instance = Model.create(data=data)

    def test_works(self):
        # run test logic with access to self.instance

3. 在运行测试之前使用固定装置进行填充。在您正在测试的任何应用程序中的fixtures 目录中为您的模型的某些实例定义数据(可能需要创建目录)。您可以在 json 或 yaml 中定义它们,我相信其他格式。然后在你的测试中:

class Tester(TestCase):
    def setUp(self):
        fixtures = ['/myapp/fixtures/dump.json']

    def test_works(self):
        # test logic and you can access all the instances created from the data in dump.json

更多关于固定装置的信息:https://django-testing-docs.readthedocs.io/en/latest/fixtures.html

如果您希望您的测试数据库具有与生产数据库相似的数据,您可以从生产数据库中提取数据并将其保存在夹具中。

【讨论】:

  • 但是测试数据库没有填充任何数据,每次我在测试数据库上运行查询时,结果都是空的?
  • @superdee 正确,这确实是一个功能,因为您将完全和明确地控制数据库的内容,并且您的测试将更加独立。在每个测试中,您可以创建一些对象,或者在测试类的setUp 方法中创建对象,或者使用fixture。
  • 我可以用生产数据库中已有的数据填充测试数据库吗?这是一个固定装置吗,现在我一直在手动创建和保存模型,但是从生产数据库中填充测试数据库中的数据而不是复制和粘贴每一行会很好
  • @superdee 我刚刚对帖子进行了编辑,我认为这在一定程度上解决了这个问题。只需找到一种将生产数据库中的数据转储为 json 格式(或类似格式)的方法。然后将其存放在固定装置中。
【解决方案2】:

不要那样做。您必须使用测试的setUp 来构建要测试的情况。不要使用固定装置,因为您必须维护它们,将来您将更改模型并且您的固定装置也必须更新。这很烦人。

如果您进行了良好的单元测试,您可以mock 您的模型并测试您想要测试的功能。当我想测试一个方法时,我经常这样做。

如果您需要,您可以创建一些实用程序函数来帮助您设置创建模型和相关模型以构建您想要测试的环境所需的情况。

【讨论】:

    【解决方案3】:

    我同意其他人的观点,出于各种原因,这是一个坏主意。如果您想继续使用它,请设置一个具有只读权限的单独数据库用户。如何执行此操作取决于您使用的数据库服务器。

    仔细检查您是否确实在测试中使用了只读用户的凭据。

    【讨论】:

    • 作为附录,系统检查框架可能是针对实时数据库运行“测试”的更合适的工具。它还表明,与这里的大多数答案相比,这绝不是一个坏主意:它直接内置在框架中。
    猜你喜欢
    • 2010-12-11
    • 2017-10-04
    • 2022-07-05
    • 2022-11-22
    • 1970-01-01
    • 2014-07-26
    • 2014-07-17
    • 1970-01-01
    • 2013-11-11
    相关资源
    最近更新 更多