流控制和失败:不允许数据库访问,请使用“ django_db”。...错误

时间:2018-09-28 12:59:35

标签: python django pytest pytest-django

我的一项芹菜任务遇到一些奇怪的行为。

def run_single_test(test_name_or_decorator):
    # get dict of test names, test paths
    test_dict = get_single_test_names()

    # check to see if test is in the dict
    if test_name_or_decorator not in test_dict:
        return 'The requested test could not be found.'

    for test_name, test_path in test_dict.items():
        # if test name is valid run associated test
        if test_name == test_name_or_decorator:
            pytest.main(['-p', 'no:django','--json-report', test_path])
            report = return_test_result_json('.report.json')
            report_id = str(uuid.uuid4())
            test_run_data = TestResults.objects.create(name=report_id, data=report)

    return 'this is your test report: {}'.format(get_report(test_run_data.id))

此任务将执行pytest.main()命令并运行测试,但是当使用.create()将.report.json插入Db时,出现以下错误:

Failed: Database access not allowed, use the "django_db" mark, or the "db" or "transactional_db" fixtures to enable it.

现在,如果我将for test_name....块中的所有功能都简化了,并将其移入自己的功能中,一切正常:

def run_single_test_path():

    test_path = 'test_folder/test_file.py::TestClass::specific_test_name'
    pytest.main(['-p', 'no:django','--json-report', test_path])
    report = return_test_result_json('.report.json')
    report_id = str(uuid.uuid4())
    test_run_data = TestResults.objects.create(name=report_id, data=report)
    return 'this is your test report: {}'.format(get_report(test_run_data.id))

我得到了预期的回报:

"this is your test report: {'created': datetime.datetime(2018, 9, 27, 15, 51, 59, 297991, tzinfo=<UTC>), 'summary': {'total': 1, 'passed': 1}, 'exitcode': 0}"

使用其他相同pytest.main()和.create()的变体的其他任务没有发生此行为。 另一个观察结果是,如果我先运行此任务,并且抛出数据库访问错误,则所有其他任务将因相同的错误而失败。

我的工作理论是for循环或if导致.create()异常,但是我绝对不知道为什么。

1 个答案:

答案 0 :(得分:3)

通常,pytest.main并不关心测试运行后剩下的全局状态,因为假定该过程在测试运行完成后以返回的退出代码终止。因此,如果您在pytest.main完成之后在同一进程中运行代码,则必须对范围的修改保持谨慎。其中之一是在django测试配置中由pytest-django激活的数据库阻止程序;测试执行完成后,它不会被停用。要取消激活,请在代码中明确执行以下操作:

import pytest_django

def run_single_test(test_name_or_decorator):
    ...
    pytest.main(['-p', 'no:django','--json-report', test_path])
    pytest_django.plugin._blocking_manager.unblock()

    # database access unblocked, you can run the query now
    test_run_data = TestResults.objects.create(name=report_id, data=report)

或添加将隐式执行此操作的运行后挂钩,例如:

# conftest.py

import pytest_django

def pytest_unconfigure(config):
    pytest_django.plugin._blocking_manager.unblock()