设置 pymysql 以与 django、pytest 和 pytest-django 一起工作
Setting up pymysql to work with django, pytest and pytest-django
我建立了一个 Django 网站以及基于 pytest
和 pytest-django
包的测试。我希望获得 PyMySQL
包以与我的测试和生产设置一起使用。
我明白为了让 PyMySQL 将自己暴露为 mysqldb
模块以便 django(和其他模块)可以使用它我应该将以下代码片段放在代码的开头。
import pymysql
pymysql.install_as_MySQLdb()
我多次尝试在我的代码中的不同位置调用上述函数,但 none 似乎很早就被 pytest 检测到了。
这包括将片段放在 conftest.py:pytest_configure
中,放在我的 django 项目的 manage.py
文件中,等等。都没有用。
我从 mysqlclient
切换到 PyMySQL
的原因是 mysqlclient
似乎无法与 travis.org 一起工作,一旦我在 .travis.yml
:
addons:
mariadb: '10.0'
为了使用 MariaDB 而不是 vanilla MySQL。
让 travis 使用 python mysqlclient
包也可以解决我的问题,但我也无法完成。
作为参考,this 是 PR 的 travis 工作,以防我错过了一些重要的事情。
好吧,一开始我认为这是不可能的,因为 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
我 fork 了 rematch
项目来测试这个,the jobs are looking good(第一个作业失败了,因为我懒得在所有需求文件中添加 pymysql
)。
放弃pytest
,使用manage.py test
或者(这是我的第一个解决方案建议),您可以通过 manage.py
运行 测试,因此您可以在 manage.py
之上添加 pymysql
配置行, 按照 pytest-django
's FAQ:
中的描述实施自定义测试 运行ner
pytest-django is designed to work with the pytest
command, but if you really need integration with manage.py test
, you can create a simple test runner like this:
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)
Add the path to this class in your Django settings:
TEST_RUNNER = 'my_project.runner.PytestTestRunner'
并通过
调用测试
$ python manage.py test <django args> -- <pytest args>
但是,您将无法通过使用此解决方案直接调用 pytest
来 运行 测试。
我通过添加
解决了同样的问题
import pymysql
pymysql.install_as_MySQLdb()
到我的 python3.6/site-packages/pytest_django/init.py 文件
我建立了一个 Django 网站以及基于 pytest
和 pytest-django
包的测试。我希望获得 PyMySQL
包以与我的测试和生产设置一起使用。
我明白为了让 PyMySQL 将自己暴露为 mysqldb
模块以便 django(和其他模块)可以使用它我应该将以下代码片段放在代码的开头。
import pymysql
pymysql.install_as_MySQLdb()
我多次尝试在我的代码中的不同位置调用上述函数,但 none 似乎很早就被 pytest 检测到了。
这包括将片段放在 conftest.py:pytest_configure
中,放在我的 django 项目的 manage.py
文件中,等等。都没有用。
我从 mysqlclient
切换到 PyMySQL
的原因是 mysqlclient
似乎无法与 travis.org 一起工作,一旦我在 .travis.yml
:
addons:
mariadb: '10.0'
为了使用 MariaDB 而不是 vanilla MySQL。
让 travis 使用 python mysqlclient
包也可以解决我的问题,但我也无法完成。
作为参考,this 是 PR 的 travis 工作,以防我错过了一些重要的事情。
好吧,一开始我认为这是不可能的,因为 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
我 fork 了 rematch
项目来测试这个,the jobs are looking good(第一个作业失败了,因为我懒得在所有需求文件中添加 pymysql
)。
放弃pytest
,使用manage.py test
或者(这是我的第一个解决方案建议),您可以通过 manage.py
运行 测试,因此您可以在 manage.py
之上添加 pymysql
配置行, 按照 pytest-django
's FAQ:
pytest-django is designed to work with the
pytest
command, but if you really need integration withmanage.py test
, you can create a simple test runner like this: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)
Add the path to this class in your Django settings:
TEST_RUNNER = 'my_project.runner.PytestTestRunner'
并通过
调用测试$ python manage.py test <django args> -- <pytest args>
但是,您将无法通过使用此解决方案直接调用 pytest
来 运行 测试。
我通过添加
解决了同样的问题import pymysql
pymysql.install_as_MySQLdb()
到我的 python3.6/site-packages/pytest_django/init.py 文件