def test_events_can_be_fetched_ordered_by_date(self): more_changes = [("2015-05-01", 3), ("2015-05-02", 5), ("2015-05-09", -8)] events = self.create_events(self.sprint, self.changes + more_changes) assert len(events) == len(Event.get_events(self.sprint)) timetable = Event.get_events_timetable(self.sprint) assert 2 == len(timetable["2015-05-01"]) assert -2 == sum(timetable["2015-05-01"])
def test_item_create_calls_item_created_event(self, mock_create_event): sprint = Sprint.objects.create( name='256', start_date=self.today, end_date=self.tomorrow ) item = Item( name='Int.32', description='test item', estimate_work=3, estimate_review=2, sprint=sprint ) expected_event = Event( sprint=sprint, change=Event.INC, value=5 ) mock_create_event.return_value = expected_event item.save() events = Event.get_events(sprint) assert len(events) == 1 event = events[0] assert event.sprint == expected_event.sprint assert event.change == expected_event.change assert event.value == expected_event.value
def scrumboard_chart_burndown(sprint): from scrumboard.models import Event timetable = Event.get_events_timetable(sprint) from datetime import timedelta, date def daterange(start_date, end_date): for n in range(int((end_date - start_date).days)): yield start_date + timedelta(n) def iso_date(single_date): return single_date.strftime("%Y-%m-%d") tomorrow = date.today() + timedelta(days=1) labels1 = [iso_date(single_date) for single_date in daterange(sprint.start_date, tomorrow)] # TODO: if not single_date in sprint.excluded_days() labels2 = [iso_date(single_date) for single_date in daterange(tomorrow, sprint.end_date + timedelta(days=1))] from itertools import accumulate dataset_burndown = list(accumulate([sum(timetable[l]) for l in labels1])) sprint_length = int((sprint.end_date - sprint.start_date).days) # TODO: sprint.length() that takes free days into account dataset_prognosis = [sprint.capacity*(1.0 - x/sprint_length) for x in range(sprint_length)] + [0] return {'sprint': sprint, 'labels': labels1 + labels2, 'dataset_burndown': dataset_burndown, 'dataset_prognosis': dataset_prognosis}
def test_for_status(status): self.item.status = status event = Event.create_item_deleted_event(self.item) assert isinstance(event, Event) assert event.change == Event.DEC assert event.value == 2 assert event.sprint == self.sprint
def test_if_event_can_be_created(self): event = Event.objects.create( sprint=self.sprint, change=Event.INC, value=3 ) assert event in Event.get_events(self.sprint)
def test_create_event_review_estimate_decreased(self): self.item.estimate_work -= 5 events = Event.create_item_changed_events(self.item) assert len(events) == 1 assert events[0].change == Event.DEC assert events[0].value == 5 assert events[0].sprint == self.sprint
def test_create_event_work_estimate_increased(self): self.item.estimate_work += 5 events = Event.create_item_changed_events(self.item) assert len(events) == 1 assert events[0].change == Event.INC assert events[0].value == 5 assert events[0].sprint == self.sprint
def test_create_event_review_estimate_decreased_and_work_estimate_increased(self): self.item.estimate_work += 5 self.item.estimate_review -= 1 events = Event.create_item_changed_events(self.item) assert len(events) == 1 assert events[0].change == Event.INC assert events[0].value == 4 assert events[0].sprint == self.sprint
def test_move_item_takes_nothing_when_status_external_review(self): item = Item.objects.create( name="Item", sprint=self.sprint1, estimate_work=13, estimate_review=2, status=Item.EXTERNAL_REVIEW ) item.sprint = self.sprint2 events = Event.create_item_changed_events(item) assert len(events) == 0
def test_external_review_to_done(self): item = Item.objects.create( name="Item", sprint=self.sprint1, estimate_work=21, estimate_review=13, status=Item.EXTERNAL_REVIEW ) item.status = Item.DONE events = Event.create_item_changed_events(item) assert len(events) == 0
def test_committed_to_blocked(self): item = Item.objects.create( name="Item", sprint=self.sprint1, estimate_work=21, estimate_review=13, status=Item.COMMITTED ) item.status = Item.BLOCKED events = Event.create_item_changed_events(item) assert len(events) == 0
def test_review_to_fix(self): item = Item.objects.create( name="Item", sprint=self.sprint1, estimate_work=8, estimate_review=3, status=Item.REVIEW ) item.status = Item.FIX events = Event.create_item_changed_events(item) assert len(events) == 0
def test_committed_to_wip(self): item = Item.objects.create( name="Item", sprint=self.sprint1, estimate_work=8, estimate_review=3, status=Item.COMMITTED ) item.status = Item.WIP events = Event.create_item_changed_events(item) assert len(events) == 0
def test_fix_to_external_review(self): item = Item.objects.create( name="Item", sprint=self.sprint1, estimate_work=21, estimate_review=13, status=Item.FIX ) item.status = Item.EXTERNAL_REVIEW events = Event.create_item_changed_events(item) assert len(events) == 1 assert events[0].change == Event.DEC assert events[0].value == 13
def test_wip_to_pending_review(self): item = Item.objects.create( name="Item", sprint=self.sprint1, estimate_work=8, estimate_review=3, status=Item.WIP ) item.status = Item.PENDING_REVIEW events = Event.create_item_changed_events(item) assert len(events) == 1 assert events[0].change == Event.DEC assert events[0].value == 8
def test_move_item_takes_effort_and_review_when_status_blocked(self): item = Item.objects.create( name="Item", sprint=self.sprint1, estimate_work=13, estimate_review=3, status=Item.BLOCKED ) item.sprint = self.sprint2 events = Event.create_item_changed_events(item) assert len(events) == 2 assert events[0].change == Event.INC assert events[0].value == 16 assert events[0].sprint == self.sprint2 assert events[1].change == Event.DEC assert events[1].value == 16 assert events[1].sprint == self.sprint1
def test_move_item_takes_only_review_when_status_fix(self): item = Item.objects.create( name="Item", sprint=self.sprint1, estimate_work=5, estimate_review=3, status=Item.FIX ) item.sprint = self.sprint2 events = Event.create_item_changed_events(item) assert len(events) == 2 assert events[0].change == Event.INC assert events[0].value == 3 assert events[0].sprint == self.sprint2 assert events[1].change == Event.DEC assert events[1].value == 3 assert events[1].sprint == self.sprint1
def test_move_item_takes_only_review_when_status_pending_review(self): item = Item.objects.create( name="Item", sprint=self.sprint1, estimate_work=13, estimate_review=5, status=Item.PENDING_REVIEW ) item.sprint = self.sprint2 events = Event.create_item_changed_events(item) assert len(events) == 2 assert events[0].change == Event.INC assert events[0].value == 5 assert events[0].sprint == self.sprint2 assert events[1].change == Event.DEC assert events[1].value == 5 assert events[1].sprint == self.sprint1
def test_for_status(status): item = Item.objects.create( name="Item", sprint=self.sprint1, estimate_work=8, estimate_review=3, status=status ) item.sprint = self.sprint2 events = Event.create_item_changed_events(item) assert len(events) == 2 assert events[0].change == Event.INC assert events[0].value == 11 assert events[0].sprint == self.sprint2 assert events[1].change == Event.DEC assert events[1].value == 11 assert events[1].sprint == self.sprint1
def test_for_status(status): self.item.status = status assert Event.create_item_deleted_event(self.item) is None
def test_do_not_create_event_for_item_update_when_item_is_not_updated(self): events = Event.create_item_changed_events(self.item) assert 0 == len(events)
def test_do_not_create_event_for_instance_created_if_estimates_are_0(self): self.item.estimate_work = 0 self.item.estimate_review = 0 assert Event.create_item_created_event(self.item) is None
def test_no_event_when_no_estimate_changed(self): assert 0 == len(Event.create_item_changed_events(self.item))
def test_events_can_be_fetched_by_sprint(self): events = self.create_events(self.sprint, self.changes) assert len(events) == len(Event.get_events(self.sprint))