2016-02-18 10 views
1

У меня есть простой event handler, который ищет то, что на самом деле был изменен (он зарегистрирован в течение IObjectModifiedEvent событий), код выглядит следующим образом:Как запрограммировать создание подробного события, например z3c.form?

def on_change_do_something(obj, event): 
    modified = False 
    # check if the publication has changed 
    for change in event.descriptions: 
     if change.interface == IPublication: 
      modified = True 
      break 

    if modified: 
     # do something 

Так что мой вопрос: как я могу программно генерировать эти описания? Я использую plone.app.dexterity везде, поэтому z3c.form делает это автоматически при использовании формы, но я хочу протестировать ее с помощью unittest.

+0

Вероятно, я не получаю то, что вам нужно, но если вы хотите * unit test * функцию, почему вы не можете просто называть ее параметром mock event? Объект, который предоставляет атрибут 'description'? –

+0

@keul, это была идея, я хочу знать, как издеваться над описанием, исходящим из z3c.form – gforcada

+0

К сожалению, я не получу большую картину. Кажется, что вы, вероятно, не выполняете единичный тест (но тест интеграции?), Если вам нужен реальный z3c.form. –

ответ

3

event.description номинально является объектом IModificationDescription, который по существу представляет собой список объектов IAttributes: каждый объект Attributes, имеющий интерфейс (например, схему) и атрибуты (например, список имен полей), изменен.

решение

Простейшие является создание объекта zope.lifecycleevent.Attributes для каждого поля изменилось, и передать в качестве аргументов конструктору событий - например:

# imports elided... 

changelog = [ 
    Attributes(IFoo, 'some_fieldname_here'), 
    Attributes(IMyBehaviorHere, 'some_behavior_provided_fieldname_here', 
    ] 
notify(ObjectModifiedEvent(context, *changelog) 
+0

Спасибо! это сделало трюк, я был смущен, потому что мне казалось, что такой подход не будет работать, но Атрибуты делают некоторые обманки, которых я не ожидал – gforcada

0

Я также могу неправильно понять что-то, но вы можете просто запустить событие в своем коде с такими же параметрами, как z3c.form (похоже на комментарий от @keul)?

После короткого поиска в 4.3.x Plone, я нашел это в z3c.form.form:

def applyChanges(self, data): 
    content = self.getContent() 
    changes = applyChanges(self, content, data) 
    # ``changes`` is a dictionary; if empty, there were no changes 
    if changes: 
     # Construct change-descriptions for the object-modified event 
     descriptions = [] 
     for interface, names in changes.items(): 
      descriptions.append(
       zope.lifecycleevent.Attributes(interface, *names)) 
     # Send out a detailed object-modified event 
     zope.event.notify(
      zope.lifecycleevent.ObjectModifiedEvent(content, *descriptions)) 
    return changes 

Вам нужно два testcases, тот, который не делает ничего, и тот, который идет через ваш код.

applyChanges находится в том же модуле (z3c.form.form), он итерации по полям формы и вычисляет dict со всеми изменениями.

Вы должны установить там точку перерыва, чтобы проверить, как строит dict.

Впоследствии вы можете сделать то же самое в своем тестовом примере.

Таким образом, вы можете написать читаемые тестовые примеры.

def test_do_something_in_event(self) 

    content = self.get_my_content() 
    descriptions = self.get_event_descriptions() 

    zope.event.notify(zope.lifecycleevent.ObjectModifiedEvent(content, *descriptions)) 

    self.assertSomething(...)   

ИМХО насмешливый всю логику прочь может быть плохой идеей для будущего, если изменения кода и, вероятно, работает совершенно иначе, ваш тест будет по-прежнему хорошо.