コード例 #1
0
ファイル: sprint_test.py プロジェクト: nagyist/agilo
 def setUp(self):
     self.super()
     self.start = normalize_date(now())
     duration = timedelta(days=20)
     self.end = normalize_date(self.start + duration)
     self.manager = SprintModelManager(self.env)
     self.tmm = TeamMemberModelManager(self.env)
コード例 #2
0
def create_emtpy_sprint(env):
    assert sprint_name != None, 'Please configure a sprint name.'
    sprint = SprintModelManager(env).create(name=sprint_name,
                                                  start=now(),
                                                  duration=14)
    assert sprint is not None
    t_manager = AgiloTicketModelManager(env)
    for t_id, t_type, t_status in sprint._fetch_tickets():
        ticket = t_manager.create(tkt_id=t_id, t_type=t_type)
        if ticket[Key.SPRINT] == sprint.name:
            ticket[Key.SPRINT] = None
            t_manager.save(ticket, None, 'reset sprint field for performance measurement')
コード例 #3
0
ファイル: rules.py プロジェクト: djangsters/agilo
 def _ensure_milestone_fits_to_sprint(self, ticket, sprint_name):
     milestone_name = self._milestone_name_from_ticket(ticket)
     pulled_task_into_milestone = milestone_name is not None and Key.MILESTONE in ticket._old
     moved_task_between_milestones = (Key.SPRINT in ticket._old and ticket._old[Key.SPRINT] != sprint_name)
     milestone_did_change = pulled_task_into_milestone or moved_task_between_milestones
     if not milestone_did_change:
         return
     # Now checks if the milestone is compatible with the current set sprint
     # otherwise reset the sprint value
     sp_manager = SprintModelManager(self.env)
     sprints = [s.name for s in sp_manager.select(criteria={'milestone': milestone_name})]
     if not ticket[Key.SPRINT] in sprints:
         # The milestone is changed, and the sprint not, probably is an high
         #level re-planning, so reset the Sprint. 
         ticket[Key.SPRINT] = None
コード例 #4
0
ファイル: sprint_test.py プロジェクト: djangsters/agilo
 def setUp(self):
     self.super()
     self.start = normalize_date(now())
     duration = timedelta(days=20)
     self.end = normalize_date(self.start + duration)
     self.manager = SprintModelManager(self.env)
     self.tmm = TeamMemberModelManager(self.env)
コード例 #5
0
ファイル: web_ui.py プロジェクト: djangsters/agilo
class SprintModule(Component):
    """Module to handle Sprint objects"""
    
    implements(ITemplateProvider, ITimelineEventProvider, IPermissionRequestor)

    def __init__(self, *args, **kwargs):
        """Sets a SprintModelManager"""
        super(SprintModule, self).__init__(*args, **kwargs)
        self.sp_manager = SprintModelManager(self.env)
        self.tm_manager = TeamModelManager(self.env)
        
    #=============================================================================
    # IPermissionRequestor methods
    #=============================================================================
    def get_permission_actions(self):
        actions = [Action.SPRINT_VIEW, Action.SPRINT_EDIT]
        return actions + [(Action.SPRINT_ADMIN, actions)]
    
    #=============================================================================
    # ITemplateProvider methods
    #=============================================================================
    def get_htdocs_dirs(self):
        return []
    
    def get_templates_dirs(self):
        return [resource_filename('agilo.scrum.sprint', 'templates')]
    
    #==========================================================================
    # ITimelineEventProvider methods
    #==========================================================================
    def get_timeline_filters(self, req):
        if Action.SPRINT_VIEW in req.perm:
            yield (Key.SPRINT, 'Sprints')

    def get_timeline_events(self, req, start, stop, filters):
        if Key.SPRINT not in filters:
            return
        # prepare select criteria
        criteria = {'start': '>=%d' % to_timestamp(start),
                    'start': '<=%d' % to_timestamp(stop)}
        for sprint in self.sp_manager.select(criteria=criteria):
            # the first value of the data tuple tells if we're showing
            # a start or an end date (True=start, False=end), see next function
            if sprint.is_currently_running:
                yield(Key.SPRINT, sprint.start, '', (True, sprint))
            if sprint.is_closed:
                yield(Key.SPRINT, sprint.end, '', (False, sprint))

    def render_timeline_event(self, context, field, event):
        (start, sprint) = event[3]
        if field == 'url':
            return context.href.sprint(sprint.name)
        elif field == 'title':
            if start:
                return tag('Sprint ', tag.em(sprint.name), ' started')
            return tag('Sprint ', tag.em(sprint.name), ' finished')
        elif field == 'description':
            return format_to(self.env, None, context(resource=sprint),
                             sprint.description)
