How to get exact value from fixture in @pytest.mark.parametrize

64 Views Asked by At

I use pytest fixture which return object {"article_new_1": article_new_1, "article_new_2": article_new_2}:

@pytest.fixture
def create_articles_new(create_categories):
    article_new_1 = ArticleFactory.create(category=create_categories["category_1"], status=ArticleStatusChoices.NEW)
    article_new_2 = ArticleFactory.create(category=create_categories["category_2"], status=ArticleStatusChoices.NEW)
    return {"article_new_1": article_new_1, "article_new_2": article_new_2}

I try to parametrize a test using the fixture. I would like to paste two articles of the fixture to @pytest.mark.parametrize.

@pytest.mark.parametrize(
    "article,expected",
        [
            ('create_articles_new.article_new_1', 200),
            ('create_articles_new.article_new_2', 403),
        ],
)
def test_articles(client, article, expected):
    res = client.get(reverse("get_article", kwargs={"article_guid": article.guid}))
    assert res.status_code == expected

QUISTION: What should I paste instead of create_articles_new.article_new_1 and create_articles_new.article_new_2?

1

There are 1 best solutions below

4
tmt On BEST ANSWER

To have a fixture create the parametrization, it needs to be called by declaring indirect=True. However, you wouldn't have expected as a separate test function argument. Instead, article would be a tuple consisting of the Article object (I assume that ArticleFactory creates Article) and the expected result:

import pytest
from _pytest.fixtures import SubRequest


@pytest.fixture()
def article(create_categories, request: SubRequest) -> tuple[Article, int]:
    return (
        ArticleFactory.create(
            category=create_categories[request.param[0]],
            status=ArticleStatusChoices.NEW
        ),
        request.param[1],
    )


@pytest.mark.parametrize(
    "article",
    [
        ("category_1", 200),
        ("category_2", 403),
    ],
    indirect=True,
)
def test_articles(client, article: tuple[Article, int]) -> None:
    res = client.get(
        reverse("get_article", kwargs={"article_guid": article[0].guid})
    )
    assert res.status_code == article[1]

Notes:

  • Fixtures can access passed parametrization arguments via request fixture and its param property.
  • article fixture doesn't need to return a tuple. You could have it return a dict, data class, or whatever you find more suitable.
  • SubRequest is imported only to give you a hint what object your fixture would be working with. You can omit it.