这是一个简单的测试文件:
# test_single.py
def test_addition():
"Two plus two is still four"
assert 2 + 2 == 4
def test_addition2():
"One plus one is still two"
assert 1 + 1 == 2
py.test中的默认输出类似于
$ py.test test_single.py -v
[...]
test_single.py::test_addition PASSED
test_single.py::test_addition2 PASSED
我想
Two plus two is still four PASSED
One plus one is still two PASSED
即。使用docstrings作为测试的描述。
我尝试在conftest.py
文件中使用自定义:
import pytest
@pytest.mark.tryfirst
def pytest_runtest_makereport(item, call, __multicall__):
# execute all other hooks to obtain the report object
rep = __multicall__.execute()
if rep.when == "call":
extra = item._obj.__doc__.strip()
rep.nodeid = extra
return rep
即接近,但它会在每一行重复文件名:
$ py.test test_single.py
======================================================================================== test session starts =========================================================================================
platform darwin -- Python 2.7.7 -- py-1.4.26 -- pytest-2.6.4
plugins: greendots, osxnotify, pycharm
collected 2 items
test_single.py
And two plus two is still four .
test_single.py
And one plus one is still two .
====================================================================================== 2 passed in 0.11 seconds ======================================================================================
如何在输出中避免使用test_single.py
的行,或者只打印一次?
查看py.test的来源及其部分插件没有帮助。
我知道pytest-spec插件,但它使用函数的名称作为描述。我不想写def test_two_plus_two_is_four()
。
答案 0 :(得分:17)
将我的评论扩展到@ michael-wan的答案:获得类似specplugin
的内容conftest.py
:
def pytest_itemcollected(item):
par = item.parent.obj
node = item.obj
pref = par.__doc__.strip() if par.__doc__ else par.__class__.__name__
suf = node.__doc__.strip() if node.__doc__ else node.__name__
if pref or suf:
item._nodeid = ' '.join((pref, suf))
和
的pytest
输出
class TestSomething:
"""Something"""
def test_ok(self):
"""should be ok"""
pass
看起来像
如果省略docstrings将使用class / func名称。
答案 1 :(得分:5)
我错过了rspec in ruby
for python。因此,基于插件pytest-testdox.
,我编写了类似的文档字符串作为报告消息。你可以查看his answer on splitting arguments into tokens。 pytest-pspec
答案 2 :(得分:4)
对于(我认为)开箱即用的插件,请查看pytest-testdox。
它提供了每个测试函数名称的友好格式化列表,其中test_
被剥离,下划线被替换为空格,因此测试名称是可读的。它还按测试文件分解了部分。
这是输出的样子:
答案 3 :(得分:2)
@Matthias Berth,您可以尝试使用pytest_itemcollected
def pytest_itemcollected(item):
""" we just collected a test item. """
item.setNodeid('' if item._obj.__doc__ is None else item._obj.__doc__.strip() )
并修改pydir / lib / site-packages / pytest-2.9.1-py2.7.egg / _pytest / unittest.py 将以下函数添加到TestCaseFunction类
def setNodeid(self, value):
self._nodeid = value
,结果将是:
platform win32 -- Python 2.7.10, pytest-2.9.1, py-1.4.31, pluggy-0.3.1 -- D:\Python27\python.exe
cachedir: .cache
rootdir: E:\workspace\satp2\atest\testcase\Search\grp_sp, inifile:
plugins: html-1.8.0, pep8-1.0.6
collecting 0 itemsNone
collected 2 items
Two plus two is still four <- sut_amap3.py PASSED
One plus one is still two <- sut_amap3.py PASSED
当你使用pytest-html的时候 您可以使用您创建的pytest_runtest_makereport函数,它将生成具有您自定义名称的报告。 希望这有帮助。
答案 4 :(得分:0)
我想做同样的事情,但是要用一种更简单的方式,最好不要使用外部插件来做超出需要的事情,并且还要避免更改nodeid
,因为它可能会破坏其他东西
我想出了以下解决方案:
test_one.py
import logging
logger = logging.getLogger(__name__)
def test_one():
""" The First test does something """
logger.info("One")
def test_two():
""" Now this Second test tests other things """
logger.info("Two")
def test_third():
""" Third test is basically checking crazy stuff """
logger.info("Three")
conftest.py
import pytest
import inspect
@pytest.mark.trylast
def pytest_configure(config):
terminal_reporter = config.pluginmanager.getplugin('terminalreporter')
config.pluginmanager.register(TestDescriptionPlugin(terminal_reporter), 'testdescription')
class TestDescriptionPlugin:
def __init__(self, terminal_reporter):
self.terminal_reporter = terminal_reporter
self.desc = None
def pytest_runtest_protocol(self, item):
self.desc = inspect.getdoc(item.obj)
@pytest.hookimpl(hookwrapper=True, tryfirst=True)
def pytest_runtest_logstart(self, nodeid, location):
if self.terminal_reporter.verbosity == 0:
yield
else:
self.terminal_reporter.write('\n')
yield
if self.desc:
self.terminal_reporter.write(f'\n{self.desc} ')
运行--verbose
============================= test session starts =============================
platform win32 -- Python 3.8.2, pytest-5.4.1.dev62+g2d9dac95e, py-1.8.1, pluggy-0.13.1 -- C:\Users\Victor\PycharmProjects\pytest\venv\Scripts\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\Victor\PycharmProjects\pytest, inifile: tox.ini
collecting ... collected 3 items
test_one.py::test_one
The First test does something PASSED [ 33%]
test_one.py::test_two
Now this Second test tests other things PASSED [ 66%]
test_one.py::test_third
Third test is basically checking crazy stuff PASSED [100%]
============================== 3 passed in 0.07s ==============================
运行--log-cli-level=INFO
============================= test session starts =============================
platform win32 -- Python 3.8.2, pytest-5.4.1.dev62+g2d9dac95e, py-1.8.1, pluggy-0.13.1
rootdir: C:\Users\Victor\PycharmProjects\pytest, inifile: tox.ini
collected 3 items
test_one.py::test_one
The First test does something
-------------------------------- live log call --------------------------------
INFO test_one:test_one.py:7 One
PASSED [ 33%]
test_one.py::test_two
Now this Second test tests other things
-------------------------------- live log call --------------------------------
INFO test_one:test_one.py:11 Two
PASSED [ 66%]
test_one.py::test_third
Third test is basically checking crazy stuff
-------------------------------- live log call --------------------------------
INFO test_one:test_one.py:15 Three
PASSED [100%]
============================== 3 passed in 0.07s ==============================
conftest.py
中的插件可能足够简单,任何人都可以根据自己的需求进行自定义。