Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use docstrings to list tests in py.test

Here is a simple test file:

# 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

The default output in py.test is like

$ py.test test_single.py -v
[...]
test_single.py::test_addition PASSED
test_single.py::test_addition2 PASSED

I would like to have

Two plus two is still four PASSED
One plus one is still two PASSED

i.e. use the docstrings as descriptions for the tests.

I tried to use a customization in a conftest.py file:

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

that is close, but it repeats the filename on every line:

$ 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 ======================================================================================

How can I avoid the lines with test_single.py in the output, or maybe print it only once?

Looking into the source of py.test and some of its plugins did not help.

I am aware of the pytest-spec plugin, but that uses the function's name as a description. I don't want to write def test_two_plus_two_is_four().

like image 941
Matthias Berth Avatar asked Mar 06 '15 12:03

Matthias Berth


People also ask

Can doctest be used to test docstrings?

There are several common ways to use doctest: To check that a module's docstrings are up-to-date by verifying that all interactive examples still work as documented. To perform regression testing by verifying that interactive examples from a test file or a test object work as expected.

Can pytest run doctests?

Using 'doctest' options In pytest, you can enable those flags using the configuration file. pytest also introduces new options to allow doctests to run in Python 2 and Python 3 unchanged: ALLOW_UNICODE : when enabled, the u prefix is stripped from unicode strings in expected doctest output.

What are docstrings used for in Python?

A Python docstring is a string used to document a Python module, class, function or method, so programmers can understand what it does without having to read the details of the implementation. Also, it is a common practice to generate online (html) documentation automatically from docstrings.

How do I run all Python doctests?

Right click on a blank space in the python code, and there is a menu option to run all the Doctests found in the file, not just the tests for one function.


4 Answers

To expand on my comment to @michael-wan's answer: to achive something similar to specplugin put into 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)) 

and the pytest output of

class TestSomething: """Something"""  def test_ok(self):     """should be ok"""     pass 

will look like

py.test screen grab

If you omit docstrings class/func names will be used.

like image 179
Misha Tavkhelidze Avatar answered Sep 28 '22 12:09

Misha Tavkhelidze


I was missing rspec in ruby for python. So, based on the plugin pytest-testdox., I have written similar one which takes doc strings as report message. You can check it out pytest-pspec. enter image description here

like image 29
7H3 IN5ID3R Avatar answered Sep 28 '22 11:09

7H3 IN5ID3R


For a plugin that (I think) does what you want out of the box, check out pytest-testdox.

It provides a friendly formatted list of each test function name, with test_ stripped, and underscores replaced with spaces, so that the test names are readible. It also breaks up the sections by test file.

This is what the output looks like:

enter image description here

like image 35
Symmetric Avatar answered Sep 28 '22 11:09

Symmetric


@Matthias Berth, you can try to use 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() )

and modify pydir/Lib/site-packages/pytest-2.9.1-py2.7.egg/_pytest/unittest.py add the following function to the TestCaseFunction class

def setNodeid(self, value):
    self._nodeid = value

and the result will be :

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

enter image description here by the way when you are using pytest-html you can use the pytest_runtest_makereport function you make and it will generate the report with the name you customized. hope this helps.

like image 25
Michael Wan Avatar answered Sep 28 '22 12:09

Michael Wan