g13gui: Fix param names and migrate ObserverTestCase

ObserverTestCase is code, not test stuff, so migrate that into the observer
module properly.
This commit is contained in:
June Tate-Gans 2021-04-27 14:57:19 -05:00
parent d5b4957916
commit 3183ae8b2b
2 changed files with 70 additions and 39 deletions

View File

@ -1,5 +1,7 @@
#!/usr/bin/python #!/usr/bin/python
import unittest
from enum import Enum from enum import Enum
@ -12,7 +14,7 @@ class ChangeType(Enum):
class Observer(object): class Observer(object):
"""Simple interface class to handle Observer-style notifications""" """Simple interface class to handle Observer-style notifications"""
def onSubjectChanged(self, subject, changeType, key, changeData): def onSubjectChanged(self, subject, changeType, key, data=None):
"""Event handler for observer notifications. """Event handler for observer notifications.
Each subclass of Observer MUST override this method. There is no default Each subclass of Observer MUST override this method. There is no default
@ -22,7 +24,7 @@ class Observer(object):
changed in its data model. changed in its data model.
changeType[ChangeType]: the type of change that occurred. changeType[ChangeType]: the type of change that occurred.
key[string]: a required name for what field changed. key[string]: a required name for what field changed.
whatChanged[object]: an optional context-dependent object, dict, or data[object]: an optional context-dependent object, dict, or
None, specifying what changed. In the case of an ADD or MODIFY, None, specifying what changed. In the case of an ADD or MODIFY,
whatChanged should be the new data. In the case of a DELETE, it should whatChanged should be the new data. In the case of a DELETE, it should
be the old data (or None). be the old data (or None).
@ -47,20 +49,20 @@ class Subject(object):
if observer in self._observers: if observer in self._observers:
self._observers.discard(observer) self._observers.discard(observer)
def addChange(self, type, key, whatChanged=None): def addChange(self, type, key, data=None):
"""Schedules a change notification for transmitting later. """Schedules a change notification for transmitting later.
type[ChangeType]: the type of change that occurred. type[ChangeType]: the type of change that occurred.
key[string]: a required name for what field changed. key[string]: a required name for what field changed.
whatChanged[object]: an optional context-dependent object, dict, or data[object]: an optional context-dependent object, dict, or
None, specifying what changed. In the case of an ADD or MODIFY, None, specifying what changed. In the case of an ADD or MODIFY,
whatChanged should be the new data. In the case of a DELETE, it should whatChanged should be the new data. In the case of a DELETE, it should
be the old data (or None). be the old data (or None).
""" """
if '_changes' not in self.__dict__: if '_changes' not in self.__dict__:
self._changes = [(type, key, whatChanged)] self._changes = [(type, key, data)]
else: else:
self._changes.append((type, key, whatChanged)) self._changes.append((type, key, data))
def clearChanges(self): def clearChanges(self):
"""Removes all scheduled changes from the change buffer.""" """Removes all scheduled changes from the change buffer."""
@ -82,3 +84,53 @@ class Subject(object):
for change in self._changes: for change in self._changes:
observer.onSubjectChanged(self, *change) observer.onSubjectChanged(self, *change)
self._changes = [] self._changes = []
class ObserverTestCase(Observer, unittest.TestCase):
def __init__(self, methodName):
unittest.TestCase.__init__(self, methodName)
self.changes = []
self.clearChanges()
def onSubjectChanged(self, subject, type, key, data=None):
self.changes.insert(0, {
'subject': subject,
'type': type,
'key': key,
'data': data
})
def assertChangeCount(self, count):
try:
self.assertEqual(len(self.changes), count)
except AssertionError as e:
message = [repr(e), '']
message.append('Changes were:')
num = 1
self.changes.reverse()
for change in self.changes:
message.append('%s: %s' % (num, repr(change)))
num = num + 1
raise AssertionError('\n'.join(message))
def assertChangeNotified(self, subject, type, key):
change = self.changes[-1]
self.assertEqual(change['subject'], subject)
self.assertEqual(change['type'], type)
self.assertEqual(change['key'], key)
def getChangeData(self):
return self.changes[-1]['data']
def assertChangeDataEquals(self, data):
change = self.changes[-1]
self.assertEqual(change['data'], data)
def skipChange(self):
self.nextChange()
def nextChange(self):
self.changes.pop()
def clearChanges(self):
self.changes = []

View File

@ -3,25 +3,6 @@
import unittest import unittest
import observer import observer
class TestObserver(observer.Observer):
def __init__(self):
self.changes = []
def onSubjectChanged(self, subject, type, key, whatChanged):
self.changes.insert(0, {
'subject': subject,
'type': type,
'key': key,
'whatChanged': whatChanged
})
def assertChangeNotified(self, subject, type, key):
change = self.changes.pop()
assert(change['subject'] == subject)
assert(change['type'] == type)
assert(change['key'] == key)
return change['whatChanged']
class TestIncorrectObserver(observer.Observer): class TestIncorrectObserver(observer.Observer):
pass pass
@ -31,22 +12,21 @@ class TestSubject(observer.Subject):
pass pass
class ObserverTestCase(unittest.TestCase): class ObserverTestCase(observer.ObserverTestCase):
def setUp(self): def setUp(self):
self.subject = TestSubject() self.subject = TestSubject()
def testRegistration(self): def testRegistration(self):
observer = TestObserver() self.subject.registerObserver(self)
self.subject.registerObserver(observer) self.assertEqual(len(self.subject._observers), 1)
assert(len(self.subject._observers) == 1)
self.subject.registerObserver(observer) self.subject.registerObserver(self)
assert(len(self.subject._observers) == 1) self.assertEqual(len(self.subject._observers), 1)
self.subject.removeObserver(observer) self.subject.removeObserver(self)
assert(len(self.subject._observers) == 0) self.assertEqual(len(self.subject._observers), 0)
self.subject.removeObserver(observer) self.subject.removeObserver(self)
def testSubclassNotificationError(self): def testSubclassNotificationError(self):
testObserver = TestIncorrectObserver() testObserver = TestIncorrectObserver()
@ -61,15 +41,14 @@ class ObserverTestCase(unittest.TestCase):
unittest.fail('Expected NotImplementedError') unittest.fail('Expected NotImplementedError')
def testSubclassNotification(self): def testSubclassNotification(self):
o = TestObserver() self.subject.registerObserver(self)
self.subject.registerObserver(o)
self.subject.addChange(observer.ChangeType.ADD, 'foo', 'bar') self.subject.addChange(observer.ChangeType.ADD, 'foo', 'bar')
self.subject.notifyChanged() self.subject.notifyChanged()
result = o.assertChangeNotified( self.assertChangeCount(1)
self.subject, observer.ChangeType.ADD, 'foo') self.assertChangeNotified(self.subject, observer.ChangeType.ADD, 'foo')
assert(result == 'bar') self.assertChangeDataEquals('bar')
if __name__ == '__main__': if __name__ == '__main__':