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)

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()

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)

metafunc object: 
metafunc.fixturenames: set of required function arguments for given function. 
Metafunc.parametrize(argnamesargvaluesindirect=Falseids=Nonescope=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