我有几个 pytest 装置:
@pytest.fixture
def articles_new(category):
article_new_1 = ArticleFactory.create(category=category["category_1"], status=ArticleStatusChoices.NEW)
article_new_2 = ArticleFactory.create(category=category["category_2"], status=ArticleStatusChoices.NEW)
return {"article_new_1": article_new_1, "article_new_2": article_new_2}
@pytest.fixture
def articles_published_with_readers(category):
article_published_with_readers_1 = ArticleFactory.create(
category=category["category_2"],
readers=ArticleRoleTypesChoices.EMPLOYEE,
status=ArticleStatusChoices.PUBLISHED,
)
return {"article_published_with_readers_1": article_published_with_readers_1}
@pytest.fixture
def category(product):
category_1 = CategoryFactory.create(product=product["product_1"])
category_2 = CategoryFactory.create(product=product["product_2"])
return {"category_1": category_1, "category_2": category_2}
@pytest.fixture
def product():
product_1 = ProductFactory.create()
product_2 = ProductFactory.create()
return {"product_1": product_1, "product_2": product_2}
我尝试重构这样的测试:
def test_articles(self, client, user):
client.force_login(user)
res = client.get(reverse("get_article", kwargs={"article_guid": article_new_1.guid}))
assert res.status_code == 200
res = client.get(reverse("get_article", kwargs={"article_guid": article_published_with_readers_1.guid}))
assert res.status_code == 403
进入类似的事情:
@pytest.mark.parametrize(
"article, expected",
[
......
],
)
def test_articles(self, client, user, article, expected):
client.force_login(user)
res = client.get(reverse("get_article", kwargs={"article_guid": article.guid}))
assert res.status_code == expected
这个问题如何解决?
注意: article_new_1 和 article_published_with_readers_1 有不同的类别。
这是解决此问题的一种方法:
import logging
import pytest
@pytest.fixture
def client(): ...
@pytest.fixture
def user(): ...
@pytest.fixture
def category(product):
category_1 = "category_1"
category_2 = "category_2"
return {"category_1": category_1, "category_2": category_2}
@pytest.fixture
def product():
product_1 = "product_1"
product_2 = "product_2"
return {"product_1": product_1, "product_2": product_2}
def create_new_article(category):
return f"article with category {category['category_1']}"
def publish_article(category):
return f"published article with category {category['category_1']}"
@pytest.mark.parametrize(
"article_type, expected",
[
pytest.param("new", 200, id="success case"),
pytest.param("published", 403, id="failed case"),
],
)
def test_article(client, user, category, article_type, expected):
logging.debug("article_type=%r", article_type)
if article_type == "new":
article = create_new_article(category)
elif article_type == "published":
article = publish_article(category)
else:
raise ValueError("Invalid article type")
# Do something with article and expected
logging.debug("article=%r", article)
logging.debug("expected=%r", expected)
# assert res.status_code == expected
输出:
test_it.py::test_article[success case]
-------------------------------------------- live log call --------------------------------------------
DEBUG root:test_it.py:44 article_type='new'
DEBUG root:test_it.py:53 article='article with category category_1'
DEBUG root:test_it.py:54 expected=200
PASSED
test_it.py::test_article[failed case]
-------------------------------------------- live log call --------------------------------------------
DEBUG root:test_it.py:44 article_type='published'
DEBUG root:test_it.py:53 article='published article with category category_1'
DEBUG root:test_it.py:54 expected=403
PASSED
========================================== 2 passed in 0.01s ==========================================
注释
我没有将实际文章传递到测试中,而是传入了
article_type
:“新”或“已发布”。在测试中,我会使用这个文章类型来确定要创建哪种类型的文章。
create_new_article()
和publish_article()
不是固定装置,它们只是正常功能
我嘲笑了那些我无权访问的装置/函数/类
代替
("new", 200)
我用
pytest.param("new", 200, id="success case")
这允许灵活地为每个参数化案例指定名称,例如“成功案例”或“失败案例”
这个解决方案有点混乱,用一个大的
if
块来创建文章而不是直接将文章传递到测试中,但它简单且易于理解。