Я реализую тесты для некоторых lxml
пользовательских элементов (например, ParentElement
, ChildElement
), которые зарегистрированы через декоратор из пользовательского класса поиска (ModelLookup
).
pytest
используется для запуска тестов, а я использую приборы, определенные в conftest.py
.
Проблема в том, что когда объекты для пользовательских элементов создаются как часть прибора, при тестировании функция набора теряется, и я получаю следующую ошибку:
> assert ['eclios', 'ruby'] == sorted([e.name for e in simple_tidy_family.child_element])
E AttributeError: 'lxml.etree._Element' object has no attribute 'name'
На С другой стороны, если объекты создаются как часть тестовой функции, все работает нормально.
В идеале я хотел бы повторно использовать эти приборы в других тестах, поэтому сначала определю их в контесте.
Код модуля:
from __future__ import unicode_literals
from lxml import etree
class ModelLookup(etree.PythonElementClassLookup):
_lookup = {}
@classmethod
def register_node_handler_class(cls, handler_cls):
if handler_cls.cls_tag not in cls._lookup.keys():
cls._lookup[handler_cls.cls_tag] = handler_cls
return handler_cls
def lookup(self, doc, node):
if node.tag in self._lookup.keys():
print(node.tag)
return self._lookup[node.tag]
return etree.ElementBase
@ModelLookup.register_node_handler_class
class ParentElement(etree.ElementBase):
cls_tag = 'ParentElement'
@staticmethod
def tada():
return 'tada'
@property
def child_element(self):
return self.xpath('./ChildElement')
@child_element.setter
def child_element(self, value):
self.append(value)
@property
def name(self):
return self.get('name')
@name.setter
def name(self, value):
self.set('name', value)
@ModelLookup.register_node_handler_class
class ChildElement(etree.ElementBase):
cls_tag = 'ChildElement'
@property
def name(self):
return self.get('name')
@name.setter
def name(self, value):
self.set('name', value)
conftest.py
from __future__ import unicode_literals
import pytest
import xmlpal.xmlpal as xpal
import logging
@pytest.fixture()
def simple_family():
ruby = xpal.ChildElement(**{'name': 'ruby'})
eclios = xpal.ChildElement(**{'name': 'eclios'})
adam = xpal.ParentElement()
adam.append(ruby)
adam.append(eclios)
logging.info(f'my name is {ruby.name}')
return adam
тестовый код:
from __future__ import unicode_literals
from lxml import etree
import xmlpal.xmlpal as xpal
def test_fixture_family(simple_family):
assert 'tada' == simple_family.tada()
assert isinstance(simple_family, xpal.ParentElement)
assert 2 == len(simple_family.child_element)
assert 2 == len([e for e in simple_family.child_element if isinstance(e, etree._Element)])
assert ['eclios', 'ruby'] == sorted([e.name for e in simple_family.child_element])
assert 2 == len([e for e in simple_family.child_element if isinstance(e, xpal.ChildElement)])
def test_local_family():
ruby = xpal.ChildElement(**{'name': 'ruby'})
eclios = xpal.ChildElement(**{'name': 'eclios'})
adam = xpal.ParentElement()
adam.append(ruby)
adam.append(eclios)
assert 'tada' == adam.tada()
assert isinstance(adam, xpal.ParentElement)
assert 2 == len(adam.child_element)
assert 2 == len([e for e in adam.child_element if isinstance(e, etree._Element)])
assert ['eclios', 'ruby'] == sorted([e.name for e in adam.child_element])
assert 2 == len([e for e in adam.child_element if isinstance(e, xpal.ChildElement)])
Любая помощь приветствуется!