From 3183ae8b2b691ad43251c116655087ca0a68b983 Mon Sep 17 00:00:00 2001 From: June Tate-Gans Date: Tue, 27 Apr 2021 14:57:19 -0500 Subject: [PATCH] g13gui: Fix param names and migrate ObserverTestCase ObserverTestCase is code, not test stuff, so migrate that into the observer module properly. --- g13gui/g13gui/observer.py | 64 +++++++++++++++++++++++++++++---- g13gui/g13gui/observer_tests.py | 45 +++++++---------------- 2 files changed, 70 insertions(+), 39 deletions(-) diff --git a/g13gui/g13gui/observer.py b/g13gui/g13gui/observer.py index 7360cb1..2a59cec 100644 --- a/g13gui/g13gui/observer.py +++ b/g13gui/g13gui/observer.py @@ -1,5 +1,7 @@ #!/usr/bin/python +import unittest + from enum import Enum @@ -12,7 +14,7 @@ class ChangeType(Enum): class Observer(object): """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. Each subclass of Observer MUST override this method. There is no default @@ -22,7 +24,7 @@ class Observer(object): changed in its data model. changeType[ChangeType]: the type of change that occurred. 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, whatChanged should be the new data. In the case of a DELETE, it should be the old data (or None). @@ -47,20 +49,20 @@ class Subject(object): if observer in self._observers: 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. type[ChangeType]: the type of change that occurred. 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, whatChanged should be the new data. In the case of a DELETE, it should be the old data (or None). """ if '_changes' not in self.__dict__: - self._changes = [(type, key, whatChanged)] + self._changes = [(type, key, data)] else: - self._changes.append((type, key, whatChanged)) + self._changes.append((type, key, data)) def clearChanges(self): """Removes all scheduled changes from the change buffer.""" @@ -82,3 +84,53 @@ class Subject(object): for change in self._changes: observer.onSubjectChanged(self, *change) 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 = [] diff --git a/g13gui/g13gui/observer_tests.py b/g13gui/g13gui/observer_tests.py index 5ea57d7..91ef329 100644 --- a/g13gui/g13gui/observer_tests.py +++ b/g13gui/g13gui/observer_tests.py @@ -3,25 +3,6 @@ import unittest 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): pass @@ -31,22 +12,21 @@ class TestSubject(observer.Subject): pass -class ObserverTestCase(unittest.TestCase): +class ObserverTestCase(observer.ObserverTestCase): def setUp(self): self.subject = TestSubject() def testRegistration(self): - observer = TestObserver() - self.subject.registerObserver(observer) - assert(len(self.subject._observers) == 1) + self.subject.registerObserver(self) + self.assertEqual(len(self.subject._observers), 1) - self.subject.registerObserver(observer) - assert(len(self.subject._observers) == 1) + self.subject.registerObserver(self) + self.assertEqual(len(self.subject._observers), 1) - self.subject.removeObserver(observer) - assert(len(self.subject._observers) == 0) + self.subject.removeObserver(self) + self.assertEqual(len(self.subject._observers), 0) - self.subject.removeObserver(observer) + self.subject.removeObserver(self) def testSubclassNotificationError(self): testObserver = TestIncorrectObserver() @@ -61,15 +41,14 @@ class ObserverTestCase(unittest.TestCase): unittest.fail('Expected NotImplementedError') def testSubclassNotification(self): - o = TestObserver() - self.subject.registerObserver(o) + self.subject.registerObserver(self) self.subject.addChange(observer.ChangeType.ADD, 'foo', 'bar') self.subject.notifyChanged() - result = o.assertChangeNotified( - self.subject, observer.ChangeType.ADD, 'foo') - assert(result == 'bar') + self.assertChangeCount(1) + self.assertChangeNotified(self.subject, observer.ChangeType.ADD, 'foo') + self.assertChangeDataEquals('bar') if __name__ == '__main__':