[英]How to implement pytest fixture and parametrized arguments as arguments on the same test?
I want to create a test for a class called Graph
.我想为一个名为Graph
的类创建一个测试。 I've created a fixture called my_graph
that just creates a Graph
instance.我创建了一个名为my_graph
的夹具,它只是创建了一个Graph
实例。 Now I want to create a test that accepts the fixture and parametrized arguments that contain a list of inputs and expected outputs.现在我想创建一个测试,它接受包含输入和预期输出列表的夹具和参数化参数。
Here is what I've tried below but I keep getting that the vertex
fixture is not found.这是我在下面尝试过的,但我一直发现找不到vertex
夹具。
@pytest.fixture
def my_graph() -> adjacency_list.Graph:
g = adjacency_list.Graph()
return g
@pytest.mark.parametrize("my_graph, vertex, expected",
[('A', ['A']), (1, [1])])
def test_add_vertex(my_graph: adjacency_list.Graph, vertex: Union[str, int], expected: List[Union[str, int]]):
my_graph.add_vertex(vertex)
assert all([a == b for a, b in zip(my_graph.get_vertices(), expected))
The mistake is including the my_graph
fixture in the .parametrize(arg_names,...)
.错误是在.parametrize(arg_names,...)
包含my_graph
夹具。
Since my_graph
is already a fixture, and you seem to be creating a Graph
instance in the same way for all the tests, you don't need to parametrize it.由于my_graph
已经是一个装置,并且您似乎正在以相同的方式为所有测试创建一个Graph
实例,因此您不需要对其进行参数化。 Just declare it as a parameter of the test function and pytest will find your fixture:只需将其声明为测试函数的参数,pytest 就会找到您的夹具:
# Remove "my_graph" from here ---▼
@pytest.mark.parametrize("vertex, expected", [("A", ["A"]), (1, [1])])
def test_add_vertex(my_graph: Graph, vertex: Union[str, int], expected: List[Union[str, int]]):
...
I think you got confused from the @pytest.mark.parametrize example, wherein it shows that all inputs to the test are parametrized.我认为您对@pytest.mark.parametrize示例感到困惑,其中显示测试的所有输入都已参数化。 It doesn't have to be like that.不必如此。 Only those inputs that will have multiple possible values should be included in the .parametrize
declaration .只有那些具有多个可能值的输入才应包含在.parametrize
声明中。 For other fixtures ( @pytest.fixture
), just declare them as-is in the test function parameters.对于其他装置( @pytest.fixture
),只需在测试函数参数中按原样声明它们。
Note also that the signature for parametrize
expects that the number of argnames
and the number of argvalues
should match:还要注意, parametrize
的签名期望argnames
的数量和argvalues
的数量应该匹配:
@pytest.mark.parametrize("input_a, input_b, input_c", [
("param_a1", "param_b1", "param_c1"),
("param_a2", "param_b2", "param_c2"),
("param_a3", "param_b3", "param_c3"),
...
])
Here, there are 3 parametrized inputs, so the list should be 3-item tuples.这里有 3 个参数化输入,因此列表应该是 3 项元组。 This is a common gotcha when parametrizing tests, and this will produce errors such as " fixture not found " or " must be equal to the number of values ".这是参数化测试时的常见问题,这会产生诸如“未找到夹具”或“必须等于值的数量”之类的错误。
So, if for example, you need to instantiate the Graph
object differently based on the parametrized vertex
and expected
, then you need to also include the instantiated Graph
object in the .parametrize
list of tuples:所以,如果例如,你需要实例化Graph
基础上,参数化的不同对象vertex
和expected
,那么你还需要包括实例Graph
中的对象.parametrize
元组的列表:
class Graph:
def __init__(self, name: str):
self._name = name
self._vertices = []
...
@pytest.mark.parametrize(
"input_graph, vertex, expected",
[
(Graph("Graph A"), "A", ["A"]),
(Graph("Graph 1"), 1, [1]),
],
)
def test_add_vertex(input_graph, vertex: Union[str, int], expected: List[Union[str, int]]):
input_graph.add_vertex(vertex)
assert all([a == b for a, b in zip(input_graph.get_vertices(), expected)])
Here, instead of using the my_graph
fixture, parametrize
declares a differently named input_graph
, and each set of test inputs instantiates a Graph
object.在这里,不是使用my_graph
固定装置, parametrize
声明了一个不同名称的input_graph
,并且每组测试输入实例化一个Graph
对象。 The renaming is mostly to avoid confusion with your my_graph
fixture.重命名主要是为了避免与my_graph
夹具混淆。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.