python - 如何测试 pytest 夹具本身?
问题描述
测试 pytest 夹具本身的正确方法是什么。请不要将其与在测试中使用夹具混淆。我只想自己测试灯具的正确性。
当尝试在测试中调用并执行它们时,我面临:
Fixture "app" called directly. Fixtures are not meant to be called directly
对此的任何意见将不胜感激。关于这个主题的文档没有给我有意义的指导:https ://docs.pytest.org/en/latest/deprecations.html#calling-fixtures-directly
测试夹具本身的动机来了,因为当我们的测试由于夹具中的错误而失败时,这在我们的 TAP 文件中没有正确跟踪,是什么促使我单独测试夹具。
解决方案
pytest
有一个pytester
用于测试pytest
自身和插件的插件;它在不影响当前测试运行的隔离运行中执行测试。例子:
# conftest.py
import pytest
pytest_plugins = ['pytester']
@pytest.fixture
def spam(request):
yield request.param
夹spam
具有一个问题,它只能用于参数化测试;一旦在未参数化的测试中请求它,它将引发AttributeError
. 这意味着我们不能通过这样的常规测试来测试它:
def test_spam_no_params(spam):
# too late to verify anything - spam already raised in test setup!
# In fact, the body of this test won't be executed at all.
pass
相反,我们使用插件testdir
提供的夹具在隔离的测试运行中执行测试:pytester
import pathlib
import pytest
# an example on how to load the code from the actual test suite
@pytest.fixture
def read_conftest(request):
return pathlib.Path(request.config.rootdir, 'conftest.py').read_text()
def test_spam_fixture(testdir, read_conftest):
# you can create a test suite by providing file contents in different ways, e.g.
testdir.makeconftest(read_conftest)
testdir.makepyfile(
"""
import pytest
@pytest.mark.parametrize('spam', ('eggs', 'bacon'), indirect=True)
def test_spam_parametrized(spam):
assert spam in ['eggs', 'bacon']
def test_spam_no_params(spam):
assert True
""")
result = testdir.runpytest()
# we should have two passed tests and one failed (unarametrized one)
result.assert_outcomes(passed=3, error=1)
# if we have to, we can analyze the output made by pytest
assert "AttributeError: 'SubRequest' object has no attribute 'param'" in ' '.join(result.outlines)
为测试加载测试代码的另一个方便的可能性是testdir.copy_example
方法。在 中设置根路径pytest.ini
,例如:
[pytest]
pytester_example_dir = samples_for_fixture_tests
norecursedirs = samples_for_fixture_tests
现在创建samples_for_fixture_tests/test_spam_fixture/test_x.py
包含以下内容的文件:
import pytest
@pytest.mark.parametrize('spam', ('eggs', 'bacon'), indirect=True)
def test_spam_parametrized(spam):
assert spam in ['eggs', 'bacon']
def test_spam_no_params(spam):
assert True
(它与之前作为字符串传递的代码相同testdir.makepyfile
)。上述测试更改为:
def test_spam_fixture(testdir, read_conftest):
testdir.makeconftest(read_conftest)
# pytest will now copy everything from samples_for_fixture_tests/test_spam_fixture
testdir.copy_example()
testdir.runpytest().assert_outcomes(passed=3, error=1)
这样,您不必在测试中将 Python 代码维护为字符串,还可以通过使用pytester
. 您还可以通过pytester_example_path
标记配置测试数据根:
@pytest.mark.pytester_example_path('fizz')
def test_fizz(testdir):
testdir.copy_example('buzz.txt')
将查找fizz/buzz.txt
相对于项目根目录的文件。
有关更多示例,请务必查看文档中的测试插件部分;pytest
另外,您可能会找到我对如何测试 pytest 夹具是否引发异常的问题的其他答案?很有帮助,因为它包含该主题的另一个工作示例。我还发现直接研究代码非常有帮助,因为遗憾的是没有为它提供广泛的文档,但代码几乎是自我记录的。Testdir
pytest
推荐阅读
- python - 如何修复自定义消息框以在父 python pyqt5 的新线程中工作
- deep-learning - 当输出是浮点数数组时,pytorch中的适当损失函数
- javascript - 在 React Native 中向数组添加新对象
- java - 安装调试 apk 时 android studio 中出现未知错误
- c - 如何在没有 itoa() 的情况下将任何变量更改为字符串?
- c# - 如何使用其他方法在方法中运行 ProgressBar
- android-studio - 无法从一项活动转移到另一项活动
- azure-devops - 通过 poweshell 脚本 Azure devops 自动完成 PR
- linux - Linux Perl - 将十六进制值转换为十进制
- c# - 在使用“as”强制转换对象之前是否需要进行 C# 空检查?