コード例 #6
0
 def _ensure_milestone_fits_to_sprint(self, ticket, sprint_name):
     milestone_name = self._milestone_name_from_ticket(ticket)
     pulled_task_into_milestone = milestone_name is not None and Key.MILESTONE in ticket._old
     moved_task_between_milestones = (
         Key.SPRINT in ticket._old
         and ticket._old[Key.SPRINT] != sprint_name)
     milestone_did_change = pulled_task_into_milestone or moved_task_between_milestones
     if not milestone_did_change:
         return
     # Now checks if the milestone is compatible with the current set sprint
     # otherwise reset the sprint value
     sp_manager = SprintModelManager(self.env)
     sprints = [
         s.name
         for s in sp_manager.select(criteria={'milestone': milestone_name})
     ]
     if not ticket[Key.SPRINT] in sprints:
         # The milestone is changed, and the sprint not, probably is an high
         #level re-planning, so reset the Sprint.
         ticket[Key.SPRINT] = None
コード例 #7
0
ファイル: model.py プロジェクト: nagyist/agilo
 def __init__(self, env, default_capacity=[6, 6, 6, 6, 6, 0, 0], **kwargs):
     """
     Initialize the TeamMember object wrapping the default capacity
     into a list of value
     """
     days = dict()
     for i, day in self.DAYS.items():
         days['ts_%s' % day] = default_capacity[i]
     kwargs.update(days)
     super(TeamMember, self).__init__(env, **kwargs)
     # Instance of Sprint Model Manager
     from agilo.scrum.sprint import SprintModelManager
     self.sp_manager = SprintModelManager(self.env)
コード例 #8
0
    def validate(self, ticket):
        """Validate the ticket against the defined rules"""
        debug(self, "Called validate(%s)..." % ticket)
        if ticket is not None and isinstance(ticket, AgiloTicket) and \
                Key.REMAINING_TIME in ticket.fields_for_type:

            sprint_name = ticket[Key.SPRINT]
            if sprint_name not in (None, ''):
                sprint = SprintModelManager(self.env).get(name=sprint_name)
                if sprint and sprint.team is not None:
                    owner = ticket[Key.OWNER]
                    self.check_team_membership(ticket,
                                               sprint,
                                               owner,
                                               is_owner=True)
                    for r in ticket.get_resource_list():
                        self.check_team_membership(ticket, sprint, r)
