Parameterized tests
The purpose of parameterizing a test is to run a test
against multiple sets of arguments. pytest supports test parametrization in
several well-integrated ways:
1. @pytest.mark.parametrize
2. pytest_generate_tests
@pytest.mark.parametrize
We can do this
by using following marker.
@pytest.mark.parametrize
Create a test called test_divisions.py
import pytest
@pytest.mark.parametrize("dividend,divisor",[(10,2),(11,3),(20,5),(36,6)])
def test_division(dividend,divisor):
assert (dividend% divisor==0)
@pytest.mark.parametrize("dividend,divisor",[(10,2),(11,3),(20,5),(36,6)])
def test_division(dividend,divisor):
assert (dividend% divisor==0)
Execute the test by running the following command
pytest test_divisions.py -v
output will be
Above test method accepts 2 arguments – dividend and divisor. It
divides and compare output with expected value.
Test has 4 set of input values, so test has ran 4 times.
pytest_generate_tests: enable implementing your own custom dynamic parametrization
scheme or extensions.
Sometimes you may want to implement your own parametrization
scheme or implement some dynamism for determining the parameters or scope of a
fixture. For this, you can use the pytest_generate_tests
hook which is called when collecting a test function. Through the passed in metafunc object you can inspect the
requesting test context and, most importantly, you can call
metafunc.parametrize() to cause parametrization.
For example, let’s say we want to run a test taking string inputs
which we want to set via a new pytest command line option. Let’s first write a
simple test accepting a stringinput fixture function argument:
Create a test file called test_strings.py
def test_valid_strings(stringinput):
assert stringinput.isalpha()
assert stringinput.isalpha()
Now we add a conftest.py file containing the addition of a command
line option and the parametrization of our test function:
import pytest
def pytest_addoption(parser):
parser.addoption("--stringinput",action="append",default=[],help="list of stringinputs to pass to test functions")
def pytest_generate_tests(metafunc):
if 'stringinput' in metafunc.fixturenames:
metafunc.parametrize("stringinput",metafunc.config.option.stringinput)
def pytest_addoption(parser):
parser.addoption("--stringinput",action="append",default=[],help="list of stringinputs to pass to test functions")
def pytest_generate_tests(metafunc):
if 'stringinput' in metafunc.fixturenames:
metafunc.parametrize("stringinput",metafunc.config.option.stringinput)
metafunc object:
metafunc.fixturenames: set of required function arguments for given function.
Metafunc.parametrize(argnames, argvalues, indirect=False, ids=None, scope=None): Add new invocations to the underlying test function using the list
of argvalues for the given argnames. Parametrization is performed during the
collection phase. If you need to setup expensive resources see about setting
indirect=True to do it rather at test setup time.
If we now pass two stringinput values, our test will run
twice:
pytest -q –stringinput=”hello” –stringinput=”world”
test_string.py -v
Let’s also run with a stringinput that will lead to a failing
test:
pytest -q –stringinput=”hello” –stringinput=”!”
test_string.py -v
If you don’t specify a stringinput it will be skipped because
metafunc.parametrize() will be called with an empty parameter listlist:
pytest test_strings.py
Comments
Post a Comment