1

I have a fixture which in I want to use request.param multiple times.

@pytest.fixture
def get_settings(request):
    with mock.patch("helpers.helpers.get_settings") as mocked_settings:
        mocked_settings.return_value = Settings(
            TOKEN_KEY=request.param,      # <== Here
            TOKEN_PASSWORD=request.param) # <== And here
        yield


@pytest.fixture
def get_user():
    return User(name="Test User")

def generate_new_token(user: User) -> str:

    settings = get_settings()
    private_key = settings.TOKEN_KEY
    token_password = settings.TOKEN_PASSWORD

    if not private_key.strip():
        raise ValueError("Private key must not be empty")

How can I do it? If I do something like above (with two request.param), and then use it in my test function like this:

@pytest.mark.parametrize('get_settings, expected', [(FAKE_TOKEN_KEY, '', None), (FAKE_TOKEN_KEY, '1', None)],
                         indirect=["get_settings"])
def test_generate_new_token(get_user, get_settings, expected):
    assert generate_new_token(user=get_user) == expected

I get this error:

in "parametrize" the number of names (2): ['get_settings', 'expected'] must be equal to the number of values (3)

I'm not sure if it's related to the second fixture (get_user) I'm passing to the test function or not. But how can I fix it?

UPDATE

None is the expected value and I put the other two in tuple. But in this case I get following error:

test setup failed

request = <SubRequest 'get_settings' for <Function test_generate_new_token[get_settings1-None]>>

@pytest.fixture
def get_settings(request):
    with mock.patch("helpers.helpers.get_settings") as mocked_settings:
      > mocked_settings.return_value = Settings(
            DEBUG=True,
            TOKEN_KEY=request.param,  # FAKE_TOKEN_KEY,
            TOKEN_PASSWORD=request.param)

../conftest.py:76:


pydantic/env_settings.py:36: in pydantic.env_settings.BaseSettings.init ???


???

E pydantic.error_wrappers.ValidationError: 2 validation errors for Settings E TOKEN_KEY

E str type expected (type=type_error.str)

E TOKEN_PASSWORD

E str type expected (type=type_error.str)

pydantic/main.py:406: ValidationError

Ghasem
  • 14,455
  • 21
  • 138
  • 171
  • No, it's related to the number of values in `parametrize`, the 2 variables (`get_settings`, `expected`) do not match the 3 values (`FAKE_TOKEN_KEY`, `'1'`, `None`). – MrBean Bremen Nov 11 '21 at 19:12
  • @MrBeanBremen That's where I can't figure out the right way to do it. In all the tutorials I watched, there's just one `request.param` in fixture and that works. But in my case I need more than one and I'm looking for a way to do it. – Ghasem Nov 11 '21 at 19:15
  • Ah ok. You can pass a tuple as request param, as you try to do, but I don't see the `expected` parameter value in your decorator. Also, if you pass a tuple, you have to access the values in the tuple via index in `request.param`. – MrBean Bremen Nov 11 '21 at 19:19
  • If `None` is the expected value (just realized that it may be), then you just forgot to put brackets around the tuple, e.g. `[((FAKE_TOKEN_KEY, ''), None), ...]`. – MrBean Bremen Nov 11 '21 at 19:24
  • @MrBeanBremen I set the tuples as you suggested. But I'm getting a weird error. I updated my question with that error. – Ghasem Nov 11 '21 at 20:15
  • 1
    You didn't change the usage of `param` for the tuple as I wrote, you need something like `TOKEN_KEY=request.param[0]` and `TOKEN_PASSWORD=request.param[1]`. – MrBean Bremen Nov 11 '21 at 20:19
  • @MrBeanBremen Thank you! That fixed the problem. Why don't you add it as an answer? – Ghasem Nov 11 '21 at 21:02
  • Sorry, wasn't around to write an answer, and now you already did :) – MrBean Bremen Nov 12 '21 at 16:57

1 Answers1

3

So there were two changes I needed to make in my code to fix the problem:

1- I had to pass the parameters in a tuple:

@pytest.mark.parametrize('get_settings, expected', [
((FAKE_TOKEN_KEY, ''), None), 
((FAKE_TOKEN_KEY, '1'), None)
],
                         indirect=["get_settings"])

2- I had to pass the param indexes in the fixture:

@pytest.fixture
def get_settings(request):
    with mock.patch("helpers.helpers.get_settings") as mocked_settings:
        mocked_settings.return_value = Settings(
            TOKEN_KEY=request.param[0],      # <== Here I added index [0]
            TOKEN_PASSWORD=request.param[1]) # <== And here index [1]
        yield
Ghasem
  • 14,455
  • 21
  • 138
  • 171