コード例 #9
0
class MetricsChartWidget(FlotChartWidget):
    """This widget generates HTML and JS code so that Flot can generate a 
    chart for the team metrics (per sprint) combining some metrics."""
    
    default_width =  400
    default_height = 200
    
    def __init__(self, env, **kwargs):
        from agilo.scrum.sprint import SprintModelManager
        template_filename = 'scrum/metrics/templates/agilo_metrics_chart.html'
        self._define_chart_resources(env, template_filename, kwargs)
        super(MetricsChartWidget, self).__init__(env, template_filename, **kwargs)
        self.sp_manager = SprintModelManager(env)
    
    def _get_metrics_data(self, metric_names, sprint_names, metrics_by_sprint):
        metrics = []
        for label in metric_names:
            metric_values = []
            for i, sprint_name in enumerate(sprint_names):
                m = metrics_by_sprint[sprint_name]
                value = m[label]
                if value != None:
                    metric_values.append((i, value))
            metrics.append((get_label(label), metric_values))
        return metrics
    
    def _make_title(self, metric_names):
        titles = []
        for name in metric_names:
            titles.append(get_label(name))
        return ' / '.join(titles)
    
    def fill(self, team_name, metric_names):
        # Charts are not allowed to import the model classes globally
        from agilo.scrum.metrics import TeamMetrics
        sprints = self.sp_manager.select( 
                                criteria={'team': team_name}, 
                                order_by=['%s' % Key.START])
        sprint_names = [sprint.name for sprint in sprints]
        metrics_by_sprint = dict([(s.name, TeamMetrics(self.env, sprint=s)) \
                                  for s in sprints])
        metrics = self._get_metrics_data(metric_names, sprint_names, metrics_by_sprint)
        title = self._make_title(metric_names)
        self.data.update(
            dict(team_name=team_name, sprint_names=sprint_names,
                 metrics=metrics, title=title))
コード例 #10
0
ファイル: web_ui.py プロジェクト: nagyist/agilo
class SprintModule(Component):
    """Module to handle Sprint objects"""

    implements(ITemplateProvider, ITimelineEventProvider, IPermissionRequestor)

    def __init__(self, *args, **kwargs):
        """Sets a SprintModelManager"""
        super(SprintModule, self).__init__(*args, **kwargs)
        self.sp_manager = SprintModelManager(self.env)
        self.tm_manager = TeamModelManager(self.env)

    #=============================================================================
    # IPermissionRequestor methods
    #=============================================================================
    def get_permission_actions(self):
        actions = [Action.SPRINT_VIEW, Action.SPRINT_EDIT]
        return actions + [(Action.SPRINT_ADMIN, actions)]

    #=============================================================================
    # ITemplateProvider methods
    #=============================================================================
    def get_htdocs_dirs(self):
        return []

    def get_templates_dirs(self):
        return [resource_filename('agilo.scrum.sprint', 'templates')]

    #==========================================================================
    # ITimelineEventProvider methods
    #==========================================================================
    def get_timeline_filters(self, req):
        if Action.SPRINT_VIEW in req.perm:
            yield (Key.SPRINT, 'Sprints')

    def get_timeline_events(self, req, start, stop, filters):
        if Key.SPRINT not in filters:
            return
        # prepare select criteria
        criteria = {
            'start': '>=%d' % to_timestamp(start),
            'start': '<=%d' % to_timestamp(stop)
        }
        for sprint in self.sp_manager.select(criteria=criteria):
            # the first value of the data tuple tells if we're showing
            # a start or an end date (True=start, False=end), see next function
            if sprint.is_currently_running:
                yield (Key.SPRINT, sprint.start, '', (True, sprint))
            if sprint.is_closed:
                yield (Key.SPRINT, sprint.end, '', (False, sprint))

    def render_timeline_event(self, context, field, event):
        (start, sprint) = event[3]
        if field == 'url':
            return context.href.sprint(sprint.name)
        elif field == 'title':
            if start:
                return tag('Sprint ', tag.em(sprint.name), ' started')
            return tag('Sprint ', tag.em(sprint.name), ' finished')
        elif field == 'description':
            return format_to(self.env, None, context(resource=sprint),
                             sprint.description)
コード例 #11
0
ファイル: web_ui.py プロジェクト: nagyist/agilo
 def __init__(self, *args, **kwargs):
     """Sets a SprintModelManager"""
     super(SprintModule, self).__init__(*args, **kwargs)
     self.sp_manager = SprintModelManager(self.env)
     self.tm_manager = TeamModelManager(self.env)
