Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In which py.test callout can I find both 'item' and 'report' data?

Tags:

python

pytest

pytest_runtest_makereport() gets two arguments, item and call. From item, I can find the funcarg I created for this test, and from call, I can find the exception info (if any):

def pytest_runtest_makereport (item, call):
    my_funcarg = item.funcargs['name']
    my_funcarg.excinfo = call.excinfo

Unfortunately, excinfo is populated for both failures and for skips. To distinguish, I need to look at the report argument to pytest_report_teststatus():

def pytest_report_teststatus (report):
    if report.when == 'call':
        if report.failed:
            failed = True
        elif report.skipped:
            skipped = True
        else:
            passed = True

That's great info, but I can't correlate it to the funcarg I created for the test. I have looked at the report argument (a TestReport report), and I can't find any way to get back to the item passed to pytest_runtest_makereport(), or the funcarg I created.

Where can I get access to both?

like image 895
Martin Del Vecchio Avatar asked May 25 '12 13:05

Martin Del Vecchio


People also ask

How do I run multiple tests in pytest?

Run Multiple Tests From a Specific File and Multiple Files To run all the tests from all the files in the folder and subfolders we need to just run the pytest command. This will run all the filenames starting with test_ and the filenames ending with _test in that folder and subfolders under that folder.

How do you run the same test case multiple times in pytest?

Repeating a test Each test collected by pytest will be run count times. If you want to override default tests executions order, you can use --repeat-scope command line option with one of the next values: session , module , class or function (default). It behaves like a scope of the pytest fixture.

What does pytest Mark do?

By using the pytest. mark helper you can easily set metadata on your test functions. You can find the full list of builtin markers in the API Reference. Or you can list all the markers, including builtin and custom, using the CLI - pytest --markers .

How do I run a specific test in pytest?

Running pytest We can run a specific test file by giving its name as an argument. A specific function can be run by providing its name after the :: characters. Markers can be used to group tests. A marked grouped of tests is then run with pytest -m .


2 Answers

There is a little undocumented somewhat unofficial method with which hook implementations can interact with other hook implementations, for example to post-process their result. In your concrete case you might do something like:

@pytest.mark.tryfirst
def pytest_runtest_makereport(item, call, __multicall__):
    rep = __multicall__.execute()
    # your code follows and you can use rep.passed etc.
    return rep

Notes:

  • a hook call will usually call multiple hook implementations
  • the "tryfirst" marker instructs the hook call to have your implementation be invoked early
  • the multicall parameter represents the ongoing hook call and can be used to call the remaining hook implementations and then
    use their result for further processing
  • you need to return "rep" here because you shadow the "real" creation

The multicall API is very seldomly really and i suspect there could be solutions for your use case that don't require it.

HTH, Holger

like image 188
hpk42 Avatar answered Oct 16 '22 10:10

hpk42


While hpk42's answer works, __multicall__ is being depreciated.

This achieves the same result though:

@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
    outcome = yield
    rep = outcome.get_result()
    setattr(item, "rep_" + rep.when, rep)
    return rep
like image 33
yvesva Avatar answered Oct 16 '22 10:10

yvesva