运行 pytest 针对多个后端进行测试?

Running pytest tests against multiple backends?

我已经为与 Github API 交互的代码库构建了一系列测试(使用 pytest)(既调用它,又接收 webhooks)。

目前,这些测试 运行 针对 github 的半现实模拟:通过 Sentry's Responses and run through a fake github/git implementation (of the bits I need), which can also be interacted with directly from the tests cases. Any webhook which needs to be triggered uses Werkzeug's test client 拦截对 github 的调用以回调到所使用的 WSGI 应用程序作为 webhook 端点。

这很好用,速度很快(足够)并且是一个很好的默认设置,但我希望可以选择 运行 这些针对 github 本身的相同测试,这就是我感到困惑的地方:我需要将被测系统的当前实现(直接 "library" 访问代码库和模拟 github)切换为不同的(API 访问 "externally" 运行 代码库和实际 github),我不太确定如何进行。

我尝试使用 pytest_generate_tests 通过插件切换(代码库和 github 的)夹具实现,但我不太清楚这是否有效,到目前为止我尝试通过 pytest -p <package_name> 将本地文件作为插件加载到 pytest 中,但没有取得太大成功。

我想知道我的方向是否正确,在这种情况下,是否有人可以帮助使用 "local" 插件(不是通过安装工具安装的,也不是 conftest.py-基于)在 pytest.

不确定这是否有任何相关性,但我在 CPython 3.6 上使用 pytest 3.6.0 运行ning,请求 2.18.4,响应 0.9.0 和 Werkzeug 0.14.1。

有几种方法可以解决这个问题。默认情况下我会选择 运行 你的模拟测试,然后当命令行标志出现时针对 both 模拟和真实版本进行测试。

首先是比较简单的部分,添加一个命令行选项:

def pytest_addoption(parser):
    parser.addoption('--github', action='store_true',
                 help='Also test against real github')

现在可以通过 pytestconfig 夹具作为 pytestconfig.getoption('github') 使用,通常也可以间接使用,例如通过请求装置作为 request.config.getoption('github').

现在您需要使用此参数化任何需要与 github API 交互的测试,以便它们通过模拟和真实实例获得 运行。在不知道你的代码的情况下,Werkzeug 客户端听起来是个好点:把它变成一个夹具,然后它可以被参数化为 return 一个真实的客户端或你提到的测试客户端:

@pytest.fixture
def werkzeug_client(werkzeug_client_type):
    if werkzeug_client_type == 'real':
        return create_the_real_client()
    else:
        return create_the_mock_client()

def pytest_generate_tests(metafunc):
    if 'werkzeug_client_type' in metafunc.fixturenames:
        types = ['mock']
        if metafunc.config.getoption('github'):
            types.append('real')
        metafunc.parametrize('werkzeug_client_type', types)

现在,如果您将测试编写为:

def test_foo(werkzeug_client):
     assert werkzeug_client.whatever()

您将正常进行一次测试,使用 pytest --github 调用时将进行两次测试。

(请注意挂钩必须在 conftest.py 文件中,而固定装置可以在任何地方。要特别注意 pytest_addoption 挂钩实际上只应在顶层 conftest 文件中使用以避免混淆关于什么时候 hook 被 pytest 使用,什么时候不使用。所以你真的应该把所有这些代码放在顶层 conftest.py 文件中。)