コード例 #12
0
ファイル: sprint_test.py プロジェクト: nagyist/agilo
class TestSprint(AgiloTestCase):
    """
    Tests the Sprint object
    """
    def setUp(self):
        self.super()
        self.start = normalize_date(now())
        duration = timedelta(days=20)
        self.end = normalize_date(self.start + duration)
        self.manager = SprintModelManager(self.env)
        self.tmm = TeamMemberModelManager(self.env)

    def testSprintCreationWithDates(self):
        """Tests the Sprint creation with the start and end date"""
        sprint = self.manager.create(name="Test Sprint",
                                     start=self.start,
                                     end=self.end)
        self.assert_equals(
            sprint.duration,
            count_working_days(self.start.date(), self.end.date()))
        # Now save the sprint and reload it from the DB
        # AT: With the manager the sprint is already saved
        # self.manager.save(sprint)
        sprint = self.manager.get(name="Test Sprint")
        self.assert_equals(
            sprint.duration,
            count_working_days(self.start.date(), self.end.date()))
        self.assert_equals(self.end, sprint.end)
        self.assert_equals(self.start, sprint.start)
        # Now add a description and test the reload
        sprint.description = 'This is a test Sprint'
        self.manager.save(sprint)
        # clear the cache so we are sure it will be reloaded from the DB
        self.manager.get_cache().invalidate()
        sprint = self.manager.get(name="Test Sprint")
        self.assert_equals(sprint.description, 'This is a test Sprint')

    def testSprintUpdateDuration(self):
        """
        Tests the Sprint update of the duration in case start, or end, 
        or duration are changed
        """
        sprint = self.manager.create(name="Test Sprint",
                                     start=self.start,
                                     end=self.end)
        self.assert_equals(
            sprint.duration,
            count_working_days(sprint.start.date(), sprint.end.date()))
        # Now change the start date +1
        sprint.start = sprint.start + timedelta(days=1)
        self.assert_equals(
            sprint.duration,
            count_working_days(sprint.start.date(), sprint.end.date()))
        # Now move the end -1
        sprint.end = sprint.end - timedelta(days=1)
        self.assert_equals(
            sprint.duration,
            count_working_days(sprint.start.date(), sprint.end.date()))

    def testSprintCreateWithStartDuration(self):
        """
        Test the creation of a sprint setting the start date and the
        duration in working days
        """
        sprint = self.teh.create_sprint(name="Test Sprint",
                                        start=self.start,
                                        end=self.end)
        another_sprint = self.teh.create_sprint(name="Another Sprint",
                                                start=self.start,
                                                duration=sprint.duration)
        # Check they have the same end date...
        self.assert_equals(sprint.end.date(), another_sprint.end.date())
        # Now, save and load and check that the data are set correctly
        # FIXME: where is the check mentioned in the above comment?
        # Now change the end and see if the duration change as well
        another_sprint.end = another_sprint.end + timedelta(days=1)
        self.assert_true(another_sprint.duration > sprint.duration)

    def testSprintSelect(self):
        """Test the Sprint select function"""
        self.manager.create(name="Test Sprint 1",
                            start=self.start,
                            end=self.end)
        self.manager.create(name="Test Sprint 2",
                            start=self.start,
                            end=self.end)
        self.manager.create(name="Test Sprint 3",
                            start=parse_date("2008-06-10"),
                            end=parse_date("2008-06-30"))
        # Now test the select
        sprints = self.manager.select(
            criteria={'end': '> %d' % to_timestamp(now())})
        self.assert_equals(len(sprints), 2)
        sprints = self.manager.select()
        self.assert_equals(len(sprints), 3)

    def testDeleteSprint(self):
        """Tests the deletion of a Sprint"""
        sprint1 = self.manager.create(name="Test Sprint 1",
                                      start=self.start,
                                      end=self.end)
        self.assert_true(sprint1.exists)
        self.assert_true(self.manager.delete(sprint1))
        # Now make sure is not there anymore
        self.manager.get(name="Test Sprint 1")

    def testRenameSprint(self):
        """Tests the Sprint rename"""
        name = 'Test sprint name'
        sprint = self.manager.create(name=name, start=self.start, end=self.end)
        self.assert_true(sprint.exists)
        self.assert_equals(sprint.name, name)

        # create a ticket for this sprint
        t = self.teh.create_ticket(Type.USER_STORY, props={Key.SPRINT: name})
        # reload ticket
        self.assert_equals(t[Key.SPRINT], name)
        # create a metrics object
        team = self.teh.create_team(name='Testteam')
        metrics = TeamMetrics(self.env, sprint, team)
        metrics['test'] = 1.0
        metrics.save()

        # Rename the sprint
        new_name = 'New sprint name'
        sprint.name = new_name
        self.assert_true(self.manager.save(sprint))
        self.assert_equals(sprint.name, new_name)
        # Remove the sprint from the cache and reload it again
        self.manager.get_cache().invalidate(model_instance=sprint)
        # check new name after reload
        sprint = self.manager.get(name=new_name)
        self.assert_equals(sprint.name, new_name)

        t = self.teh.load_ticket(t_id=t.id)
        # sprint in ticket and metrics should be renamed as well
        self.assert_equals(t[Key.SPRINT], new_name)
        metrics = TeamMetrics(self.env, sprint, team)
        self.assert_equals(metrics.sprint, sprint)
        self.assert_equals(metrics['test'], 1.0)

        # Rename the sprint with some not allowed characters
        new_name = "That's my sprint!"
        sprint.name = new_name
        self.assert_true(sprint.save())
        self.assert_equals(sprint.name, new_name)

        # check new name after reload
        sprint = Sprint(self.env, name=new_name)
        self.assert_equals(sprint.name, new_name)

    def testAssignTeamToSprint(self):
        """Tests the assignment of a team to a Sprint"""
        team = self.teh.create_team(name="The Team")
        self.teh.create_member(name="Team Member 1", team=team)
        self.teh.create_member(name="Team Member 2", team=team)
        # Now create a Sprint
        s = self.manager.create(name="Test S", team=team)

        self.assert_equals(team.name, s.team.name)
        for i, member in enumerate(team.members):
            self.assert_equals(member.name, s.team.members[i].name)

    def testSprintClosedAndIsCurrentlyRunning(self):
        """Tests the is_closed and is_started"""
        start = now() - timedelta(days=3)  # no risk to get a weekend
        s = self.teh.create_sprint("Test", start=start)
        self.assert_true(s.is_currently_running)
        self.assert_false(s.is_closed)
        s.start += timedelta(
            days=5
        )  # Move 5 to make sure that we will overcome also a normalization over a weekend
        self.assert_false(s.is_currently_running, "%s <= %s  < %s" % \
                         (s.start, start, s.end))
        self.assert_false(s.is_closed)

        # check functions for an old, closed sprint
        s.start = parse_date("2008-01-01")
        s.end = parse_date("2008-01-31")
        self.assert_false(s.is_currently_running)
        self.assert_true(s.is_closed)

    def testSprintIsNotCurrentlyRunningAfterSprintEnd(self):
        today = now()
        sprint_start = today - timedelta(days=20)
        sprint = self.teh.create_sprint("Test", start=sprint_start)
        sprint.end = today - timedelta(days=10)
        # Sprint ended ten days before today
        self.assert_false(sprint.is_currently_running)
        self.assert_true(sprint.is_closed)

    def testLoadSprintWhichHasNoStartDate(self):
        self.manager.create(name='foo')
        sprint = self.manager.get(name='foo')
        self.assert_true(sprint.exists)
        self.assert_equals('foo', sprint.name)

    def testCanDisableSprintStartDateNormalization(self):
        config = AgiloConfig(self.env).get_section(AgiloConfig.AGILO_GENERAL)
        option_name = 'sprints_can_start_or_end_on_weekends'
        self.assert_false(config.get_bool(option_name))
        config.change_option(option_name, True, save=True)
        self.assert_true(
            AgiloConfig(self.env).sprints_can_start_or_end_on_weekends)

        start = datetime(2009, 05, 30, tzinfo=utc)
        sprint = self.teh.create_sprint('Foo', start=start)
        self.assert_equals(start, sprint.start)
        self.assert_equals(utc, sprint.start.tzinfo)

    def testManagerAttributeIsNotSerialized(self):
        sprint = self.teh.create_sprint('Foo Sprint')
        sprint_dict = sprint.as_dict()
        self.assert_false('manager' in sprint_dict)

    def test_can_build_resource(self):
        sprint = self.teh.create_sprint('Foo Sprint')
        self.assert_equals(Resource(Realm.SPRINT, sprint.name),
                           sprint.resource())

    def test_can_build_by_duration_without_normalization(self):
        self.teh.disable_sprint_date_normalization()
        some_friday = datetime(day=30, month=4, year=2010)
        self.assert_equals(4, some_friday.weekday())

        sprint = self.teh.create_sprint('Foo Sprint',
                                        start=some_friday,
                                        duration=4)
        sprint_length = (sprint.end - sprint.start).days
        self.assert_equals(3, sprint_length)
