pythontestingpytestparametrized-testingpytest-fixtures

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


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?


Solution

  • 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: