Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

remember/return returnvalues of test functions #207

Closed
pytestbot opened this issue Oct 22, 2012 · 12 comments
Closed

remember/return returnvalues of test functions #207

pytestbot opened this issue Oct 22, 2012 · 12 comments
Labels
type: enhancement new feature or API change, should be merged into features branch

Comments

@pytestbot
Copy link
Contributor

Originally reported by: Ronny Pfannschmidt (BitBucket: RonnyPfannschmidt, GitHub: RonnyPfannschmidt)


this would come in handy for things like the twisted integration,
which currently has to copy the pyfunc_call hook of pytest to get the function return values in order to block on a defered

an alternative would be to expose the "call a test function" machinery in a way that allows to use the returnvalue without copying the machinery


@pytestbot pytestbot added the type: enhancement new feature or API change, should be merged into features branch label Jun 15, 2015
@Droogans
Copy link

@nicoddemus you appear to be authoring 100% of the recent commits on master.

When would something like this ever become a generally accepted best practice in the project? I'd like to be able to return arbitrary objects after I've finished writing several assert statements, and have that returned object appear later in hook function arguments (item perhaps?).

@RonnyPfannschmidt
Copy link
Member

the main problem with this one is that it requires some refactorings in the internals that aren't clearly defined yet

@nicoddemus
Copy link
Member

Hi @Droogans,

Right now we don't have plans to add this feature to the core, but I you can easily do it yourself by attaching an object to request.node, which is actually an "item", something like:

def test(request):
    obj = SomeObject()
    request.node.obj = obj

Also to be honest copying the pytest_pyfunc_call does not seem too bad, here it is after cleaning it up a bit by removing support for yield tests:

@hookimpl(trylast=True)
def pytest_pyfunc_call(pyfuncitem):
    funcargs = pyfuncitem.funcargs
    testargs = {arg: funcargs[arg] arg in pyfuncitem._fixtureinfo.argnames}
    testfunction(**testargs)
    return True

Here you can even do some custom logic before doing something with the return value, for example check for a mark for example.

As @RonnyPfannschmidt mentioned, it is not clear yet how we could refactor the internals in order to support this more clearly.

@Droogans
Copy link

@nicoddemus aren't yield based tests going away in 4.x anyway?

@nicoddemus
Copy link
Member

Yep, that's why I didn't bother copying their logic above 😉

@Droogans
Copy link

Droogans commented Aug 1, 2018

Ok I went ahead and tried this today, this was what I had to do:

@pytest.hookimpl(trylast=True, hookwrapper=True)
def pytest_pyfunc_call(pyfuncitem):
    yield
    funcargs = pyfuncitem.funcargs
    testargs = { arg: funcargs[arg] for arg in pyfuncitem._fixtureinfo.argnames }
    element_of_interest = pyfuncitem.obj(**testargs)
    selenium = funcargs.get('selenium')

    if selenium and element_of_interest:
        selenium.execute_script('arguments[0].scrollIntoView(true);', element_of_interest)
        # pass through to the end of the selenium fixture's teardown section, will take screenshot there

@nicoddemus
Copy link
Member

In the snippet above you will end up calling the test function twice, is that what you intended?

@Droogans
Copy link

Droogans commented Aug 1, 2018

No, but that's why I posted it here. It appears to be doing some extra work at the end, I'll see if I can't put a debugging statement in a few places to catch those things as I continue to iron out this snippet. Thanks.

@nicoddemus
Copy link
Member

If you take out the hook-wrapper declaration it should do what you want, I think:

def pytest_pyfunc_call(pyfuncitem):
    funcargs = pyfuncitem.funcargs
    ...

fkohlgrueber pushed a commit to fkohlgrueber/pytest that referenced this issue Oct 27, 2018
@Zac-HD
Copy link
Member

Zac-HD commented Sep 26, 2020

Closing in favor of #7337, where the plan is to issue a warning and eventually error on non-None return values. Specific use-cases like async functions can be, and already are, handled by plugins which insert a run-the-thing shim.

@RonnyPfannschmidt
Copy link
Member

Reopening as this issue is about enabling other plugins to actually handle this without copying the surrounding machinery, which inherently adds a structural fragility

@RonnyPfannschmidt
Copy link
Member

closing this as too broad, will create new card

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement new feature or API change, should be merged into features branch
Projects
None yet
Development

No branches or pull requests

5 participants