设置 pymysql 以与 django、pytest 和 pytest-django 一起工作

Setting up pymysql to work with django, pytest and pytest-django

我建立了一个 Django 网站以及基于 pytestpytest-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 文件