5 from model.project import Project
6 from model import project
7 from model import action
10 class ProjectClassBehaviour(unittest.TestCase):
12 self.p_class = Project
13 self.observer = Mock()
14 self.p_class.observers.append(self.observer)
16 def test_should_inform_listeners_of_project_creation(self):
18 self.assertTrue(self.observer.notify.called)
20 class ProjectBehaviour(unittest.TestCase):
23 self.name = u'my project'
24 self.status = self.initial_status()
25 self.actions = self.initial_actions()
26 self.infos = self.initial_infos()
27 self.project = model.project.Project(self.name,self.status)
28 for a in self.actions:
29 self.project.add_action(a)
31 self.project.add_info(i)
32 self.observer = Mock()
33 self.project.observers.append(self.observer)
35 def initial_actions(self):
38 def create_action(self):
40 a.status = self.action_status()
43 def action_status(self):
46 def initial_infos(self):
49 def initial_status(self):
50 return project.inactive
52 def test_should_remember_its_name(self):
53 self.assertEqual(self.project.name,self.name)
55 def test_should_notify_observer_of_name_change(self):
56 self.project.name = 'new name'
57 self.assert_observed('name','new name',self.name)
59 def test_should_notify_observer_of_status_change(self):
60 old_status = self.project.status
61 self.project.status = project.done
62 self.assert_observed_status(project.done,old_status)
64 def create_action_with_status(self,status=action.inactive):
68 def test_should_register_itself_as_project_for_added_actions(self):
69 a = self.create_action_with_status()
70 self.project.add_action(a)
71 self.assertEqual(a.project,self.project)
73 def test_should_register_itself_as_observer_for_added_actions(self):
74 a = self.create_action()
75 self.project.add_action(a)
76 a.observers.append.assert_called_with(self.project)
78 def test_should_notify_observer_of_added_actions(self):
80 a.status = action.done
81 self.project.add_action(a)
82 self.assert_observed('add_action', a)
84 def test_should_notify_observers_of_action_status_changes(self):
85 for a in self.project.actions:
86 self.project.action_changed_status(a, action.active)
87 self.assert_observed('changed_action', a, None)
89 def test_should_set_added_unprocessed_actions_to_active(self):
91 a.status = action.unprocessed
92 self.project.add_action(a)
93 self.assertEqual(a.status,action.active)
95 def test_should_be_equal_if_name_and_status_are_identical(self):
97 other.name = self.project.name
98 other.status = self.project.status
99 self.assertTrue(self.project == other)
100 self.assertFalse(self.project != other)
101 other.name = 'other name'
102 self.assertTrue(self.project != other)
104 def assert_observed(self,attribute,new=None,old=None):
105 calls = self.observer.notify.call_args_list
106 self.assertTrue(((self.project,attribute),{'new':new,'old':old}) in calls,
107 'Expected notification from %s concerning the change of %s from %s to %s\n Only got these calls:\n%s'%(repr(self.project),repr(attribute),repr(old),repr(new),repr(calls)))
109 def assert_observed_status(self,status,previous_status=None):
110 if not previous_status:
111 previous_status = self.status
112 self.assert_status(status)
113 self.assert_observed('status',status,previous_status)
115 def assert_status(self,status):
116 self.assertEqual(self.project.status,status)
118 class ActiveProjectBehaviour(ProjectBehaviour):
120 def initial_actions(self):
121 a = self.create_action_with_status(action.active)
124 def initial_status(self):
125 return project.active
127 def test_should_be_active(self):
128 self.assert_status(project.active)
130 def test_should_contain_active_actions(self):
131 self.assertTrue(self.project.has_active_actions())
133 # def test_should_become_inactive_if_no_active_action_remains(self):
134 # self.project.status = project.active
135 # for a in self.project.actions_with_status(action.active):
136 # self.project.remove_action(a)
137 # self.assert_observed_status(project.inactive)
139 # def test_should_become_inactive_when_active_actions_become_inactive(self):
140 # self.project.status = project.active
141 # for a in self.project.actions_with_status(action.active):
142 # a.status = action.done
143 # self.project.notify(a,'status',action.done)
144 # self.assert_observed_status(project.inactive)
146 def test_should_deactivate_its_active_actions_on_deactivate(self):
147 active_actions = self.project.actions_with_status(action.active)
148 self.project.deactivate()
149 self.assertEqual(self.project.status,project.inactive)
150 for a in active_actions:
151 self.assertEqual(a.status,action.inactive)
156 class InactiveProjectBehaviour(ProjectBehaviour):
157 def initial_status(self):
158 return project.inactive
159 def test_should_be_inactive(self):
160 self.assert_status(project.inactive)
162 # def test_should_become_active_if_active_actions_are_added(self):
164 # a.status = action.active
165 # self.project.add_action(a)
166 # self.assertEqual(self.project.status,project.active)
168 def test_should_activate_all_inactive_actions_when_activated_itself(self):
169 inactive_actions = self.project.actions_with_status(action.inactive)
170 for a in inactive_actions:
171 self.assertEqual(a.status,action.inactive)
172 self.project.activate()
173 for a in inactive_actions:
174 self.assertEqual(a.status,action.active)
176 class EmptyProjectBehaviour(InactiveProjectBehaviour):
178 def test_should_return_an_empty_list_of_actions(self):
179 self.assertEqual(self.project.actions,[])
181 def test_should_return_an_empty_list_of_infos(self):
182 self.assertEqual(self.project.infos,[])
185 class ProjectWithActionsBehaviour(ProjectBehaviour):
187 self.action = self.create_action()
188 super(ProjectWithActionsBehaviour,self).setUp()
190 def initial_actions(self):
193 def test_should_contain_all_added_actions(self):
194 self.assertEqual(self.project.actions,self.actions)
196 def test_should_forget_removed_actions(self):
197 self.project.remove_action(self.actions[0])
198 self.assertFalse(self.actions[0] in self.project.actions)
200 def test_should_remove_itself_as_observer_for_removed_actions(self):
201 self.project.remove_action(self.actions[0])
202 self.actions[0].observers.remove.assert_called_with(self.project)
204 def test_should_set_action_to_done_before_removing(self):
205 self.project.remove_action(self.actions[0])
206 self.assertEqual(self.actions[0].status,action.done)
208 def test_should_notify_observer_of_removed_actions(self):
209 self.project.remove_action(self.actions[0])
210 self.assert_observed('remove_action',self.actions[0],None)
212 def test_generator(field):
213 def test_should_notify_observer_of_changes_in_actions(self):
214 self.project.notify(self.actions[0], field, 'new %s'%field)
215 self.assert_observed('changed_action',self.actions[0])
216 return test_should_notify_observer_of_changes_in_actions
218 for field in ['description','info','context']:
219 no_change_on_action_becoming_active = 'test_should_notify_observer_of_changes_in_action_%s' % field
220 test = test_generator(field)
221 setattr(ProjectWithActionsBehaviour, no_change_on_action_becoming_active, test)
224 class ProjectWithInactiveActionsBehaviour(ProjectWithActionsBehaviour):
226 def action_status(self):
227 return action.inactive
229 # def test_should_become_active_when_inactive_actions_become_active(self):
230 # self.actions[0].status = action.active
231 # self.project.notify(self.actions[0],'status',action.active)
232 # self.assert_observed_status(project.active)
234 def test_should_return_the_inactive_action(self):
235 self.assertEqual(self.project.actions_with_status(action.inactive),[self.actions[0]])
237 def test_should_return_no_active_action(self):
238 self.assertEqual(self.project.actions_with_status(action.active),[])
242 class InactiveProjectWithInactiveActionsBehaviour(ProjectWithInactiveActionsBehaviour,InactiveProjectBehaviour):
246 class ProjectWithActiveActionsBehaviour(ProjectWithActionsBehaviour):
248 def action_status(self):
251 def test_should_return_the_active_action(self):
252 self.assertEqual(self.project.actions_with_status(action.active),[self.actions[0]])
254 def test_should_return_no_inactive_action(self):
255 self.assertEqual(self.project.actions_with_status(action.inactive),[])
259 #class ActiveProjectWithActiveActionsBehaviour(ProjectWithActiveActionsBehaviour,ActiveProjectBehaviour):
264 class ProjectWithInfosBehaviour(ProjectBehaviour):
267 super(ProjectWithInfosBehaviour,self).setUp()
269 self.project.add_info(self.info)
271 def test_should_contain_all_added_infos(self):
272 self.assertEqual(self.project.infos,[self.info])
274 def test_should_really_forget_removed_infos(self):
275 self.project.remove_info(self.info)
276 self.assertFalse(self.info in self.project.infos)
278 def test_should_register_itself_as_observer_for_added_infos(self):
279 self.info.observers.append.assert_called_with(self.project)
281 def test_should_deregister_itself_as_observer_for_removed_infos(self):
282 self.project.remove_info(self.info)
283 self.info.observers.remove.assert_called_with(self.project)
286 def test_should_notify_observer_of_removed_infos(self):
287 self.project.remove_info(self.info)
288 self.assert_observed('remove_info',self.info)
290 def test_should_notify_observer_of_changes_in_infos(self):
291 self.project.notify(self.info, 'text', 'new text')
292 self.assert_observed('changed_info',self.info)
297 def generate_no_becoming_active_test(status):
298 def initial_status(self):
300 def test_should_not_change_status_if_actions_become_active(self):
301 self.project.notify(self.actions[0], 'status', action.active)
302 self.assertEqual(status,self.project.status)
303 def test_should_not_change_status_if_active_actions_are_added(self):
305 a.status = action.active
306 self.project.add_action(a)
307 self.assertEqual(status,self.project.status)
308 return (initial_status,test_should_not_change_status_if_actions_become_active,test_should_not_change_status_if_active_actions_are_added)
310 for status in ['someday','done','tickled']:
311 class_name = '%sProjectBehaviour'%status.capitalize()
312 my_class=type(class_name,(ProjectWithActiveActionsBehaviour,),{})
313 no_change_on_action_becoming_active = 'test_should_not_change_%s_status_if_actions_become_active' % status
314 no_change_on_active_action_added= 'test_should_not_change_%s_status_if_active_actions_are_added' % status
315 initial_status,no_change_on_action_becoming_active_test,no_change_on_active_action_added_test = generate_no_becoming_active_test(getattr(model.project,status))
317 setattr(my_class, 'initial_status', initial_status)
318 setattr(my_class, no_change_on_action_becoming_active, no_change_on_action_becoming_active_test)
319 setattr(my_class, no_change_on_active_action_added, no_change_on_active_action_added_test)
320 globals()[class_name]=my_class