如何布局 PyTest Fixtures 和多行字符串?

How to layout PyTest Fixtures and multi-line strings?

我正在寻找一种以更优雅的方式布置 pytest 装置的方法。

现在我的测试目录如下所示:

.
└── test
    └── cli
        ├── test_compile.py
        └── testdata
            └── ...

在test_compile中,我有一系列测试,每个测试都使用一个夹具作为输入(一个字符串)。现在,我在文件底部布置了所有多行字符串。所以它看起来像这样:

def test_parse_zero_steps():
    _testStep(1, 1, py_zero_steps, "ZERO_STEPS")


py_zero_steps = """
# ---

foo = "bar"

# +
import tensorflow
"""

_testStep 是一个内部函数,我将一系列参数传递给它以断言我是否正确解析了 blob。

这已经很笨重了,我有 20 多个字符串需要在这里使用来测试边缘情况。有 elegant/more-pythonic 的方法吗?我查看了看起来更好的参数化 (https://docs.pytest.org/en/6.2.x/example/parametrize.html),但仍然不清楚我应该如何处理这些 large/annoying 字符串。将它们全部放在自己单独的文件中?

假设您所有的测试都将调用 _testSteps,最好的方法可能是使用 parametrize,正如问题中已经提到的那样。测试数据可以在一个单独的文件中,可以是 Python 变量或函数,也可以是 json 文件(或其他格式),可以被 parametrize.

这是一个使用 Python 函数的简单示例:

def params():
    return [
        (
            1, 1, """
# ---

foo = "bar"

# +
import tensorflow
""",
            "ZERO_STEPS"
        ),
        (
            1, 2, """
# something sensible
""",
            "ONE_STEP"
        ),
...
    ]

这可以用于 parametrize:

@pytest.mark.parametrize("arg1, arg2, text, name", params(),
                         ids=[p[3] for p in params()])
def test_parse(arg1, arg2, text, name):
    _testStep(arg1, arg2, text, name)

输出如下:

$ pytest -vv
...
test_steps.py::test_parse[ZERO_STEPS] PASSED
test_steps.py::test_parse[ONE_STEP] PASSED

请注意,我已将测试 ID 设置为 name 参数以避免出现不可读的测试名称。这只是一个示例,但由于字符串较长,因此调整 ids 是有意义的。如果没有它,输出将如下所示:

test_steps.py::test_parse[1-1-\n# ---\n\nfoo = "bar"\n\n# +\nimport tensorflow\n-ZERO_STEPS] PASSED
test_steps.py::test_parse[1-2-\n# something sensible\n-ONE_STEP] PASSED

这不是完全可读的。