I have a class called Tree
and a class called Property
in models.py
:
class Tree:
def __init__(self, name=None):
self.name = name
self.properties = []
def get_name(self):
return self.name
def add_property(self, prop):
if prop.__class__.__name__ != 'Property':
raise TypeError('Only properties may be added as properties')
else:
print('adding property: ' + str(prop))
self.properties.append(prop)
def add_properties(self, arr):
for label in arr:
property = Property(label=label)
self.add_property(property)
def get_properties(self):
return self.properties
class Property:
def __init__(self, label=None):
self.label = label
self.tree = None
self.values = []
def __str__(self):
return self.label
I am trying to test these classes using the following pytest test script, which takes inputs from a .feature file:
import pytest
from pytest_bdd import scenario, given, when, then, parsers
from models import Tree
@scenario('../features/Tree.feature',
'add properties to a tree')
def test_tree():
pass
@given("a new tree is created", target_fixture="create_tree")
def create_tree():
return Tree()
@pytest.fixture()
@when(parsers.cfparse("{properties} are added as properties"))
def add_properties(create_tree, properties):
properties = properties.split(',')
create_tree.add_properties(properties)
return create_tree
@then("I can get these properties")
def publish_article(add_properties):
result = add_properties.get_properties()
assert len(result) == 3
Tree.feature
Feature: Tree
# BUILD TOP-DOWN
Scenario: add properties to a tree
Given a new tree is created
When height, weight, age are added as properties
Then I can get these properties
Somehow, the add_properties
method in the when
step is being called twice. I know this because the following is printed:
add_properties = <models.Tree object at 0x10b792760>
@then("I can get these properties")
def publish_article(add_properties):
print(add_properties.get_properties())
> assert len(add_properties.get_properties()) == 3
E assert 6 == 3
E + where 6 = len([<models.Property object at 0x10b792b50>, <models.Property object at 0x10b792a00>, <models.Property object at 0x10b792...dels.Property object at 0x10b62a280>, <models.Property object at 0x10b62a040>, <models.Property object at 0x10b62a0d0>])
E + where [<models.Property object at 0x10b792b50>, <models.Property object at 0x10b792a00>, <models.Property object at 0x10b792...dels.Property object at 0x10b62a280>, <models.Property object at 0x10b62a040>, <models.Property object at 0x10b62a0d0>] = <bound method Tree.get_properties of <models.Tree object at 0x10b792760>>()
E + where <bound method Tree.get_properties of <models.Tree object at 0x10b792760>> = <models.Tree object at 0x10b792760>.get_properties
tests/step_defs/test_tree.py:26: AssertionError
----------------------------- Captured stdout call -----------------------------
adding property: height
adding property: weight
adding property: age
adding property: height
adding property: weight
adding property: age
[<models.Property object at 0x10b792b50>, <models.Property object at 0x10b792a00>, <models.Property object at 0x10b792a60>, <models.Property object at 0x10b62a280>, <models.Property object at 0x10b62a040>, <models.Property object at 0x10b62a0d0>]
=========================== short test summary info ============================
FAILED tests/step_defs/test_property.py::test_property - pytest_bdd.exception...
FAILED tests/step_defs/test_tree.py::test_tree - assert 6 == 3
========================= 2 failed, 1 passed in 0.24s ==========================
Why are the properties being added twice?
I think the problem is that pytest_bdd lets you use the @given
as fixtures but you also added the @pytest.fixture
decorator on the @when
.
That means the add_properties
function is called once as the when
step and then it is called again as a pytest fixture. Remove the extra decorator and use the original create_tree
fixture instead.
import pytest
from pytest_bdd import scenario, given, when, then, parsers
from models import Tree
@scenario('../features/Tree.feature',
'add properties to a tree')
def test_tree():
pass
@given("a new tree is created", target_fixture="create_tree")
def create_tree():
return Tree()
@when(parsers.cfparse("{properties} are added as properties"))
def add_properties(create_tree, properties):
properties = properties.split(',')
create_tree.add_properties(properties)
return create_tree
@then("I can get these properties")
def publish_article(create_tree):
result = create_tree.get_properties()
assert len(result) == 3