Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass a fixture to a helper function in PyTest?

Tags:

python

pytest

I have a function that needs to utilize a fixture in my test suite. This is just a small helper function that helps to generate a full URL.

def gen_url(endpoint):
    return "{}/{}".format(api_url, endpoint)

I have a fixture in conftest.py that returns the URL:

@pytest.fixture(params=["http://www.example.com"])
def api_url(request):
    return request.param

@pytest.fixture(params=["MySecretKey"])
def api_key(request):
    return request.param

Finally, in my test function, I need to call my gen_url:

def test_call_action_url(key_key):
    url = gen_url("player")
    # url should equal: 'http://www.example.com/player'
    # Do rest of test here...

When I do this, though, it throws an error saying that api_url isn't defined when gen_url is called. If I add api_url as a second parameter, I need to pass it as a second parameter. That's...not what I want to do.

Can I add api_url as a second parameter to gen_url without being required to pass it from the tests? Why can't I use it like api_key in my test_* function?

like image 893
Confused In Seattle Avatar asked Aug 28 '17 16:08

Confused In Seattle


1 Answers

If you make gen_url a fixture, it can request api_url without explicitly passing it:

@pytest.fixture
def gen_url(api_url):
    def _gen_url(endpoint):
        return '{}/{}'.format(api_url, endpoint)
    return _gen_url


def test_call_action_url(api_key, gen_url):
    url = gen_url('player')
    # ...

Additionally, if api_key is only used to make requests, a TestClient class could encapsulate it, so test methods would only require the client:

try:
    from urllib.parse import urljoin  # Python 3
except ImportError:
    from urlparse import urljoin  # Python 2

import requests

@pytest.fixture
def client(api_url, api_key):
    class TestClient(requests.Session):
        def request(self, method, url, *args, **kwargs):
            url = urljoin(api_url, api_key)
            return super(TestClient, self).request(method, url, *args, **kwargs)

    # Presuming API key is passed as Authorization header
    return TestClient(headers={'Authorization': api_key})


def test_call_action_url(client):
    response = client.get('player')  # requests <api_url>/player
    # ...
like image 101
theY4Kman Avatar answered Oct 19 '22 02:10

theY4Kman