python 如何在生产数据库上运行 django 单元测试?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1646468/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 22:47:58  来源:igfitidea点击:

How to run django unit-tests on production database?

pythondjangounit-testing

提问by James

i'm starting the TDD development attitude and am writting unit-tests for my django application. I'm aware of fixtures and know that's the way tests should be executed, but for a given test i do need to execute it on the whole database, and json fixture for 10+ million row database is not something i'd like to handle, moreover, this test is "read-only".

我开始采用 TDD 开发态度,并正在为我的 Django 应用程序编写单元测试。我知道fixtures并且知道这是应该执行测试的方式,但是对于给定的测试,我确实需要在整个数据库上执行它,并且10+百万行数据库的jsonfixture不是我想要处理的,而且,这个测试是“只读的”。

So the question is how are you setting up your test suites to run on the production database? I imagine it could be as easy as adding the DATABASE_NAME setting in the setUp method of certain test. But the settings.DATABASE_NAME="prod_db" results in "NameError: global name 'settings' is not defined" while running the test. Moreover, there is a risk described in http://code.djangoproject.com/ticket/11987, that you can accidentally delete a production database.

所以问题是您如何设置测试套件以在生产数据库上运行?我想这就像在某些测试的 setUp 方法中添加 DATABASE_NAME 设置一样简单。但是 settings.DATABASE_NAME="prod_db" 在运行测试时导致“NameError: global name 'settings' is not defined”。此外,http://code.djangoproject.com/ticket/11987 中描述了一个风险,您可能会意外删除生产数据库。

So, how is it possible, or, even better, what is best practice, to run a single test of a test suite on a production database instead of temporary one?

那么,如何在生产数据库而不是临时数据库上运行测试套件的单个测试,或者更好的是,最佳实践是什么?

Cheers in advance for any opinions!

提前为任何意见干杯!

采纳答案by S.Lott

First, if you're running it on the production database, it isn't much of a "unit" test.

首先,如果你在生产数据库上运行它,它就不是一个“单元”测试。

It's a first-class batch job and needs to be treated like a first-class production batch job.

这是一流的批处理作业,需要像一流的生产批处理作业一样对待。

You cam't to use the Django testcommand for looking at production data. It always creates an empty database which is populated from fixtures in the TestCase.

您不能使用 Djangotest命令查看生产数据。它始终创建一个空数据库,该数据库由 TestCase 中的装置填充。

You could make your production database processing a proper management command. This has the environment all properly configured so that your command can simply use the Django ORM to process your data.

你可以让你的生产数据库处理一个适当的管理命令。这已经正确配置了环境,以便您的命令可以简单地使用 Django ORM 来处理您的数据。

The alternative is to be sure that you configure your settings. Either use the DJANGO_SETTINGS_MODULEenvironment variable or use the settings.configure()function to create an environment.

另一种方法是确保您配置了您的设置。要么使用DJANGO_SETTINGS_MODULE环境变量,要么使用settings.configure()函数创建环境。

You can then import the models and do the processing you want to do against the production database.

然后,您可以导入模型并针对生产数据库执行您想要执行的处理。

You can call it "test" if you want to, but you're looking at production data, so it's got to be treated like production application with respect to getting the settings file and using the proper ORM configuration.

如果您愿意,您可以将其称为“测试”,但您正在查看生产数据,因此在获取设置文件和使用正确的 ORM 配置方面,必须将其视为生产应用程序。

回答by James

In case someone googles here searching for the solution for a given problem, here is the skeleton on how to perform unit tests on django production database. Check the django docs section here, for the file/directory structure, and instructions on where to put the given code. It should go in yourapp/management/commands/newcommandname.py, and both the management and commands folders should contain empty __init__.pyfiles which makes python treat them as valid modules.

如果有人在这里谷歌搜索给定问题的解决方案,这里是关于如何在 django 生产数据库上执行单元测试的框架。检查此处的 django 文档部分,了解文件/目录结构以及有关放置给定代码的位置的说明。它应该进入yourapp/management/commands/newcommandname.py,并且管理和命令文件夹都应该包含空__init__.py文件,这使得 python 将它们视为有效模块。

The test suite can by run as:

测试套件可以通过以下方式运行:

$python manage.py newcommandname

$python manage.py newcommandname

And here comes the code you should put in yourapp/management/commands/newcommandname.py:

这是你应该输入的代码yourapp/management/commands/newcommandname.py

from django.core.management.base import BaseCommand
import unittest

class Command(BaseCommand):
    help = """
    If you need Arguments, please check other modules in 
    django/core/management/commands.
    """

    def handle(self, **options):
        suite = unittest.TestLoader().loadTestsFromTestCase(TestChronology)
        unittest.TextTestRunner().run(suite)


class TestChronology(unittest.TestCase):
    def setUp(self):
        print "Write your pre-test prerequisites here"

    def test_equality(self):
        """
        Tests that 1 + 1 always equals 2.
        """
        from core.models import Yourmodel
        self.failUnlessEqual(1 + 1, 2)

回答by Noel Puru

This TEST_RUNNER works on Django 1.3

此 TEST_RUNNER 适用于 Django 1.3

from django.test.simple import DjangoTestSuiteRunner as TestRunner

class DjangoTestSuiteRunner(TestRunner):
    def setup_databases(self, **kwargs):
        pass

    def teardown_databases(self, old_config, **kwargs):
        pass

回答by Gregor Müllegger

A unittest is meant to test without any sideeffects. Though your test would be nothing that is known as unittest. If you want to do it anyway, you can use a custom test runner that is setting up the database (or in your case using the existing db).

单元测试旨在进行无任何副作用的测试。尽管您的测试不是所谓的单元测试。如果您无论如何都想这样做,您可以使用设置数据库的自定义测试运行程序(或者在您的情况下使用现有数据库)。

You can set the TEST_RUNNER setting in your settings.py file. The default is locate in django.test.simple.run_tests. You can look at the source here: http://code.djangoproject.com/browser/django/trunk/django/test/simple.py

您可以在 settings.py 文件中设置 TEST_RUNNER 设置。默认位于django.test.simple.run_tests. 你可以在这里查看源代码:http: //code.djangoproject.com/browser/django/trunk/django/test/simple.py

Copy and paste the code in a new file and remove the following lines from the code:

将代码复制并粘贴到新文件中,并从代码中删除以下行:

connection.creation.create_test_db(verbosity, autoclobber=not interactive)
...
connection.creation.destroy_test_db(old_name, verbosity)

connection.creation.create_test_db(verbosity, autoclobber=not interactive)
...
connection.creation.destroy_test_db(old_name, verbosity)

This will prevent django from creating a test database and reseting the database configuration of your settings file.

这将阻止 django 创建测试数据库并重置设置文件的数据库配置。

回答by Michel Samia

Not a good idea, but if you know what you are doing (basically breaking your production) you can check this setting:

不是一个好主意,但如果你知道你在做什么(基本上破坏你的生产)你可以检查这个设置:

https://docs.djangoproject.com/en/2.2/ref/settings/#test

https://docs.djangoproject.com/en/2.2/ref/settings/#test

DATABASES = {
  'default': {
     ...
     'TEST': {
        'NAME': 'your prod db'
     }
}