如何将 pytest 与 bazel 一起使用?

Bor*_*ris 6 python pytest bazel

我有一个my_module.py实现my_module的文件和一个test_my_module.py执行import my_module并运行一些用pytest编写的测试的文件。

通常我cd通过进入包含这两个文件的目录然后执行测试来运行测试

pytest
Run Code Online (Sandbox Code Playgroud)

现在我想使用 Bazel。我已添加my_module.py为 apy_binary但我不知道调用我的测试的正确方法是什么。

Dav*_*ard 11

创建可重用的代码,不需要pytest在每个带有测试的 python 文件末尾添加调用。您可以创建一个py_test规则来调用包装器/运行器pytest并保留所有参数。然后围绕 py_test 创建一个宏。我在 Bazel 实验中解释了详细的解决方案:Python (3), linter & pytest,并附有源代码链接。

创建 python 工具(包装对 pytest 或仅 pylint 的调用)tools/pytest/pytest_wrapper.py

import sys
import pytest

# if using 'bazel test ...'
if __name__ == "__main__":
    sys.exit(pytest.main(sys.argv[1:]))


Run Code Online (Sandbox Code Playgroud)

在中创建宏tools/pytest/defs.bzl

"""Wrap pytest"""

load("@rules_python//python:defs.bzl", "py_test")
load("@my_python_deps//:requirements.bzl", "requirement")

def pytest_test(name, srcs, deps = [], args = [], data = [], **kwargs):
    """
        Call pytest
    """
    py_test(
        name = name,
        srcs = [
            "//tools/pytest:pytest_wrapper.py",
        ] + srcs,
        main = "//tools/pytest:pytest_wrapper.py",
        args = [
            "--capture=no",
            "--black",
            "--pylint",
            "--pylint-rcfile=$(location //tools/pytest:.pylintrc)",
            # "--mypy",
        ] + args + ["$(location :%s)" % x for x in srcs],
        python_version = "PY3",
        srcs_version = "PY3",
        deps = deps + [
            requirement("pytest"),
            requirement("pytest-black"),
            requirement("pytest-pylint"),
            # requirement("pytest-mypy"),
        ],
        data = [
            "//tools/pytest:.pylintrc",
        ] + data,
        **kwargs
    )

Run Code Online (Sandbox Code Playgroud)

暴露一些资源tools/pytest/BUILD.bazel

exports_files([
    "pytest_wrapper.py",
    ".pylintrc",
])


Run Code Online (Sandbox Code Playgroud)

从你的包中调用它BUILD.bazel

load("//tools/pytest:defs.bzl", "pytest_test")
...

pytest_test(
    name = "test",
    srcs = glob(["*.py"]),
    deps = [
        ...
    ],
)

Run Code Online (Sandbox Code Playgroud)

then 调用bazel test //...意味着pylintpytestblack都是测试流程的一部分。


Eri*_*lib 6

将以下代码添加到文件中test_my_module.py并将测试脚本标记为 apy_test而不是py_binary在您的BUILD文件中:

if __name__ == "__main__":
    import pytest
    raise SystemExit(pytest.main([__file__]))
Run Code Online (Sandbox Code Playgroud)

然后你可以运行你的测试 bazel test test_my_module

  • 必须做 pytest 不需要的事情来满足 bazel 这种方式是 PITA,我认为这是不必要的负担 (3认同)
  • 将 `[__file__]` 替换为 `sys.argv` 允许转发使用 `pytest_addoption` 添加的自定义 pytest 选项。 (2认同)
  • 虽然这回答了问题,但在从 python 的 pytest 迁移到 bazel 的 py_test 时,我遇到了其他问题。我在此答案中捕获了这些问题:/sf/answers/4975983981/ (2认同)