好吧,起初我认为这是不可能的,因为 pytest-django 已经在模块级别导入了很多 django 东西,而且你无法通过钩子插入自己来击败它——它们都是在插件之后执行的是通过入口点加载的,所以 django 届时已经被导入了。
但是,查看pytest --help,请注意一个很少使用的选项,但在这种情况下会有所帮助:
$ pytest --help
...
test session debugging and configuration:
-p name early-load given plugin (multi-allowed). To avoid
loading of plugins, use the `no:` prefix, e.g.
`no:doctest`.
通过插件提前加载运行pymysql配置
因此,通过 -p arg 传递的自定义插件将比通过入口点加载的插件更早导入。解决方案现在很简单:编写一个导入和配置 pymysql 的小模块,并通过 -p arg 传递它:
# rematch/pymysql_hack.py
import pymysql
pymysql.install_as_MySQLdb()
测试调用:
$ PYTHONPATH=. pytest -p pymysql_hack -rapP server tests/server
我派生了rematch 项目来测试它,the jobs are looking good(第一个工作失败了,因为我懒得在所有需求文件中添加pymysql)。
放弃pytest,使用manage.py test
或者(这是我的第一个解决方案建议),您可以通过manage.py 运行测试,因此您可以在manage.py 之上添加pymysql 配置行,如pytest-django's FAQ 中所述实现自定义测试运行器:
pytest-django 旨在与pytest 命令配合使用,但如果您确实需要与manage.py test 集成,您可以像这样创建一个简单的测试运行器:
class PytestTestRunner(object):
"""Runs pytest to discover and run tests."""
def __init__(self, verbosity=1, failfast=False, keepdb=False, **kwargs):
self.verbosity = verbosity
self.failfast = failfast
self.keepdb = keepdb
def run_tests(self, test_labels):
"""Run pytest and return the exitcode.
It translates some of Django's test command option to pytest's.
"""
import pytest
argv = []
if self.verbosity == 0:
argv.append('--quiet')
if self.verbosity == 2:
argv.append('--verbose')
if self.verbosity == 3:
argv.append('-vv')
if self.failfast:
argv.append('--exitfirst')
if self.keepdb:
argv.append('--reuse-db')
argv.extend(test_labels)
return pytest.main(argv)
在你的 Django 设置中添加这个类的路径:
TEST_RUNNER = 'my_project.runner.PytestTestRunner'
并通过
调用测试
$ python manage.py test <django args> -- <pytest args>
但是,您将无法使用此解决方案通过直接调用 pytest 来运行测试。