[Tutor] Do not understand code snippet from "26.8. test — Regression tests package for Python"

Mats Wichmann mats at wichmann.us
Mon Apr 17 00:50:08 EDT 2017


On 04/16/2017 10:01 PM, boB Stepp wrote:
> OK, between Alan and Martin I think that I see how to make the code
> snippet actually test a *function* as the snippet seems to suggest.
> Recollect that my original question(s) started:


You got me thinking as well, as I don't much care for unittest, at least
partly because it forces you to use classes even when it doesn't feel
all that natural.

So here's a vaguely practical example of applying the same pattern using
pytest - that is, if you're going to test a function several different
ways, can you use just one test function instead of writing multiples.

First let's write the function to test: it tries to reverse its
argument, which should be something that can be iterated over, using
fancy list slicing.  To show it's working there is also code to try it
out if it is called as a program (as opposed to as a module).

=== reverser.py ==
def slicerev(collection):
    return collection[::-1]

if __name__ == "__main__":
    print slicerev([1,2,3,4])
    print slicerev((1,2,3,4))
    print slicerev('abcd')
===

Now write a test for this function, naming it, by convention,
test_{funcname}.py. (if it's named this way pytest can find it
automatically but it's not mandatory, you can give the name of the test
file as an argument).

Import pytest because we need the definition of the fixture decorator;
and import the function we're going to be testing, since it is, after
all, in a different file.

Since what we're factoring here is supplying different sets of data,
decorate a function "slicedata" which will return the data, turning it
into a pytest fixture (there's plenty of information on pytest fixtures
so won't repeat here); supply pairs of values where one value is the
data to call the function with and the other is the expected result of
calling the function under test.

The actual test function should be pretty straightforward.

=== test_slicerev.py ===
import pytest

from reverser import slicerev

@pytest.fixture(params=[
    ([1,2,3,4], [4,3,2,1]),
    ((1,2,3,4), (4,3,2,1)),
    ('abcd',    'edcba')
    ])
def slicedata(request):
    return request.param

def test_slicerev(slicedata):
    input, expected = slicedata
    output = slicerev(input)
    assert output == expected
===

Run the tests with "py.test test_slicerev.py"

Note the "expected" data for the string type is intentionally incorrect
so you should see an error with some explanatory output.

(you'll probably have to install pytest, since it's not in the standard
library; pytest can run all the unittest style tests too though).


More information about the Tutor mailing list