yielding closure from a fixture in pytest
There is a pattern I occasionally see. There is a fixture, which need to do something in the middle of the test. It’s a fixture because it has dependency on other fixtures (in my case host
magical fixture of testinfra), and it need to do cleanup after test was executed.
One undignified way is to return a function:
@pytest.fixture()
def myfixture():
def retfun():
doing_something()
return retfun
In this case test can use myfixture as a function:
def test_foo(myfixture):
myfixture()
There is no cleanup stage here, and nested ‘def’ is always kinda hard to read.
I’ve just make it a bit more functional.
def put_data(host):
yield lambda: (
host.check_output('/usr/bin/truncate testblob --size 1337')
)
host.check_output('rm testblob')
The call from the test is the same:
def test_foo(put_data):
do_something()
put_data()
assert result()
The key advantages:
- There is no excessive ‘def’ declaration. Labmda is almost the same as the function, but it clearly shows that it’s a ‘run once’ code.
yield lambda
make it looks closer to a return of the closureyield
instead ofreturn
allows to do cleanup (even after test failed!)- finally, those brackets around
lambda
body allows to put lambda body on a separate line, making it easier to read.
I clearly understand that there is no difference between yield func
and yield lambda
, but combination of yield
and lambda
in a single line (instead of separate def
) making it more concise, in my opinion.