previous Graphing sensor data with Python
Everyone loves a good py.test fixture. Those things are so flexible. Sometimes it’s desirable to have a fixture return a function, like this:
@pytest.fixture
def get_x():
# some code
x = 1
def closure_fn():
return x
return closure_fn
def test_something(get_x):
x = get_x()
assert x == 1
After some time, the number of function-returning fixtures gets to the point where our test function signatures start to get a bit over the top:
def test_something(fixture_a,
fixture_b,
get_x,
get_y,
get_z):
x = get_x()
y = get_y()
z = get_z()
assert x, y, z == 1, 2, 3
Because py.test fixtures can return arbitrary Python objects and also support dependencies on other fixtures (fixture functions support the same injection syntax as test functions), we can just use a Python datastructure of some type to group our get_* functions into a single fixture. The “grouping” fixture and its usage could look like this:
@pytest.fixture
def getters(get_x, get_y, get_z):
return get_x, get_y, get_z
def test_more_things(getters):
get_x, get_y, get_z = getters
x = get_x()
# ...
But this way, we’d need to remember in which order we packed out getters when we want to call them from the test function. Surely there’s a better way. This is Python, of course there’s a better way! We could use a dictionary, which would mean we could address our getter functions by name, but then our calling syntax would be getters['get_x']() which is a bit opaque. We can use a little namedtuple magic to get prettier calling syntax, like this:
import collections
@pytest.fixture
def getters(get_x, get_y, get_z):
dict_ = {
'get_x': get_x,
'get_y': get_y,
'get_z': get_z,
}
nt = collections.namedtuple('getters', dict_.keys())
return nt(**dict_)
def test_more_things(getters):
x = getters.get_x()
# ...
This way, we get saner calling syntax and don’t have to worry about unpacking our groups in every test function. Wunderbar!
how fly so fast? next