secret.shadow
secret.shadow

Reputation: 89

Pytest: Runtime parametrization of a test

Does anyone know of a workaround to dynamically parametrize a pytest test.

Example:

resp = []

def test_1():
    r = requests.get(<some url>)
    resp = <parse a list out of response r>


@pytest.mark.parameterize("response",resp)
def test_2(response):
    <Use resp values and pass it one by one to another api>

I came across the following issue on pytest github which is almost same as my issue.

https://github.com/pytest-dev/pytest/issues/3273

As per this discussion, pytest parametrizes test before execution of any test. Runtime parametrization is not supported. Does anyone know of a workaround or a pythonic way to handle this behavior?

Upvotes: 1

Views: 1487

Answers (2)

msudder
msudder

Reputation: 512

Adrian Krupa's answer is close, now add response parametrization:

CANNED_RESPONSES = dict(OK=200, REDIRECT=304, SERVER_ERROR=500)
RESPONSE = 'response'

def pytest_generate_tests(metafunc):
    if RESPONSE in metafunc.fixturenames:
        ids = list(CANNED_RESPONSES.keys())
        responses = list(CANNED_RESPONSES.values())
        metafunc.parametrize(RESPONSE, responses, ids=ids)


def test_flar(response):
    print response

This way you can get named ids in -v and multiple tests for a set of canned answers:

test_in.py::test_flar[OK] 200
PASSED
test_in.py::test_flar[REDIRECT] 304
PASSED
test_in.py::test_flar[SERVER_ERROR] 500
PASSED

Upvotes: 1

Adrian Krupa
Adrian Krupa

Reputation: 1937

Don't make the tests to depend on each other. It's not a good practice as described here.

If you want to reuse request response you can wrap it into a fixture.

@pytest.fixture(scope="module")
def response():
    import requests
    return requests.get(<some url>)

def test(response):
    <Use resp values and pass it one by one to another api>

It would be also a good idea to mock the request to make tests independent from a remote resource. You can use responses library for that.

import responses
import requests

@responses.activate
def test_simple():
    responses.add(responses.GET, 'http://twitter.com/api/1/foobar',
                  json={'error': 'not found'}, status=404)

    resp = requests.get('http://twitter.com/api/1/foobar')

Upvotes: 1

Related Questions