3
votes

I am writing a python plugin for custom HTML report for pytest test results. I want to store some arbitrary test information (i.o. some python objects...) inside tests, and then when making report I want to reuse this information in the report. So far I have only came with a bit of hackish solution.

I pass request object to my test and fill the request.node._report_sections part of it with my data. This object is then passed to TestReport.sections attribute, which is available via hook pytest_runtest_logreport, from which finally I can generate HTML and then I remove all my objects from sections attribute.

In pseudopythoncode:

def test_answer(request):
    a = MyObject("Wooo")
    request.node._report_sections.append(("call","myobj",a))    
    assert False

and

def pytest_runtest_logreport(report):
    if report.when=="call":
        #generate html from report.sections content
        #clean report.sections list from MyObject objects
        #(Which by the way contains 2-tuples, i.e. ("myobj",a)) 

Is there a better pytest way to do this?

1
Did you get a better solution afterwards? - nn0p

1 Answers

0
votes

This way seems OK. Improvements I can suggest:

Think about using a fixture to create the MyObject object. Then you can place the request.node._report_sections.append(("call","myobj",a)) inside the fixture, and make it invisible in the test. Like this:

@pytest.fixture
def a(request):
    a_ = MyObject("Wooo")
    request.node._report_sections.append(("call","myobj",a_))
    return a_

def test_answer(a):
    ...

Another idea, which is suitable in case you have this object in all of your tests, is to implement one of the hooks pytest_pycollect_makeitem or pytest_pyfunc_call, and "plant" the object there in the first place.