django -如何检测测试环境(检查/确定测试是否正在运行)

ybzsozfc  于 2023-02-06  发布在  Go
关注(0)|答案(9)|浏览(349)

如何检测视图是否在测试环境中被调用(例如,从manage.py test)?

#pseudo_code
def my_view(request):
    if not request.is_secure() and not TEST_ENVIRONMENT:
        return HttpResponseForbidden()
kuhbmx9i

kuhbmx9i1#

把这个放到你的网站上settings.py:

import sys

TESTING = len(sys.argv) > 1 and sys.argv[1] == 'test'

测试第二个命令行参数(./manage.py之后)是否为test,然后可以从其他模块访问该变量,如下所示:

from django.conf import settings

if settings.TESTING:
    ...

这样做有充分的理由:假设你正在访问一些后端服务,而不是Django的模型和数据库连接,那么你可能需要知道何时调用生产服务和测试服务。

gz5pxeao

gz5pxeao2#

创建您自己的TestSuiteRunner子类并更改设置或对应用程序的其余部分执行任何其他需要的操作。您可以在设置中指定测试运行程序:

TEST_RUNNER = 'your.project.MyTestSuiteRunner'

一般来说,您并不想这样做,但如果您确实需要它,它会起作用。

from django.conf import settings
from django.test.simple import DjangoTestSuiteRunner

class MyTestSuiteRunner(DjangoTestSuiteRunner):
    def __init__(self, *args, **kwargs):
        settings.IM_IN_TEST_MODE = True
        super(MyTestSuiteRunner, self).__init__(*args, **kwargs)
zyfwsgd6

zyfwsgd63#

看看request.META['SERVER_NAME']

def my_view(request):
    if request.META['SERVER_NAME'] == "testserver":
        print "This is test environment!"
yfwxisqw

yfwxisqw4#

在Django中,还有一种方法可以临时覆盖单元测试中的设置,这在某些情况下可能是一种更简单/更干净的解决方案。
您可以在测试中执行此操作:

with self.settings(MY_SETTING='my_value'):
    # test code

或者将其添加为测试方法上的装饰器:

@override_settings(MY_SETTING='my_value')
def test_my_test(self):
    # test code

您还可以为整个测试用例类设置装饰器:

@override_settings(MY_SETTING='my_value')
class MyTestCase(TestCase):
    # test methods

更多信息请查看Django文档:https://docs.djangoproject.com/en/1.11/topics/testing/tools/#django.test.override_settings

gkl3eglg

gkl3eglg5#

我认为最好的方法是使用自己的设置文件(即settings/ www.example.com)运行测试tests.py,该文件可以如下所示(第一行从local.py设置文件导入设置):

from local import *
TEST_MODE = True

然后执行ducktyping检查是否处于测试模式。

try:
    if settings.TEST_MODE:
        print 'foo'
except AttributeError:
    pass
jdg4fx2g

jdg4fx2g6#

如果您有多个用于不同环境的设置文件,您所需要做的就是创建一个用于测试的设置文件。
例如,您的设置文件为:

your_project/
      |_ settings/
           |_ __init__.py
           |_ base.py  <-- your original settings
           |_ testing.py  <-- for testing only

在www.example.com中testing.py,添加一个TESTING标志:

from .base import *

TESTING = True

在您的应用程序中,您可以访问settings.TESTING以检查您是否处于测试环境中。
要运行测试,请用途:

python manage.py test --settings your_project.settings.testing
lsmepo6l

lsmepo6l7#

虽然没有官方的方法来判断我们是否在测试环境中,但Django实际上为我们留下了一些线索。默认情况下,Django的测试运行器会自动将所有Django发送的电子邮件重定向到一个虚拟的发件箱。这是通过在一个名为setup_test_environment的函数中替换EMAIL_BACKEND来实现的,该函数反过来由DiscoverRunner的一个方法调用。我们可以检查settings.EMAIL_BACKEND是否被设置为'django.core.mail.backends.locmem.EmailBackend'.这意味着我们处于测试环境中.
一个不那么笨拙的解决方案是跟随开发人员的脚步,通过子类化DisoverRunner添加我们自己的设置,然后覆盖setup_test_environment方法。

lzfw57am

lzfw57am8#

借用@Tobia的回答,我认为在www.example.com中实现更好settings.py如下所示:

import sys
try:
    TESTING = 'test' == sys.argv[1]
except IndexError:
    TESTING = False

这将防止它捕获类似./manage.py loaddata test.json./manage.py i_am_not_running_a_test的内容

ztigrdn8

ztigrdn89#

我想在测试中排除一些数据迁移,并在Django 3.2项目中提出了这个解决方案:

class Migration(migrations.Migration):
    def apply(self, project_state, schema_editor, collect_sql=False):
        import inspect
        if 'create_test_db' in [i.function for i in inspect.stack()]:
            return project_state
        else:
            return super().apply(project_state, schema_editor, collect_sql=collect_sql)

我还没有在其他地方看到过这样的建议,就我的目的而言,这是相当干净的。当然,如果Django在某个时间点更改了create_test_db方法的名称(或apply方法的返回值),它可能会中断,但修改它应该相当简单,因为很可能堆栈中存在一些方法,而在非测试迁移运行期间并不存在。

相关问题