3

我正在检查 Django 的设置模块是如何构建的,以及override_settings装饰器在测试时如何处理设置,我只是看不到这个装饰器的实现如何在并行运行测试时避免出现问题。

我看到它在enable它分配给设置_wrapped属性的方法中应用了更改的设置值,并且它存储了先前值的副本,然后在disable方法中恢复。当我连续执行它时,这对我来说很好。但是当并行运行测试时,如果不影响也使用装饰器的其他测试,我无法看到它是如何工作的,假设覆盖相同的值。我看到的是,访问settings.OVERRIDDEN_SETTING时,最新执行的测试设置的值会随处返回。事实上,这个设置覆盖也应该影响其他测试中返回的值,即使它们没有被修饰。

我的意思是,如果我们有这两个测试:

@override_settings(SETTING=1):
def test_1(self):
    ...
    ...
    print(settings.SETTING)

@override_settings(SETTING=2):
def test_2(self):
    ...
    ...
    print(settings.SETTING)

def test_3(self):
    ...
    ...
    print(settings.SETTING)

如果它们并行运行,假设test_1被执行,开始执行它的代码,同时在语句执行test_2之前被调用,通过检查装饰器实现,我希望它们都打印为他们的结果. 并且取决于它何时执行,如果它也并行运行,将返回原始值 1 或 2。printtest_12printtest_3

一定有一些我没有考虑到的东西,因为我认为这段代码在经过这么长时间之后不会容易出现这种竞争条件。

任何帮助理解这一点将不胜感激。

4

1 回答 1

2

并行测试在不同的进程中运行,每个进程都访问自己的settings.

因此,Djangooverride_settings不需要专门处理并行测试。

我们可以凭经验验证使用不安全的直接修改而不是override_settings(注意sleep确保test_3运行后test_1test_2修改值):

from time import sleep

from django.conf import settings
from django.test import TestCase


class TestOverrideSettings1(TestCase):

    # @override_settings(SETTING=1)
    def test_1(self):
        settings.SETTING = 1
        print(settings.SETTING)


class TestOverrideSettings2(TestCase):

    # @override_settings(SETTING=2)
    def test_2(self):
        settings.SETTING = 2
        print(settings.SETTING)


class TestOverrideSettings3(TestCase):

    def test_3(self):
        sleep(1)
        print(settings.SETTING)

运行测试:

$ python manage.py test
1
.2
.2
.

并行运行测试:

$ python manage.py test --parallel
1
2
..0
.
于 2021-10-28T10:12:01.407 回答