我有下面一段可以正常工作的代码:
import pytest
class Person:
def __init__(self, name, age=None, height=None, lots_of_properties=None):
self.name = name
if age is not None:
self.age = age
if height is not None:
self.height = height
if lots_of_properties is not None:
self.lots_of_properties["somepropertykey"] = "somepropertyvalue"
@pytest.fixture
def a_person():
return Person("simon", 32)
def test_person_name(a_person):
assert a_person.name == "simon"
def test_person_age(a_person):
assert a_person.age == 32
这就是我到目前为止一直在使用fixture的方式。我创建了一个可以通过多个测试的夹具对象a_person
。在上面的例子中,我不能在创建时真正指定年龄,因为a_person
只定义了年龄。我怎么能传递更多的关键字参数夹具?另外,我如何修改a_person
夹具,以便我也可以修改人员的姓名和年龄?我一直在谷歌周围,看起来我必须使用@pytest.mark.parametrize
,但我似乎不能理解它如何适用于这种情况。基本上,我想要这样写:
@pytest.fixture
def a_person(name,age, height, lots_of_properties):
return Person(name, age, height, lots_of_properties)
# I would like to initialize multiple a_person objects with different params
def test_person_object_1(a_person.name = "alive", a_person.age = 33, a_person.height = 230, a_person.lots_of_properties.{}):
// test stuff
def test_person_object_2(a_person.name = "bob", a_person.age = 18, a_person.height = 180, a_person.lots_of_properties.{}):
// test stuff
但是我知道最后的语法是完全错误的。
要使用@pytest.mark.parametrize
做到这一点,您所需要的就是定义期望在fixture中作为函数参数接收的参数,并确保在测试的@pytest.mark.parametrize
中定义它们。如参数person_name
和person_age
import pytest
class Person:
def __init__(self, name, age=None, height=None, lots_of_properties=None):
self.name = name
if age is not None:
self.age = age
if height is not None:
self.height = height
if lots_of_properties is not None:
self.lots_of_properties["somepropertykey"] = "somepropertyvalue"
@pytest.fixture
def a_person(person_name: str, person_age: int) -> Person:
return Person(person_name, person_age)
@pytest.mark.parametrize("person_name, person_age", [("simon", 32)])
def test_with_parameters(a_person):
assert a_person.name == "simon"
assert a_person.age == 32
但是这种简单的方法在大多数情况下是不实用的。随着代码库变得越来越复杂,需要更复杂和直接的测试。这种方法的缺点之一是必须为每个测试定义所有参数,即使测试只测试其中一个参数。为了克服这个问题,可以将参数定义为返回默认值的单独fixture。如person_name
和person_age
装置
import pytest
class Person:
def __init__(self, name, age=None, height=None, lots_of_properties=None):
self.name = name
if age is not None:
self.age = age
if height is not None:
self.height = height
if lots_of_properties is not None:
self.lots_of_properties["somepropertykey"] = "somepropertyvalue"
@pytest.fixture
def person_name() -> str:
return "simon"
@pytest.fixture
def person_age() -> int:
return 32
@pytest.fixture
def a_person(person_name: str, person_age: int) -> Person:
return Person(person_name, person_age)
def test_person_name(a_person):
assert a_person.name == "simon"
def test_person_age(a_person):
assert a_person.age == 32
@pytest.mark.parametrize("person_name", ["not simon"])
def test_with_parameter_person_name(a_person):
assert a_person.name == "not simon"
@pytest.mark.parametrize("person_age", [20])
def test_with_parameter_person_age(a_person):
assert a_person.age == 20
@pytest.mark.parametrize("person_name, person_age", [("person1", 20), ("person2", 22), ("person3", 24)])
def test_with_parameters(a_person):
if a_person.name == "person1":
assert a_person.age == 20
elif a_person.name == "person2":
assert a_person.age == 22
elif a_person.name == "person3":
assert a_person.age == 24
else:
assert False, "Incorrect person"
这样,test_with_parameter_person_name
只能参数化与测试相关的参数,所有其他参数将从其他未参数化的fixture生成。
使用pytest标记@pytest.mark.parametrize
的一种方法如下所示:
也可以看到文档的链接:https://docs.pytest.org/en/7.1.x/how-to/parametrize.html#pytest-mark-parametrize-parametrizing-test-functions
import pytest
class Person:
def __init__(self, name, age=None, height=None, lots_of_properties=None):
self.name = name
if age is not None:
self.age = age
if height is not None:
self.height = height
if lots_of_properties is not None:
self.lots_of_properties["somepropertykey"] = "somepropertyvalue"
@pytest.fixture
def a_person():
return Person("simon", 32)
def test_person_name(a_person):
assert a_person.name == "simon"
def test_person_age(a_person):
assert a_person.age == 32
@pytest.mark.parametrize("field", [1,2,3])
def test_parametrize(a_person, field):
if 'field' == 1:
assert a_person.name == "simon"
if 'field' == 2:
assert a_person.age == 32
if 'field' == 3:
assert len(a_person.keys()) > 1
@pytest.mark.parametrize("field", [{1:Person("simon", 31)},{2:Person("simon", 32)},{3:Person("simon", 33)}])
def test_parametrize2(a_person, field):
if [field.keys()][0] == 1:
assert a_person.name == "simon"
if [field.keys()][0] == 2:
assert a_person.age == 32
if [field.keys()][0] == 3:
assert a_person.age == 33