コード例 #13
0
ファイル: model.py プロジェクト: nagyist/agilo
 def __init__(self, *args, **kwargs):
     """Set managers instance for other persistent objects"""
     super(Team, self).__init__(*args, **kwargs)
     from agilo.scrum.sprint import SprintModelManager
     self.sp_manager = SprintModelManager(self.env)
コード例 #14
0
ファイル: web_ui.py プロジェクト: djangsters/agilo
 def __init__(self, *args, **kwargs):
     """Sets a SprintModelManager"""
     super(SprintModule, self).__init__(*args, **kwargs)
     self.sp_manager = SprintModelManager(self.env)
     self.tm_manager = TeamModelManager(self.env)
コード例 #15
0
ファイル: sprint_test.py プロジェクト: djangsters/agilo
class TestSprint(AgiloTestCase):
    """
    Tests the Sprint object
    """
    def setUp(self):
        self.super()
        self.start = normalize_date(now())
        duration = timedelta(days=20)
        self.end = normalize_date(self.start + duration)
        self.manager = SprintModelManager(self.env)
        self.tmm = TeamMemberModelManager(self.env)
    
    def testSprintCreationWithDates(self):
        """Tests the Sprint creation with the start and end date"""
        sprint = self.manager.create(name="Test Sprint", start=self.start, end=self.end)
        self.assert_equals(sprint.duration, count_working_days(self.start.date(), self.end.date()))
        # Now save the sprint and reload it from the DB
        # AT: With the manager the sprint is already saved
        # self.manager.save(sprint)
        sprint = self.manager.get(name="Test Sprint")
        self.assert_equals(sprint.duration, count_working_days(self.start.date(), self.end.date()))
        self.assert_equals(self.end, sprint.end)
        self.assert_equals(self.start, sprint.start)
        # Now add a description and test the reload
        sprint.description = 'This is a test Sprint'
        self.manager.save(sprint)
        # clear the cache so we are sure it will be reloaded from the DB
        self.manager.get_cache().invalidate()
        sprint = self.manager.get(name="Test Sprint")
        self.assert_equals(sprint.description, 'This is a test Sprint')
    
    def testSprintUpdateDuration(self):
        """
        Tests the Sprint update of the duration in case start, or end, 
        or duration are changed
        """
        sprint = self.manager.create(name="Test Sprint", start=self.start, end=self.end)
        self.assert_equals(sprint.duration, count_working_days(sprint.start.date(), sprint.end.date()))
        # Now change the start date +1
        sprint.start = sprint.start + timedelta(days=1)
        self.assert_equals(sprint.duration, count_working_days(sprint.start.date(), sprint.end.date()))
        # Now move the end -1
        sprint.end = sprint.end - timedelta(days=1)
        self.assert_equals(sprint.duration, count_working_days(sprint.start.date(), sprint.end.date()))
    
    def testSprintCreateWithStartDuration(self):
        """
        Test the creation of a sprint setting the start date and the
        duration in working days
        """
        sprint = self.teh.create_sprint(name="Test Sprint",
                                           start=self.start, 
                                           end=self.end)
        another_sprint = self.teh.create_sprint(name="Another Sprint",
                                                   start=self.start,
                                                   duration=sprint.duration)
        # Check they have the same end date...
        self.assert_equals(sprint.end.date(), another_sprint.end.date())
        # Now, save and load and check that the data are set correctly
        # FIXME: where is the check mentioned in the above comment?
        # Now change the end and see if the duration change as well
        another_sprint.end = another_sprint.end + timedelta(days=1)
        self.assert_true(another_sprint.duration > sprint.duration)

    def testSprintSelect(self):
        """Test the Sprint select function"""
        self.manager.create(name="Test Sprint 1",
                                  start=self.start,
                                  end=self.end)
        self.manager.create(name="Test Sprint 2",
                                  start=self.start,
                                  end=self.end)
        self.manager.create(name="Test Sprint 3",
                                  start=parse_date("2008-06-10"),
                                  end=parse_date("2008-06-30"))
        # Now test the select
        sprints = self.manager.select(criteria={'end': '> %d' % to_timestamp(now())})
        self.assert_equals(len(sprints), 2)
        sprints = self.manager.select()
        self.assert_equals(len(sprints), 3)

    def testDeleteSprint(self):
        """Tests the deletion of a Sprint"""
        sprint1 = self.manager.create(name="Test Sprint 1", 
                                            start=self.start, 
                                            end=self.end)
        self.assert_true(sprint1.exists)
        self.assert_true(self.manager.delete(sprint1))
        # Now make sure is not there anymore
        self.manager.get(name="Test Sprint 1")
    
    def testRenameSprint(self):
        """Tests the Sprint rename"""
        name = 'Test sprint name'
        sprint = self.manager.create(name=name, start=self.start, end=self.end)
        self.assert_true(sprint.exists)
        self.assert_equals(sprint.name, name)
        
        # create a ticket for this sprint
        t = self.teh.create_ticket(Type.USER_STORY, props={Key.SPRINT: name})
        # reload ticket
        self.assert_equals(t[Key.SPRINT], name)
        # create a metrics object
        team = self.teh.create_team(name='Testteam')
        metrics = TeamMetrics(self.env, sprint, team)
        metrics['test'] = 1.0
        metrics.save()

        # Rename the sprint
        new_name = 'New sprint name'
        sprint.name = new_name
        self.assert_true(self.manager.save(sprint))
        self.assert_equals(sprint.name, new_name)
        # Remove the sprint from the cache and reload it again
        self.manager.get_cache().invalidate(model_instance=sprint)
        # check new name after reload
        sprint = self.manager.get(name=new_name)
        self.assert_equals(sprint.name, new_name)

        t = self.teh.load_ticket(t_id=t.id)
        # sprint in ticket and metrics should be renamed as well
        self.assert_equals(t[Key.SPRINT], new_name)
        metrics = TeamMetrics(self.env, sprint, team)
        self.assert_equals(metrics.sprint, sprint)
        self.assert_equals(metrics['test'], 1.0)
        
        # Rename the sprint with some not allowed characters
        new_name = "That's my sprint!"
        sprint.name = new_name
        self.assert_true(sprint.save())
        self.assert_equals(sprint.name, new_name)

        # check new name after reload
        sprint = Sprint(self.env, name=new_name)
        self.assert_equals(sprint.name, new_name)

    def testAssignTeamToSprint(self):
        """Tests the assignment of a team to a Sprint"""
        team = self.teh.create_team(name="The Team")
        self.teh.create_member(name="Team Member 1", team=team)
        self.teh.create_member(name="Team Member 2", team=team)
        # Now create a Sprint
        s = self.manager.create(name="Test S", team=team)
        
        self.assert_equals(team.name, s.team.name)
        for i, member in enumerate(team.members):
            self.assert_equals(member.name, s.team.members[i].name)
    
    def testSprintClosedAndIsCurrentlyRunning(self):
        """Tests the is_closed and is_started"""
        start = now() - timedelta(days=3) # no risk to get a weekend
        s = self.teh.create_sprint("Test", start=start)
        self.assert_true(s.is_currently_running)
        self.assert_false(s.is_closed)
        s.start += timedelta(days=5) # Move 5 to make sure that we will overcome also a normalization over a weekend
        self.assert_false(s.is_currently_running, "%s <= %s  < %s" % \
                         (s.start, start, s.end))
        self.assert_false(s.is_closed)
        
        # check functions for an old, closed sprint
        s.start = parse_date("2008-01-01")
        s.end = parse_date("2008-01-31")
        self.assert_false(s.is_currently_running)
        self.assert_true(s.is_closed)
    
    def testSprintIsNotCurrentlyRunningAfterSprintEnd(self):
        today = now()
        sprint_start = today - timedelta(days=20)
        sprint = self.teh.create_sprint("Test", start=sprint_start)
        sprint.end = today - timedelta(days=10)
        # Sprint ended ten days before today
        self.assert_false(sprint.is_currently_running)
        self.assert_true(sprint.is_closed)
    
    def testLoadSprintWhichHasNoStartDate(self):
        self.manager.create(name='foo')
        sprint = self.manager.get(name='foo')
        self.assert_true(sprint.exists)
        self.assert_equals('foo', sprint.name)
    
    def testCanDisableSprintStartDateNormalization(self):
        config = AgiloConfig(self.env).get_section(AgiloConfig.AGILO_GENERAL)
        option_name = 'sprints_can_start_or_end_on_weekends'
        self.assert_false(config.get_bool(option_name))
        config.change_option(option_name, True, save=True)
        self.assert_true(AgiloConfig(self.env).sprints_can_start_or_end_on_weekends)
        
        start = datetime(2009, 05, 30, tzinfo=utc)
        sprint = self.teh.create_sprint('Foo', start=start)
        self.assert_equals(start, sprint.start)
        self.assert_equals(utc, sprint.start.tzinfo)
    
    def testManagerAttributeIsNotSerialized(self):
        sprint = self.teh.create_sprint('Foo Sprint')
        sprint_dict = sprint.as_dict()
        self.assert_false('manager' in sprint_dict)
    
    def test_can_build_resource(self):
        sprint = self.teh.create_sprint('Foo Sprint')
        self.assert_equals(Resource(Realm.SPRINT, sprint.name), sprint.resource())
    
    def test_can_build_by_duration_without_normalization(self):
        self.teh.disable_sprint_date_normalization()
        some_friday = datetime(day=30, month=4, year=2010)
        self.assert_equals(4, some_friday.weekday())
        
        sprint = self.teh.create_sprint('Foo Sprint', start=some_friday, duration=4)
        sprint_length = (sprint.end - sprint.start).days
        self.assert_equals(3, sprint_length)
コード例 #16
0
 def __init__(self):
     self.sp_manager = SprintModelManager(self.env)
     self.c_manager = ContingentModelManager(self.env)
コード例 #17
0
 def __init__(self, env, **kwargs):
     from agilo.scrum.sprint import SprintModelManager
     template_filename = 'scrum/metrics/templates/agilo_metrics_chart.html'
     self._define_chart_resources(env, template_filename, kwargs)
     super(MetricsChartWidget, self).__init__(env, template_filename, **kwargs)
     self.sp_manager = SprintModelManager(env)
コード例 #18
0
 def _sprint(self, sprint_name):
     return SprintModelManager(self.env).get(name=sprint_name)