示例#1
0
    def test_calc_letter(self):
        """
        Test calculated letter functionality
        """
        s, c = create_offering()
        na = NumericActivity(name="Assignment 1",
                             short_name="A1",
                             status="RLS",
                             offering=c,
                             position=2,
                             max_grade=15,
                             percent=10,
                             group=False)
        na.save()

        a = CalLetterActivity(offering=c,
                              name="A1 Letter",
                              short_name="A1L",
                              status="RLS",
                              numeric_activity=na,
                              exam_activity=None,
                              position=3)
        a.save()

        # test cutoff getter/setter
        cs = a.get_cutoffs()
        cs[1] = decimal.Decimal('271') / decimal.Decimal('3')
        a.set_cutoffs(cs)
        s.save()
        cs = a.get_cutoffs()
        self.assertAlmostEqual(float(cs[1]), 90.333333333333)
示例#2
0
    def test_add_activity_components(self):
        
        c = CourseOffering.objects.get(slug = self.c_slug)
       
        #add a numeric activity and its components
        a = NumericActivity(offering = c, name = 'test_assignment_1', \
                            short_name = 'ta1', status = 'RLS', \
                            due_date = datetime.now(), max_grade = 100, position = 0)
        a.save()
      
        co1 = ActivityComponent(numeric_activity = a, title = 'part1', max_mark = 20, position = 1)
        co2 = ActivityComponent(numeric_activity = a, title = 'part2', max_mark = 30, position = 2)
        co3 = ActivityComponent(numeric_activity = a, title = 'part3', max_mark = 50, position = 3)
        
        co1.save()
        co2.save()
        co3.save()
        
        self.client.login_user('ggbaker')

        response = basic_page_tests(self, self.client, reverse('offering:marking:manage_activity_components', args=(self.c_slug,a.slug)))
          
        forms = response.context['formset'].forms
        self.assertEqual(forms[0].instance.title, 'part1')
        self.assertEqual(forms[1].instance.title, 'part2')
        self.assertEqual(forms[2].instance.title, 'part3') 
示例#3
0
 def test_group_setMark(self):
     c = CourseOffering.objects.get(slug = self.c_slug)
    
     #add a numeric activity
     a = NumericActivity(offering = c, name = 'test_assignment_1', \
                         short_name = 'ta1', status = 'RLS', \
                         due_date = datetime.now(), max_grade = 100, position = 0)
     a.save()
     
     #take 2 students to make a group       
     stud1 = Member.objects.get(person = Person.objects.get(userid = '0aaa0'), offering = c)
     stud2 = Member.objects.get(person = Person.objects.get(userid = '0aaa1'), offering = c)
             
     group = Group.objects.create(courseoffering = c, name = 'hello', manager = stud1)
     member1 = GroupMember.objects.create(group = group, student = stud1, confirmed = True, activity=a)
     member2 = GroupMember.objects.create(group = group, student = stud2, confirmed = True, activity=a)
     
     MARK = 30
     group_mark = GroupActivityMark(group = group, numeric_activity = a)
     group_mark.setMark(MARK, entered_by='ggbaker')
     group_mark.save()
     
     num_grades = NumericGrade.objects.filter(activity = a).order_by('member__person__userid')
     self.assertEqual(len(num_grades), 2)
     self.assertEqual(num_grades[0].member, stud1)        
     self.assertEqual(num_grades[0].value, MARK)     
     self.assertEqual(num_grades[0].flag, 'GRAD')
     self.assertEqual(num_grades[1].member, stud2) 
     self.assertEqual(num_grades[1].value, MARK) 
     self.assertEqual(num_grades[1].flag, 'GRAD')
示例#4
0
    def test_out_of_zero(self):
        """
        Test activities out of zero
        """
        c = CourseOffering.objects.get(slug=self.course_slug)
        a = NumericActivity(offering=c, name="AZero", short_name="AZ", status="RLS", group=False, deleted=False, max_grade=0, position=1)
        a.save()
        stud = c.member_set.filter(role="STUD")[0]
        
        # test as instructor
        client = Client()
        client.login_user("ggbaker")
        
        url = reverse('offering:change_grade_status', kwargs={'course_slug': c.slug, 'activity_slug': a.slug, 'userid': stud.person.userid})
        response = basic_page_tests(self, client, url)
        self.assertContains(response, "out of 0")

        response = client.post(url, {'grade-status-value': 3, 'grade-status-flag': 'GRAD', 'grade-status-comment': ''})
        self.assertEqual(response.status_code, 302)
        g = NumericGrade.objects.get(activity=a, member=stud)
        self.assertEqual(g.value, 3)
        
        url = reverse('offering:activity_info', kwargs={'course_slug': c.slug, 'activity_slug': a.slug})
        response = basic_page_tests(self, client, url)
        url = reverse('offering:student_info', kwargs={'course_slug': c.slug, 'userid': stud.person.userid})
        response = basic_page_tests(self, client, url)

        # test as student
        client.login_user(stud.person.userid)

        url = reverse('offering:course_info', kwargs={'course_slug': c.slug})
        response = basic_page_tests(self, client, url)
        url = reverse('offering:activity_info', kwargs={'course_slug': c.slug, 'activity_slug': a.slug})
        response = basic_page_tests(self, client, url)
示例#5
0
    def test_out_of_zero(self):
        """
        Test activities out of zero
        """
        c = CourseOffering.objects.get(slug=self.course_slug)
        a = NumericActivity(offering=c, name="AZero", short_name="AZ", status="RLS", group=False, deleted=False, max_grade=0, position=1)
        a.save()
        stud = c.member_set.filter(role="STUD")[0]
        
        # test as instructor
        client = Client()
        client.login_user("ggbaker")
        
        url = reverse('marking.views.change_grade_status', kwargs={'course_slug': c.slug, 'activity_slug': a.slug, 'userid': stud.person.userid})
        response = basic_page_tests(self, client, url)
        self.assertContains(response, "out of 0")

        response = client.post(url, {'grade-status-value': 3, 'grade-status-flag': 'GRAD', 'grade-status-comment': ''})
        self.assertEquals(response.status_code, 302)
        g = NumericGrade.objects.get(activity=a, member=stud)
        self.assertEquals(g.value, 3)
        
        url = reverse('grades.views.activity_info', kwargs={'course_slug': c.slug, 'activity_slug': a.slug})
        response = basic_page_tests(self, client, url)
        url = reverse('grades.views.student_info', kwargs={'course_slug': c.slug, 'userid': stud.person.userid})
        response = basic_page_tests(self, client, url)

        # test as student
        client.login_user(stud.person.userid)

        url = reverse('grades.views.course_info', kwargs={'course_slug': c.slug})
        response = basic_page_tests(self, client, url)
        url = reverse('grades.views.activity_info', kwargs={'course_slug': c.slug, 'activity_slug': a.slug})
        response = basic_page_tests(self, client, url)
示例#6
0
 def setUp(self):
     self.c_slug = TEST_COURSE_SLUG
     self.client = Client()
     self.c = CourseOffering.objects.get(slug = self.c_slug)
     self.a1 = NumericActivity(offering = self.c, name = 'test_assignment_1', 
                         short_name = 'ta1', status = 'RLS', 
                         due_date = datetime.now(), max_grade = 100,
                         position = 0)
     self.a1.save()
示例#7
0
class TestImportViews(TestCase):
    fixtures = ['basedata', 'coredata', 'grades']

    def setUp(self):
        self.c_slug = TEST_COURSE_SLUG
        self.client = Client()
        self.c = CourseOffering.objects.get(slug=self.c_slug)
        self.a1 = NumericActivity(offering=self.c,
                                  name='test_assignment_1',
                                  short_name='ta1',
                                  status='RLS',
                                  due_date=datetime.now(),
                                  max_grade=100,
                                  position=0)
        self.a1.save()

    def check_student_db_grade(self, grade, s, g):
        self.assertEqual(grade.member, s)
        self.assertEqual(grade.value, Decimal(g))
        self.assertEqual(grade.flag, 'GRAD')

    def test_import_view(self):
        self.client.login_user('ggbaker')

        # Import the file, check that resulting HTML has correct entries in fields for two affected students
        url = reverse('offering:mark_all_students',
                      kwargs={
                          'course_slug': self.c_slug,
                          'activity_slug': self.a1.slug
                      })
        with open('marking/testfiles/newformat_noprob_userid.csv') as file:
            post_data = {'import-file-file': [file]}
            response = self.client.post(url + "?import=true",
                                        post_data,
                                        follow=True)
        self.assertEqual(response.status_code, 200)
        stud1 = Member.objects.get(person=Person.objects.get(userid='0aaa0'),
                                   offering=self.c)
        stud2 = Member.objects.get(person=Person.objects.get(userid='0aaa1'),
                                   offering=self.c)
        STUD1_GRADE = '88'
        STUD2_GRADE = '15'
        self.assertContains(response,
                            b'value="%b"' % (STUD1_GRADE.encode('utf8'), ))
        self.assertContains(response,
                            b'value="%b"' % (STUD2_GRADE.encode('utf8'), ))

        # Submit the grades, check that they were added to DB
        post_data = {'0aaa0-value': STUD1_GRADE, '0aaa1-value': STUD2_GRADE}
        response = self.client.post(url, post_data, follow=True)
        self.assertEqual(response.status_code, 200)
        num_grades = NumericGrade.objects.filter(
            activity=self.a1).order_by('member__person__userid')
        self.assertEqual(len(num_grades), 2)
        self.check_student_db_grade(num_grades[0], stud1, STUD1_GRADE)
        self.check_student_db_grade(num_grades[1], stud2, STUD2_GRADE)
示例#8
0
 def setUp(self):
     self.c_slug = TEST_COURSE_SLUG
     self.client = Client()
     self.c = CourseOffering.objects.get(slug = self.c_slug)
     self.a1 = NumericActivity(offering = self.c, name = 'test_assignment_1', 
                         short_name = 'ta1', status = 'RLS', 
                         due_date = datetime.now(), max_grade = 100,
                         position = 0)
     self.a1.save()
     self.students = self.c.members.filter(person__role='STUD')
     self.userids = [p.userid for p in self.students]
     self.emplids = [p.emplid for p in self.students]
示例#9
0
    def test_upload(self):
        _, course = create_offering()
        a1 = NumericActivity(name="Assignment 1", short_name="A1", status="RLS", offering=course, position=2, max_grade=15, due_date=datetime.datetime.now() + datetime.timedelta(hours=1), group=False)
        a1.save()
        p = Person.objects.get(userid="ggbaker")
        member = Member(person=p, offering=course, role="INST", career="NONS", added_reason="UNK")
        member.save()
        c = Code.Component(activity=a1, title="Code File", position=3, max_size=2000, allowed=".py")
        c.save()

        userid1 = "0aaa0"
        userid2 = "0aaa1"
        userid3 = "0aaa2"
        for u in [userid1, userid2,userid3]:
            p = Person.objects.get(userid=u)
            m = Member(person=p, offering=course, role="STUD", credits=3, career="UGRD", added_reason="UNK")
            m.save()
        
        # submit as student
        client = Client()
        client.login_user("0aaa0")
        url = reverse('submission.views.show_components', kwargs={'course_slug': course.slug,'activity_slug':a1.slug})
        response = basic_page_tests(self, client, url)

        # submit a file
        tmpf = tempfile.NamedTemporaryFile(suffix=".py", delete=False)
        codecontents = 'print "Hello World!"\n'
        tmpf.write(codecontents)
        tmpf.close()

        try:
            fh = open(tmpf.name, "r")
            data = {"%i-code" % (c.id): fh}
            response = client.post(url, data)
            self.assertEquals(response.status_code, 302)
            
        finally:
            os.unlink(tmpf.name)

        # make sure it's there and correct
        subs = StudentSubmission.objects.all()
        self.assertEquals(len(subs), 1)
        sub = subs[0]
        self.assertEquals(sub.member.person.userid, '0aaa0')
            
        codes = SubmittedCode.objects.all()
        self.assertEquals(len(codes), 1)
        code = codes[0]
        code.code.open()
        self.assertEquals(code.code.read(), codecontents)
示例#10
0
    def test_add_common_problems(self):
        c = CourseOffering.objects.get(slug = self.c_slug)
        a = NumericActivity(offering = c, name = 'test_assignment_1', \
                            short_name = 'ta1', status = 'RLS', \
                            due_date = datetime.now(), max_grade = 100, position = 1)
        a.save()        
        co1 = ActivityComponent(numeric_activity = a, title = 'part1', max_mark = 50, position = 1)
        co2 = ActivityComponent(numeric_activity = a, title = 'part2', max_mark = 50, position = 2) 
        co1.save()
        co2.save()
        
        #add some common problems
        cp1 = CommonProblem(activity_component = co1, title = 'cp1', penalty="0")
        cp2 = CommonProblem(activity_component = co1, title = 'cp2', penalty="1.12")        
        cp3 = CommonProblem(activity_component = co2, title = 'cp3', penalty="-2.3")
        
        cp1.save()
        cp2.save()
        cp3.save()
        
        self.client.login_user('ggbaker')        

        response = basic_page_tests(self, self.client, reverse('offering:marking:manage_common_problems', args=(self.c_slug,a.slug)))
        
        forms = response.context['formset'].forms
 
        ins0 = forms[0].instance
        ins1 = forms[1].instance
        ins2 = forms[2].instance
        
        self.assertEqual(ins0.title, 'cp1')
        self.assertEqual(ins0.activity_component, co1)
        self.assertEqual(ins1.title, 'cp2')
        self.assertEqual(ins1.activity_component, co1)
        self.assertEqual(ins2.title, 'cp3')
        self.assertEqual(ins2.activity_component, co2)
        
        #test the marking page as well        
        url = reverse('offering:marking:marking_student', args=(self.c_slug, a.slug, '0aaa0'))
        response = basic_page_tests(self, self.client, url)
        
        mark_components = response.context['component_data']
        com1 = mark_components[0]
        com2 = mark_components[1]
        
        self.assertEqual(com1['component'], co1)
        self.assertEqual(len(com1['common_problems']), 2)
        self.assertEqual(com2['component'], co2)
        self.assertEqual(len(com2['common_problems']), 1)
示例#11
0
    def test_post_activity_components(self):
        c = CourseOffering.objects.get(slug = self.c_slug)
       
        #add a numeric activity and its components
        a = NumericActivity(offering = c, name = 'test_assignment_1', \
                            short_name = 'ta1', status = 'RLS', \
                            due_date = datetime.now(), max_grade = 100, position = 0)
        a.save()
                                    
        self.client.login_user('ggbaker')

        url = reverse('offering:marking:manage_activity_components', args=(self.c_slug, a.slug))

        # 2 forms for the first 2 components to add
        post_data = {'form-0-id' : ['', ''], 'form-1-id' : ['', ''],
                     'form-0-title': ['part1'], 'form-1-title': ['part2'], 
                     'form-0-max_mark' : ['20'], 'form-1-max_mark': ['20'],                    
                     'form-0-description' : ['basic1'], 'form-1-description': ['basic2'],
                     'form-TOTAL_FORMS' : ['3'], 'form-INITIAL_FORMS':['0']}
        
        response = self.client.post(url, post_data, follow = True)
        self.assertEqual(response.status_code, 200)
        
        cps = ActivityComponent.objects.filter(numeric_activity = a, deleted = False)
        self.assertEqual(len(cps), 2)
        self.assertEqual(cps[0].title, 'part1')        
        self.assertEqual(cps[1].title, 'part2')
        
        # keep the first 2 components, and add 2 more new components
        post_data2 = {'form-2-id' : ['', ''], 'form-3-id' : ['', ''],
                     'form-2-title': ['part3'], 'form-3-title': ['part4'], 
                     'form-2-max_mark' : ['30'], 'form-3-max_mark': ['30'],                    
                     'form-2-description' : ['advanced1'], 'form-3-description': ['advanced2'],
                     }
        post_data.update(post_data2)
       
        post_data['form-0-id'] = [str(cps[0].id), str(cps[0].id)]
        post_data['form-1-id'] = [str(cps[1].id), str(cps[1].id)]        
        post_data['form-INITIAL_FORMS'] = ['2']
        
        post_data['form-TOTAL_FORMS'] = ['5']
                
        response = self.client.post(url, post_data, follow = True)
        self.assertEqual(response.status_code, 200)
        cps = ActivityComponent.objects.filter(numeric_activity = a, deleted = False)
        self.assertEqual(len(cps), 4)
        self.assertEqual(cps[2].title, 'part3')        
        self.assertEqual(cps[3].title, 'part4')
示例#12
0
    def test_mark_history(self):
        c = CourseOffering.objects.get(slug = self.c_slug)
       
        #add a numeric activity
        a = NumericActivity(offering = c, name = 'test_assignment_1', \
                            short_name = 'ta1', status = 'RLS', \
                            due_date = datetime.now(), max_grade = 100, position = 0)
        a.save()
        
        #take 2 students to make a group       
        stud1 = Member.objects.get(person = Person.objects.get(userid = '0aaa0'), offering = c)
        stud2 = Member.objects.get(person = Person.objects.get(userid = '0aaa1'), offering = c)
                
        group = Group.objects.create(courseoffering = c, name = 'hello', manager = stud1)
        member1 = GroupMember.objects.create(group = group, student = stud1, confirmed = True, activity=a)
        member2 = GroupMember.objects.create(group = group, student = stud2, confirmed = True, activity=a)
        
        ngrade = NumericGrade(activity = a, member = stud2)                  
        ngrade.save(entered_by='ggbaker')
        
                 
        #assign mark to 0aaa1 individually twice and via the group twice, make some interval between saves     
        std_mark = StudentActivityMark(numeric_grade = ngrade, created_by = 'ggbaker')           
        std_mark.setMark(20, entered_by='ggbaker')
        std_mark.save()  
               
        group_mark = GroupActivityMark(group = group, numeric_activity = a, created_by = 'ggbaker')  
        group_mark.setMark(30, entered_by='ggbaker')
        group_mark.save()
        
        std_mark = StudentActivityMark(numeric_grade = ngrade, created_by = 'ggbaker')
        std_mark.setMark(40, entered_by='ggbaker')
        std_mark.save()   
        
        group_mark = GroupActivityMark(group = group, numeric_activity = a,  created_by = 'ggbaker')
        group_mark.setMark(50, entered_by='ggbaker')
        group_mark.save()
        
        self.client.login_user('ggbaker')

        response = self.client.get(reverse('offering:marking:mark_history_student', args=(self.c_slug, a.slug, '0aaa1')))
        self.assertEqual(response.status_code, 200)
        
        latest_act_mark = response.context['current_mark']
        self.assertEqual(len(response.context['marks_individual']), 2)
        self.assertEqual(len(response.context['marks_via_group']), 2)
        self.assertEqual(group_mark, latest_act_mark)
示例#13
0
 def test_activity_status(self):
     """
     Test operations on activity's status
     """
     # check the get_status_display override
     now = datetime.datetime.now()
     a = NumericActivity(name="Assign 1", short_name="A1", status="INVI", max_grade=10)
     self.assertEquals(a.get_status_display(), ACTIVITY_STATUS["INVI"])
     a.status="RLS"
     self.assertEquals(a.get_status_display(), ACTIVITY_STATUS["RLS"])
     a.status="URLS"
     self.assertEquals(a.get_status_display(), ACTIVITY_STATUS["URLS"])
     a.due_date = now - datetime.timedelta(hours=1)
     self.assertEquals(a.get_status_display(), ACTIVITY_STATUS["URLS"])
     # the special case: unreleased, before the due date
     a.due_date = now + datetime.timedelta(hours=1)
     self.assertEquals(a.get_status_display(), "no grades: due date not passed")
示例#14
0
 def test_calc_letter(self):
     """
     Test calculated letter functionality
     """
     s, c = create_offering()
     na = NumericActivity(name="Assignment 1", short_name="A1", status="RLS", offering=c, position=2, max_grade=15, percent=10, group=False)
     na.save()
     
     a = CalLetterActivity(offering=c, name="A1 Letter", short_name="A1L", status="RLS", numeric_activity=na, exam_activity=None, position=3)
     a.save()
     
     # test cutoff getter/setter
     cs = a.get_cutoffs()
     cs[1] = decimal.Decimal('271') / decimal.Decimal('3')
     a.set_cutoffs(cs)
     s.save()
     cs = a.get_cutoffs()
     self.assertAlmostEquals(float(cs[1]), 90.333333333333)
示例#15
0
文件: tests.py 项目: sfu-fas/coursys
class TestImportViews(TestCase):
    fixtures = ['basedata', 'coredata', 'grades']

    def setUp(self):
        self.c_slug = TEST_COURSE_SLUG
        self.client = Client()
        self.c = CourseOffering.objects.get(slug = self.c_slug)
        self.a1 = NumericActivity(offering = self.c, name = 'test_assignment_1', 
                            short_name = 'ta1', status = 'RLS', 
                            due_date = datetime.now(), max_grade = 100,
                            position = 0)
        self.a1.save()

    def check_student_db_grade(self, grade, s, g):
        self.assertEqual(grade.member, s)
        self.assertEqual(grade.value, Decimal(g))
        self.assertEqual(grade.flag, 'GRAD')

    def test_import_view(self):
        self.client.login_user('ggbaker')

        # Import the file, check that resulting HTML has correct entries in fields for two affected students
        url = reverse('offering:mark_all_students', kwargs={'course_slug':self.c_slug, 'activity_slug':self.a1.slug})
        with open('marking/testfiles/newformat_noprob_userid.csv') as file:
            post_data = {'import-file-file':[file]}
            response = self.client.post(url+"?import=true", post_data, follow=True)
        self.assertEqual(response.status_code, 200)
        stud1 = Member.objects.get(person = Person.objects.get(userid = '0aaa0'), offering = self.c)
        stud2 = Member.objects.get(person = Person.objects.get(userid = '0aaa1'), offering = self.c)
        STUD1_GRADE = '88'
        STUD2_GRADE = '15'
        self.assertContains(response, b'value="%b"' % (STUD1_GRADE.encode('utf8'),))
        self.assertContains(response, b'value="%b"' % (STUD2_GRADE.encode('utf8'),))

        # Submit the grades, check that they were added to DB
        post_data={'0aaa0-value':STUD1_GRADE, '0aaa1-value':STUD2_GRADE}
        response = self.client.post(url, post_data, follow=True)
        self.assertEqual(response.status_code, 200)
        num_grades = NumericGrade.objects.filter(activity = self.a1).order_by('member__person__userid')
        self.assertEqual(len(num_grades), 2)
        self.check_student_db_grade(num_grades[0], stud1, STUD1_GRADE)
        self.check_student_db_grade(num_grades[1], stud2, STUD2_GRADE)
示例#16
0
    def test_select_components(self):
        """
        Test submission component classes: subclasses, selection, sorting.
        """
        _, course = create_offering()
        a1 = NumericActivity(name="Assignment 1", short_name="A1", status="RLS", offering=course, position=2, max_grade=15, due_date="2010-04-01")
        a1.save()
        a2 = NumericActivity(name="Assignment 2", short_name="A2", status="RLS", offering=course, position=1, max_grade=15, due_date="2010-03-01")
        a2.save()

        p = Person.objects.get(userid="ggbaker")
        member = Member(person=p, offering=course, role="INST", career="NONS", added_reason="UNK")
        member.save()

        c1 = URL.Component(activity=a1, title="URL Link", position=8)
        c1.save()
        c2 = Archive.Component(activity=a1, title="Archive File", position=1, max_size=100000)
        c2.save()
        c3 = Code.Component(activity=a1, title="Code File", position=3, max_size=2000, allowed=".py")
        c3.save()
        comps = select_all_components(a1)
        self.assertEqual(len(comps), 3)
        self.assertEqual(comps[0].title, 'Archive File') # make sure position=1 is first
        self.assertEqual(str(comps[1].Type), "submission.models.code.Code")
        self.assertEqual(str(comps[2].Type), "submission.models.url.URL")
示例#17
0
    def test_select_components(self):
        """
        Test submission component classes: subclasses, selection, sorting.
        """
        _, course = create_offering()
        a1 = NumericActivity(name="Assignment 1",
                             short_name="A1",
                             status="RLS",
                             offering=course,
                             position=2,
                             max_grade=15,
                             due_date="2010-04-01")
        a1.save()
        a2 = NumericActivity(name="Assignment 2",
                             short_name="A2",
                             status="RLS",
                             offering=course,
                             position=1,
                             max_grade=15,
                             due_date="2010-03-01")
        a2.save()

        p = Person.objects.get(userid="ggbaker")
        member = Member(person=p,
                        offering=course,
                        role="INST",
                        career="NONS",
                        added_reason="UNK")
        member.save()

        c1 = URL.Component(activity=a1, title="URL Link", position=8)
        c1.save()
        c2 = Archive.Component(activity=a1,
                               title="Archive File",
                               position=1,
                               max_size=100000)
        c2.save()
        c3 = Code.Component(activity=a1,
                            title="Code File",
                            position=3,
                            max_size=2000,
                            allowed=".py")
        c3.save()
        comps = select_all_components(a1)
        self.assertEqual(len(comps), 3)
        self.assertEqual(comps[0].title,
                         'Archive File')  # make sure position=1 is first
        self.assertEqual(str(comps[1].Type), "submission.models.code.Code")
        self.assertEqual(str(comps[2].Type), "submission.models.url.URL")
示例#18
0
    def test_activity_pages(self):
        """
        Test pages around activities
        """
        s, c = create_offering()

        # add some assignments and members
        a = NumericActivity(name="Assignment 1", short_name="A1", status="RLS", offering=c, position=2, max_grade=15, percent=10)
        a.save()
        a1=a
        a = NumericActivity(name="Assignment 2", short_name="A2", status="URLS", offering=c, position=6, max_grade=20, group=True)
        a.save()
        p = Person.objects.get(userid="ggbaker")
        m = Member(person=p, offering=c, role="INST", added_reason="UNK")
        m.save()
        p = Person.objects.get(userid="0aaa0")
        m = Member(person=p, offering=c, role="STUD", added_reason="UNK")
        m.save()
        
        # test instructor pages
        client = Client()
        client.login_user("ggbaker")

        response = basic_page_tests(self, client, '/' + c.slug + '/')
        self.assertContains(response, 'href="' + reverse('offering:groups:groupmanage', kwargs={'course_slug':c.slug}) +'"')

        basic_page_tests(self, client, c.get_absolute_url())
        basic_page_tests(self, client, reverse('offering:student_info', kwargs={'course_slug': c.slug, 'userid': '0aaa0'}))
        basic_page_tests(self, client, reverse('offering:add_numeric_activity', kwargs={'course_slug':c.slug}))
        basic_page_tests(self, client, reverse('offering:add_letter_activity', kwargs={'course_slug':c.slug}))

        # test student pages
        client = Client()
        client.login_user("0aaa0")
        response = basic_page_tests(self, client, '/' + c.slug + '/')
        self.assertContains(response, "Gregorʏ (Greg) Baker")
        self.assertContains(response, 'href="' + reverse('offering:groups:groupmanage', kwargs={'course_slug':c.slug}) +'"')

        response = basic_page_tests(self, client, a.get_absolute_url())
        # small class (one student) shouldn't contain summary stats
        self.assertNotContains(response, "Histogram")
        self.assertNotContains(response, "Standard Deviation")
示例#19
0
    def test_group_submission_view(self):
        """
        test if group submission can be viewed by group member and non group member
        """
        now = datetime.datetime.now()
        _, course = create_offering()
        a1 = NumericActivity(name="Assignment 1", short_name="A1", status="RLS", offering=course, position=2, max_grade=15, due_date=now, group=True)
        a1.save()
        a2 = NumericActivity(name="Assignment 2", short_name="A2", status="RLS", offering=course, position=1, max_grade=15, due_date=now, group=True)
        a2.save()
        p = Person.objects.get(userid="ggbaker")
        member = Member(person=p, offering=course, role="INST", career="NONS", added_reason="UNK")
        member.save()
        c1 = URL.Component(activity=a1, title="URL Link", position=8)
        c1.save()
        c2 = Archive.Component(activity=a1, title="Archive File", position=1, max_size=100000)
        c2.save()
        c3 = Code.Component(activity=a1, title="Code File", position=3, max_size=2000, allowed=".py")
        c3.save()

        userid1 = "0aaa0"
        userid2 = "0aaa1"
        userid3 = "0aaa2"
        for u in [userid1, userid2,userid3]:
            p = Person.objects.get(userid=u)
            m = Member(person=p, offering=course, role="STUD", credits=3, career="UGRD", added_reason="UNK")
            m.save()
        m = Member.objects.get(person__userid=userid1, offering=course)
        g = Group(name="Test Group", manager=m, courseoffering=course)
        g.save()
        gm = GroupMember(group=g, student=m, confirmed=True, activity=a1)
        gm.save()
        gm = GroupMember(group=g, student=m, confirmed=True, activity=a2)
        gm.save()
        m = Member.objects.get(person__userid=userid2, offering=course)
        gm = GroupMember(group=g, student=m, confirmed=True, activity=a1)
        gm.save()
        gm = GroupMember(group=g, student=m, confirmed=True, activity=a2)
        gm.save()
        m = Member.objects.get(person__userid=userid3, offering=course)
        gm = GroupMember(group=g, student=m, confirmed=True, activity=a2)
        gm.save()

        client = Client()
        # login as "0aaa0", member of group : test_group for assignment1 and assgnment2
        client.login_user("0aaa0")

        #submission page for assignment 1
        url = reverse('submission.views.show_components', kwargs={'course_slug': course.slug,'activity_slug':a1.slug})
        response = basic_page_tests(self, client, url)
        self.assertContains(response, "This is a group submission. You will submit on behalf of the group Test Group.")
        self.assertContains(response, "You haven't made a submission for this component.")
示例#20
0
    def test_activity_pages(self):
        """
        Test pages around activities
        """
        s, c = create_offering()

        # add some assignments and members
        a = NumericActivity(name="Assignment 1", short_name="A1", status="RLS", offering=c, position=2, max_grade=15, percent=10)
        a.save()
        a1=a
        a = NumericActivity(name="Assignment 2", short_name="A2", status="URLS", offering=c, position=6, max_grade=20, group=True)
        a.save()
        p = Person.objects.get(userid="ggbaker")
        m = Member(person=p, offering=c, role="INST", added_reason="UNK")
        m.save()
        p = Person.objects.get(userid="0aaa0")
        m = Member(person=p, offering=c, role="STUD", added_reason="UNK")
        m.save()
        
        # test instructor pages
        client = Client()
        client.login_user("ggbaker")

        response = basic_page_tests(self, client, '/' + c.slug + '/')
        self.assertContains(response, 'href="' + reverse('groups.views.groupmanage', kwargs={'course_slug':c.slug}) +'"')

        basic_page_tests(self, client, c.get_absolute_url())
        basic_page_tests(self, client, reverse('grades.views.student_info', kwargs={'course_slug': c.slug, 'userid': '0aaa0'}))
        basic_page_tests(self, client, reverse('grades.views.add_numeric_activity', kwargs={'course_slug':c.slug}))
        basic_page_tests(self, client, reverse('grades.views.add_letter_activity', kwargs={'course_slug':c.slug}))

        # test student pages
        client = Client()
        client.login_user("0aaa0")
        response = basic_page_tests(self, client, '/' + c.slug + '/')
        self.assertContains(response, "Gregory Baker")
        self.assertContains(response, 'href="' + reverse('groups.views.groupmanage', kwargs={'course_slug':c.slug}) +'"')

        response = basic_page_tests(self, client, a.get_absolute_url())
        # small class (one student) shouldn't contain summary stats
        self.assertNotContains(response, "Histogram")
        self.assertNotContains(response, "Standard Deviation")
示例#21
0
    def test_component_view_page(self):
        _, course = create_offering()
        a1 = NumericActivity(name="Assignment 1", short_name="A1", status="RLS", offering=course, position=2, max_grade=15, due_date="2010-04-01")
        a1.save()
        a2 = NumericActivity(name="Assignment 2", short_name="A2", status="RLS", offering=course, position=1, max_grade=15, due_date="2010-03-01")
        a2.save()

        p = Person.objects.get(userid="ggbaker")
        member = Member(person=p, offering=course, role="INST", career="NONS", added_reason="UNK")
        member.save()

        c1 = URL.Component(activity=a1, title="URL Link", position=8)
        c1.save()
        c2 = Archive.Component(activity=a1, title="Archive File", position=1, max_size=100000)
        c2.save()
        c3 = Code.Component(activity=a1, title="Code File", position=3, max_size=2000, allowed=".py")
        c3.save()
        client = Client()
        client.login_user("ggbaker")
        
        # When no component, should display error message
        url = reverse('submission.views.show_components', kwargs={'course_slug':course.slug, 'activity_slug':a2.slug})
        response = basic_page_tests(self, client, url)
        self.assertContains(response, 'No components configured.')
        # add component and test
        component = URL.Component(activity=a2, title="URL2", position=1)
        component.save()
        component = Archive.Component(activity=a2, title="Archive2", position=1, max_size=100)
        component.save()
        # should all appear
        response = basic_page_tests(self, client, url)
        self.assertContains(response, "URL2")
        self.assertContains(response, "Archive2")
        # make sure type displays
        #self.assertContains(response, '<li class="view"><label>Type:</label>Archive</li>')
        # delete component
        self.assertRaises(NotImplementedError, component.delete)
示例#22
0
class TestImportFunctionsNumeric(TestCase):
    fixtures = ['basedata', 'coredata', 'grades']

    def setUp(self):
        self.c_slug = TEST_COURSE_SLUG
        self.client = Client()
        self.c = CourseOffering.objects.get(slug=self.c_slug)
        self.a1 = NumericActivity(offering=self.c,
                                  name='test_assignment_1',
                                  short_name='ta1',
                                  status='RLS',
                                  due_date=datetime.now(),
                                  max_grade=100,
                                  position=0)
        self.a1.save()
        self.students = self.c.members.filter(person__role='STUD')
        self.userids = [p.userid for p in self.students]
        self.emplids = [p.emplid for p in self.students]

    def get_test_file(self, name):
        with open(name, 'r') as inp:
            r = csv.reader(inp)
            self.values = []
            for line in r:
                self.values.append(line)

    def compare_grade_lists(self, data_returned):
        for sname, grade in self.values:
            sname = _strip_email_userid(sname)
            self.assertIn(sname, data_returned.keys())
            self.assertEqual(data_returned[sname], grade)

    def test_import_grades_old_format(self):
        inName = 'marking/testfiles/oldformat_noprob.csv'
        self.get_test_file(inName)
        data_to_return = {}
        with open(inName, 'r') as inp:
            err = _compose_imported_grades(inp, self.students, data_to_return,
                                           self.a1)
        self.assertEqual(err, [])
        self.assertEqual(len(data_to_return), len(self.values))
        self.compare_grade_lists(data_to_return)

    def test_import_grades_old_format_unknown_userid(self):
        inName = 'marking/testfiles/oldformat_unk_uid.csv'
        self.get_test_file(inName)
        bad_id = [n for n, _ in self.values if n not in self.userids][0]
        data_to_return = {}
        with open(inName, 'r') as inp:
            err = _compose_imported_grades(inp, self.students, data_to_return,
                                           self.a1)
        self.assertEqual(err, [
            'Error found in the file (row 2): Unmatched student number '
            'or user-id ({0}).'.format(bad_id)
        ])
        self.assertEqual(len(data_to_return), 2)

    def test_import_grades_old_format_unknown_emplid(self):
        inName = 'marking/testfiles/oldformat_unk_emplid.csv'
        self.get_test_file(inName)
        bad_emplid = [e for e, _ in self.values
                      if int(e) not in self.emplids][0]
        data_to_return = {}
        with open(inName, 'r') as inp:
            err = _compose_imported_grades(inp, self.students, data_to_return,
                                           self.a1)
        self.assertIn(
            'Error found in the file (row 1): Unmatched student number '
            'or user-id ({0}).'.format(bad_emplid), err)
        self.assertEqual(len(data_to_return), 0)

    def test_import_grades_new_format(self):
        inName = 'marking/testfiles/newformat_noprob_userid.csv'
        self.get_test_file(inName)
        del self.values[0]  # Delete header row
        data_to_return = {}
        with open(inName, 'r') as inp:
            err = _compose_imported_grades(inp, self.students, data_to_return,
                                           self.a1)
        self.assertEqual(err, [])
        self.assertEqual(len(data_to_return), len(self.values))
        self.compare_grade_lists(data_to_return)

    def test_import_grades_short_row(self):
        inName = 'marking/testfiles/newformat_shortrow_userid.csv'
        self.get_test_file(inName)
        del self.values[0]  # Delete header row
        data_to_return = {}
        with open(inName, 'r') as inp:
            err = _compose_imported_grades(inp, self.students, data_to_return,
                                           self.a1)
        self.assertEqual(err, [])
        self.assertEqual(len(data_to_return), len(self.values) - 1)

    def test_import_grades_new_format_junk_cols(self):
        inName = 'marking/testfiles/newformat_noprob_junk_cols.csv'
        self.get_test_file(inName)
        del self.values[0]  # Delete header row
        for i, row in enumerate(self.values):
            self.values[i] = [self.values[i][3], self.values[i][1]]
        data_to_return = {}
        with open(inName, 'r') as inp:
            err = _compose_imported_grades(inp, self.students, data_to_return,
                                           self.a1)
        self.assertEqual(err, [])
        self.assertEqual(len(data_to_return), len(self.values))
        self.compare_grade_lists(data_to_return)

    def test_import_grades_new_format_missing_uid_col(self):
        '''
            Judgement call on the design:  If the import file lacks a field
            named 'Userid', we treat it as an old-format file and get an 
            error on the first line.  This unfortunate outcome is required
            if we are to avoid misinterpreting a short assignment name that
            matches a student id and thereby misinterpreting an old-style
            file as though it were a defective (i.e., no 'Userid' column)
            new-style file.
        '''
        inName = 'marking/testfiles/newformat_missing_uid_col.csv'
        data_to_return = {}
        with open(inName, 'r') as inp:
            err = _compose_imported_grades(inp, self.students, data_to_return,
                                           self.a1)
        self.assertIn(
            'Error found in the file (row 1): Unmatched student number or user-id (Junk1).',
            err)
        self.assertIn(
            'Error found in the file (row 2): Unmatched student number or user-id (w1).',
            err)
        self.assertIn(
            'Error found in the file (row 3): Unmatched student number or user-id (w2).',
            err)
        self.assertEqual(len(data_to_return), 0)

    def test_import_grades_new_format_missing_act_col(self):
        inName = 'marking/testfiles/newformat_missing_act_col.csv'
        data_to_return = {}
        with open(inName, 'r') as inp:
            err = _compose_imported_grades(inp, self.students, data_to_return,
                                           self.a1)
        self.assertIn(
            'Error in file header line:  No '
            'column labelled for activity {0}.'.format(self.a1.short_name),
            err)
        self.assertEqual(len(data_to_return), 0)

    def test_import_grades_new_format_dup_act_col(self):
        inName = 'marking/testfiles/newformat_dup_act_col.csv'
        data_to_return = {}
        with open(inName, 'r') as inp:
            err = _compose_imported_grades(inp, self.students, data_to_return,
                                           self.a1)
        self.assertIn(
            'Error in file header line:  Two columns '
            'labelled {0}.'.format(self.a1.short_name), err)
        self.assertEqual(len(data_to_return), 0)

    def test_import_grades_new_format_missing_values(self):
        ''' OK for students to have no grade assigned. '''
        inName = 'marking/testfiles/newformat_missing_student_grade.csv'
        self.get_test_file(inName)
        del self.values[0]  # Delete header row
        for i, row in enumerate(self.values):
            self.values[i] = [self.values[i][6], self.values[i][1]]
        data_to_return = {}
        with open(inName, 'r') as inp:
            err = _compose_imported_grades(inp, self.students, data_to_return,
                                           self.a1)
        self.assertEqual(err, [])
        self.assertEqual(len(data_to_return), len(self.values))
        self.compare_grade_lists(data_to_return)

    def test_import_grades_new_format_bad_utf8(self):
        inName = 'marking/testfiles/newformat_bad_utf8.csv'
        data_to_return = {}
        with open(inName, 'r') as inp:
            err = _compose_imported_grades(inp, self.students, data_to_return,
                                           self.a1)
        self.assertIn(
            'File cannot be decoded as UTF-8 data: make sure it has been saved as UTF-8 text.',
            err)
        self.assertEqual(len(data_to_return), 0)

    def test_import_grades_new_format_utf8_bom(self):
        inName = 'marking/testfiles/newformat_utf8_bom.csv'
        data_to_return = {}
        with open(inName, 'r') as inp:
            err = _compose_imported_grades(inp, self.students, data_to_return,
                                           self.a1)
        self.assertIn(
            'File contains bad UTF-8 data: make sure it has been saved as UTF-8 text.',
            err)
        self.assertEqual(len(data_to_return), 0)
示例#23
0
    def test_frontend(self):
        client = Client()
        client.login_user('ggbaker')

        # set up a course
        c = CourseOffering.objects.get(slug=self.c_slug)
        a1 = NumericActivity(offering = c, name = 'test_assignment_1', \
                            short_name = 'ta1', status = 'RLS', \
                            due_date = datetime.now(), max_grade = 100, position = 0, group=True)
        a1.save()
        a2 = NumericActivity(offering = c, name = 'test_assignment_1', \
                            short_name = 'ta1', status = 'RLS', \
                            due_date = datetime.now(), max_grade = 100, position = 0, group=False)
        a2.save()

        stud1 = Member.objects.get(person=Person.objects.get(userid='0aaa0'),
                                   offering=c)
        stud2 = Member.objects.get(person=Person.objects.get(userid='0aaa1'),
                                   offering=c)
        instr = Member.objects.get(person=Person.objects.get(userid='ggbaker'),
                                   offering=c)
        group = Group.objects.create(courseoffering=c,
                                     name='hello',
                                     manager=stud1)
        member1 = GroupMember.objects.create(group=group,
                                             student=stud1,
                                             confirmed=True,
                                             activity=a1)
        member2 = GroupMember.objects.create(group=group,
                                             student=stud2,
                                             confirmed=True,
                                             activity=a1)

        # marking form (student)
        url = reverse('offering:marking:marking_student',
                      kwargs={
                          'course_slug': c.slug,
                          'activity_slug': a2.slug,
                          'userid': stud1.person.userid
                      })

        response = basic_page_tests(self, client, url)

        ac = ActivityComponent(numeric_activity=a2,
                               max_mark=5,
                               title="AC Title",
                               description="AC Description",
                               position=1,
                               deleted=False)
        ac.save()
        ac = ActivityComponent(numeric_activity=a2,
                               max_mark=5,
                               title="AC Title2",
                               description="AC Description2",
                               position=2,
                               deleted=False)
        ac.save()
        cp = CommonProblem(activity_component=ac,
                           title="CP title",
                           penalty=2,
                           description="Cp description",
                           deleted=False)
        cp.save()

        response = basic_page_tests(self, client, url)

        # submit the form and check that objects were created
        PENALTY = '12.5'  # Percentage
        CMP_1_VALUE = '5.5'
        CMP_2_VALUE = '3'
        ADJ = '1.25'  # Adjustments are subtracted
        TOTAL_MARK = (
            (Decimal(CMP_1_VALUE) + Decimal(CMP_2_VALUE) - Decimal(ADJ)) *
            (1 - (Decimal(PENALTY) / 100))).quantize(Decimal('.01'),
                                                     rounding=ROUND_HALF_EVEN)

        response = client.post(
            url, {
                'cmp-1-value': float(CMP_1_VALUE),
                'cmp-1-comment': 'perfect part 1',
                'cmp-2-value': float(CMP_2_VALUE),
                'cmp-2-comment': 'ok',
                'mark_adjustment': float(ADJ),
                'mark_adjustment_reason': 'reason',
                'late_penalty': float(PENALTY),
                u'overall_comment': 'overall'
            })
        self.assertEquals(response.status_code, 302)
        sam = StudentActivityMark.objects.filter(activity=a2,
                                                 numeric_grade__member=stud1)
        self.assertEquals(len(sam), 1)
        sam = sam[0]
        self.assertEquals(sam.mark_adjustment, Decimal(ADJ))
        self.assertEquals(sam.late_penalty, Decimal(PENALTY))
        self.assertEquals(sam.overall_comment, 'overall')
        self.assertEquals(sam.mark, TOTAL_MARK)
        acms = sam.activitycomponentmark_set.all()
        self.assertEquals(len(acms), 2)
        self.assertEquals(acms[0].value, Decimal(CMP_1_VALUE))
        self.assertEquals(acms[0].comment, 'perfect part 1')
        g = NumericGrade.objects.get(activity=a2, member=stud1)
        self.assertEquals(g.value, TOTAL_MARK)

        # make sure we get old data for "mark based on"
        response = basic_page_tests(self, client,
                                    url + "?base_activity_mark=" + str(sam.id))
        #self.assertContains(response, 'name="cmp-1-value" type="text" value="{0}'.format(CMP_1_VALUE))
        #self.assertContains(response, 'name="late_penalty" type="text" value="{0}'.format(PENALTY))

        # look at the "view details" page
        url = reverse('offering:marking:mark_summary_student',
                      kwargs={
                          'course_slug': c.slug,
                          'activity_slug': a2.slug,
                          'userid': stud1.person.userid
                      })
        response = basic_page_tests(self, client, url)
        self.assertContains(response, 'perfect part 1')

        # marking form (group)
        url = reverse('offering:marking:marking_student',
                      kwargs={
                          'course_slug': c.slug,
                          'activity_slug': a1.slug,
                          'userid': stud1.person.userid
                      })
        response = basic_page_tests(self, client, url)

        ac = ActivityComponent(numeric_activity=a1,
                               max_mark=5,
                               title="AC Title",
                               description="AC Description",
                               position=1,
                               deleted=False)
        ac.save()
        ac = ActivityComponent(numeric_activity=a1,
                               max_mark=5,
                               title="AC Title2",
                               description="AC Description2",
                               position=2,
                               deleted=False)
        ac.save()
        cp = CommonProblem(activity_component=ac,
                           title="CP title",
                           penalty=2,
                           description="Cp description",
                           deleted=False)
        cp.save()

        response = basic_page_tests(self, client, url)

        # common problem form
        url = reverse('offering:marking:manage_common_problems',
                      kwargs={
                          'course_slug': c.slug,
                          'activity_slug': a2.slug
                      })
        response = basic_page_tests(self, client, url)

        # mark all (student and group)
        url = reverse('offering:mark_all_students',
                      kwargs={
                          'course_slug': c.slug,
                          'activity_slug': a2.slug
                      })
        response = basic_page_tests(self, client, url)
        # mark all (student and group)
        url = reverse('offering:mark_all_groups',
                      kwargs={
                          'course_slug': c.slug,
                          'activity_slug': a1.slug
                      })
        response = basic_page_tests(self, client, url)
示例#24
0
 def test_activity_status(self):
     """
     Test operations on activity's status
     """
     # check the get_status_display override
     now = datetime.datetime.now()
     s, c = create_offering()
     a = NumericActivity(offering=c,
                         name="Assign 1",
                         short_name="A1",
                         status="INVI",
                         max_grade=10)
     self.assertEqual(a.get_status_display(), ACTIVITY_STATUS["INVI"])
     a.status = "RLS"
     self.assertEqual(a.get_status_display(), ACTIVITY_STATUS["RLS"])
     a.status = "URLS"
     self.assertEqual(a.get_status_display(), ACTIVITY_STATUS["URLS"])
     a.due_date = now - datetime.timedelta(hours=1)
     self.assertEqual(a.get_status_display(), ACTIVITY_STATUS["URLS"])
     # the special case: unreleased, before the due date
     a.due_date = now + datetime.timedelta(hours=1)
     self.assertEqual(a.get_status_display(),
                      "no grades: due date not passed")
示例#25
0
def test_class_1(slug):
    """
    main test course: 20 students, TA, some assignments
    """
    crs = CourseOffering.objects.get(slug=slug)

    crs.set_labtut(True)
    crs.set_url("http://www.cs.sfu.ca/CC/165/common/")
    crs.set_taemail("*****@*****.**")
    crs.save()
    for i in range(10):
        lab = "D1%02i" % (random.randint(1, 4))
        p = Person.objects.get(userid="0aaa%i" % (i))
        if Member.objects.filter(person=p, offering=crs, role="STUD"):
            # randomly added by other student-adder: skip
            continue

        m = Member(person=p,
                   offering=crs,
                   role="STUD",
                   credits=3,
                   career="UGRD",
                   added_reason="AUTO",
                   labtut_section=lab)
        m.save()

    if not Member.objects.filter(
            person__userid='ggbaker', offering=crs, role='INST'):
        Member(person=Person.objects.get(userid='ggbaker'),
               offering=crs,
               role='INST').save()

    # create a TA
    p = Person(emplid=fake_emplid(),
               userid="0grad1",
               last_name="Gradstudent",
               first_name="Douglas",
               middle_name="",
               pref_first_name="Doug")
    p.save()
    m = Member(person=p,
               offering=crs,
               role="TA",
               credits=0,
               career="NONS",
               added_reason="AUTO",
               labtut_section=None)
    m.save()

    # create example activities
    crs.activity_set.all().update(deleted=True)
    a1 = NumericActivity(offering=crs,
                         name="Assignment 1",
                         short_name="A1",
                         status="RLS",
                         due_date=crs.semester.start +
                         datetime.timedelta(days=60),
                         percent=10,
                         group=False,
                         max_grade=10,
                         position=1)
    a1.set_url("http://www.cs.sfu.ca/CC/165/common/a1")
    a1.save()
    a2 = NumericActivity(offering=crs,
                         name="Assignment 2",
                         short_name="A2",
                         status="URLS",
                         due_date=crs.semester.start +
                         datetime.timedelta(days=70),
                         percent=10,
                         group=True,
                         max_grade=20,
                         position=2)
    a2.save()
    pr = LetterActivity(offering=crs,
                        name="Project",
                        short_name="Proj",
                        status="URLS",
                        due_date=crs.semester.start +
                        datetime.timedelta(days=80),
                        percent=40,
                        group=True,
                        position=3)
    pr.save()
    re = LetterActivity(offering=crs,
                        name="Report",
                        short_name="Rep",
                        status="URLS",
                        due_date=crs.semester.start +
                        datetime.timedelta(days=81),
                        percent=10,
                        group=False,
                        position=4)
    re.save()
    ex = NumericActivity(offering=crs,
                         name="Final Exam",
                         short_name="Exam",
                         status="URLS",
                         due_date=None,
                         percent=30,
                         group=False,
                         max_grade=90,
                         position=5)
    ex.save()
    to = CalNumericActivity(offering=crs,
                            name="Final Percent",
                            short_name="Perc",
                            status="INVI",
                            due_date=None,
                            percent=0,
                            group=False,
                            max_grade=100,
                            formula="[[activitytotal]]",
                            position=6)
    to.save()
    to = CalLetterActivity(offering=crs,
                           name="Letter Grade",
                           short_name="Letter",
                           status="INVI",
                           due_date=None,
                           percent=0,
                           group=False,
                           numeric_activity=to,
                           position=6)
    to.save()

    # make A1 submittable and markable
    s = CodeComponent(activity=a1,
                      title="Code File",
                      description="The code you're submitting.",
                      allowed=".py,.java")
    s.save()
    s = PDFComponent(activity=a1,
                     title="Report",
                     description="Report on what you did.",
                     specified_filename="report.pdf")
    s.save()

    m = ActivityComponent(
        numeric_activity=a1,
        max_mark=5,
        title="Part 1",
        description="Part 1 was done well and seems to work.",
        position=1)
    m.save()
    m = ActivityComponent(
        numeric_activity=a1,
        max_mark=5,
        title="Part 2",
        description="Part 2 was done well and seems to work.",
        position=2)
    m.save()

    # create some groups
    g = Group(name="SomeGroup",
              courseoffering=crs,
              manager=Member.objects.get(offering=crs,
                                         person__userid="0aaa0",
                                         role='STUD'))
    g.save()
    for userid in ['0aaa0', '0aaa1', '0aaa5', '0aaa8']:
        gm = GroupMember(group=g,
                         student=Member.objects.get(offering=crs,
                                                    person__userid=userid),
                         confirmed=True,
                         activity=a2)
        gm.save()

    g = Group(name="AnotherGroup",
              courseoffering=crs,
              manager=Member.objects.get(offering=crs, person__userid="0aaa4"))
    g.save()
    for userid in ['0aaa4', '0aaa6', '0aaa7', '0aaa2']:
        gm = GroupMember(group=g,
                         student=Member.objects.get(offering=crs,
                                                    person__userid=userid),
                         confirmed=True,
                         activity=a2)
        gm.save()
        gm = GroupMember(group=g,
                         student=Member.objects.get(offering=crs,
                                                    person__userid=userid),
                         confirmed=True,
                         activity=pr)
        gm.save()
示例#26
0
    def test_group_submission_view(self):
        """
        test if group submission can be viewed by group member and non group member
        """
        now = datetime.datetime.now()
        _, course = create_offering()
        a1 = NumericActivity(name="Assignment 1",
                             short_name="A1",
                             status="RLS",
                             offering=course,
                             position=2,
                             max_grade=15,
                             due_date=now,
                             group=True)
        a1.save()
        a2 = NumericActivity(name="Assignment 2",
                             short_name="A2",
                             status="RLS",
                             offering=course,
                             position=1,
                             max_grade=15,
                             due_date=now,
                             group=True)
        a2.save()
        p = Person.objects.get(userid="ggbaker")
        member = Member(person=p,
                        offering=course,
                        role="INST",
                        career="NONS",
                        added_reason="UNK")
        member.save()
        c1 = URL.Component(activity=a1, title="URL Link", position=8)
        c1.save()
        c2 = Archive.Component(activity=a1,
                               title="Archive File",
                               position=1,
                               max_size=100000)
        c2.save()
        c3 = Code.Component(activity=a1,
                            title="Code File",
                            position=3,
                            max_size=2000,
                            allowed=".py")
        c3.save()

        userid1 = "0aaa0"
        userid2 = "0aaa1"
        userid3 = "0aaa2"
        for u in [userid1, userid2, userid3]:
            p = Person.objects.get(userid=u)
            m = Member(person=p,
                       offering=course,
                       role="STUD",
                       credits=3,
                       career="UGRD",
                       added_reason="UNK")
            m.save()
        m = Member.objects.get(person__userid=userid1, offering=course)
        g = Group(name="Test Group", manager=m, courseoffering=course)
        g.save()
        gm = GroupMember(group=g, student=m, confirmed=True, activity=a1)
        gm.save()
        gm = GroupMember(group=g, student=m, confirmed=True, activity=a2)
        gm.save()
        m = Member.objects.get(person__userid=userid2, offering=course)
        gm = GroupMember(group=g, student=m, confirmed=True, activity=a1)
        gm.save()
        gm = GroupMember(group=g, student=m, confirmed=True, activity=a2)
        gm.save()
        m = Member.objects.get(person__userid=userid3, offering=course)
        gm = GroupMember(group=g, student=m, confirmed=True, activity=a2)
        gm.save()

        client = Client()
        # login as "0aaa0", member of group : test_group for assignment1 and assgnment2
        client.login_user("0aaa0")

        #submission page for assignment 1
        url = reverse('offering:submission:show_components',
                      kwargs={
                          'course_slug': course.slug,
                          'activity_slug': a1.slug
                      })
        response = basic_page_tests(self, client, url)
        self.assertContains(
            response,
            "This is a group activity. You will submit on behalf of the group &ldquo;Test Group&rdquo;."
        )
        self.assertContains(
            response, "You haven't made a submission for this component.")
示例#27
0
    def test_formulas(self):
        """
        Test the formula parsing & evaluation.
        """
        # set up course and related data
        s, c = create_offering()
        p = Person.objects.get(userid="0aaa0")
        m = Member(person=p,
                   offering=c,
                   role="STUD",
                   credits=3,
                   added_reason="UNK")
        m.save()

        a = NumericActivity(name="Paragraph",
                            short_name="\u00b6",
                            status="RLS",
                            offering=c,
                            position=3,
                            max_grade=40,
                            percent=5)
        a.save()
        g = NumericGrade(activity=a, member=m, value="4.5", flag="CALC")
        g.save(entered_by='ggbaker')
        a1 = NumericActivity(name="Assignment #1",
                             short_name="A1",
                             status="RLS",
                             offering=c,
                             position=1,
                             max_grade=15,
                             percent=10)
        a1.save()
        g = NumericGrade(activity=a1, member=m, value=10, flag="GRAD")
        g.save(entered_by='ggbaker')
        a2 = NumericActivity(name="Assignment #2",
                             short_name="A2",
                             status="URLS",
                             offering=c,
                             position=2,
                             max_grade=40,
                             percent=20)
        a2.save(entered_by='ggbaker')
        g = NumericGrade(activity=a2, member=m, value=30, flag="GRAD")
        g.save(entered_by='ggbaker')

        ca = CalNumericActivity(name="Final Grade",
                                short_name="FG",
                                status="RLS",
                                offering=c,
                                position=4,
                                max_grade=1)
        ca.save()

        activities = NumericActivity.objects.filter(offering=c)
        act_dict = activities_dictionary(activities)

        # make sure a formula can be pickled and unpickled safely (i.e. can be cached)
        tree = parse("sum([Assignment #1], [A1], [A2])/20*-3", c, ca)
        p = pickle.dumps(tree)
        tree2 = pickle.loads(p)
        self.assertEqual(tree, tree2)
        # check that it found the right list of columns used
        self.assertEqual(cols_used(tree), set(['A1', 'A2', 'Assignment #1']))

        # test parsing and evaluation to make sure we get the right values out
        for expr, correct in test_formulas:
            tree = parse(expr, c, ca)
            res = eval_parse(tree, ca, act_dict, m, False)
            self.assertAlmostEqual(correct,
                                   res,
                                   msg="Incorrect result for %s" % (expr, ))

        # test some badly-formed stuff for appropriate exceptions
        tree = parse("1 + BEST(3, [A1], [A2])", c, ca)
        self.assertRaises(EvalException, eval_parse, tree, ca, act_dict, m,
                          True)
        tree = parse("1 + BEST(0, [A1], [A2])", c, ca)
        self.assertRaises(EvalException, eval_parse, tree, ca, act_dict, m,
                          True)
        tree = parse("[Foo] /2", c, ca)
        self.assertRaises(KeyError, eval_parse, tree, ca, act_dict, m, True)
        tree = parse("[a1] /2", c, ca)
        self.assertRaises(KeyError, eval_parse, tree, ca, act_dict, m, True)

        self.assertRaises(ParseException, parse, "AVG()", c, ca)
        self.assertRaises(ParseException, parse, "(2+3*84", c, ca)
        self.assertRaises(ParseException, parse, "2+3**84", c, ca)
        self.assertRaises(ParseException, parse, "AVG(2,3,4", c, ca)
        self.assertRaises(ParseException, parse, "{something}", c, ca)

        # test visible/invisible switching
        tree = parse("[Assignment #2]", c, ca)
        res = eval_parse(tree, ca, act_dict, m, True)
        self.assertAlmostEqual(res, 0.0)
        res = eval_parse(tree, ca, act_dict, m, False)
        self.assertAlmostEqual(res, 30.0)

        # test unreleased/missing grade conditions
        expr = "[Assignment #2]"
        tree = parse(expr, c, ca)

        # unreleased assignment (with grade) should not be included in the calculation
        a2.status = 'URLS'
        a2.save()
        activities = NumericActivity.objects.filter(offering=c)
        act_dict = activities_dictionary(activities)
        res = eval_parse(tree, ca, act_dict, m, True)
        self.assertAlmostEqual(res, 0.0)
        # ... unless the instructor said to do so.
        ca.set_calculation_leak(True)
        res = eval_parse(tree, ca, act_dict, m, True)
        self.assertAlmostEqual(res, 30.0)

        # explicit no grade (released assignment)
        g.flag = "NOGR"
        g.save(entered_by='ggbaker')
        a2.status = 'RLS'
        a2.save(entered_by='ggbaker')
        activities = NumericActivity.objects.filter(offering=c)
        act_dict = activities_dictionary(activities)
        res = eval_parse(tree, ca, act_dict, m, True)
        self.assertAlmostEqual(res, 0.0)

        # no grade in database (released assignment)
        g.delete()
        activities = NumericActivity.objects.filter(offering=c)
        act_dict = activities_dictionary(activities)
        res = eval_parse(tree, ca, act_dict, m, True)
        self.assertAlmostEqual(res, 0.0)

        # test [[activitytotal]]
        expr = "[[activitytotal]]"
        tree = parse(expr, c, ca)
        res = eval_parse(tree, ca, act_dict, m, True)
        self.assertAlmostEqual(res, 7.229166666)
示例#28
0
    def test_component_view_page(self):
        _, course = create_offering()
        a1 = NumericActivity(name="Assignment 1",
                             short_name="A1",
                             status="RLS",
                             offering=course,
                             position=2,
                             max_grade=15,
                             due_date="2010-04-01")
        a1.save()
        a2 = NumericActivity(name="Assignment 2",
                             short_name="A2",
                             status="RLS",
                             offering=course,
                             position=1,
                             max_grade=15,
                             due_date="2010-03-01")
        a2.save()

        p = Person.objects.get(userid="ggbaker")
        member = Member(person=p,
                        offering=course,
                        role="INST",
                        career="NONS",
                        added_reason="UNK")
        member.save()

        c1 = URL.Component(activity=a1, title="URL Link", position=8)
        c1.save()
        c2 = Archive.Component(activity=a1,
                               title="Archive File",
                               position=1,
                               max_size=100000)
        c2.save()
        c3 = Code.Component(activity=a1,
                            title="Code File",
                            position=3,
                            max_size=2000,
                            allowed=".py")
        c3.save()
        client = Client()
        client.login_user("ggbaker")

        # When no component, should display error message
        url = reverse('offering:submission:show_components',
                      kwargs={
                          'course_slug': course.slug,
                          'activity_slug': a2.slug
                      })
        response = basic_page_tests(self, client, url)
        self.assertContains(response, 'No components configured.')
        # add component and test
        component = URL.Component(activity=a2, title="URL2", position=1)
        component.save()
        component = Archive.Component(activity=a2,
                                      title="Archive2",
                                      position=1,
                                      max_size=100)
        component.save()
        # should all appear
        response = basic_page_tests(self, client, url)
        self.assertContains(response, "URL2")
        self.assertContains(response, "Archive2")
        # make sure type displays
        #self.assertContains(response, '<li class="view"><label>Type:</label>Archive</li>')
        # delete component
        self.assertRaises(NotImplementedError, component.delete)
示例#29
0
def test_class_1(slug):
    """
    main test course: 20 students, TA, some assignments
    """
    crs = CourseOffering.objects.get(slug=slug)
    
    crs.set_labtut(True)
    crs.set_url("http://www.cs.sfu.ca/CC/165/common/")
    crs.set_taemail("*****@*****.**")
    crs.save()
    for i in range(10):
        lab = "D1%02i" % (random.randint(1,4))
        p = Person.objects.get(userid="0aaa%i"%(i))
        if Member.objects.filter(person=p, offering=crs, role="STUD"):
            # randomly added by other student-adder: skip
            continue

        m = Member(person=p, offering=crs, role="STUD", credits=3, career="UGRD", added_reason="AUTO",
                labtut_section=lab)
        m.save()
    
    if not Member.objects.filter(person__userid='ggbaker', offering=crs, role='INST'):
        Member(person=Person.objects.get(userid='ggbaker'), offering=crs, role='INST').save()
    
    # create a TA
    p = Person(emplid=fake_emplid(), userid="0grad1", last_name="Gradstudent", first_name="Douglas", middle_name="", pref_first_name="Doug")
    p.save()
    m = Member(person=p, offering=crs, role="TA", credits=0, career="NONS", added_reason="AUTO",
            labtut_section=None)
    m.save()
    
    
    # create example activities
    crs.activity_set.all().update(deleted=True)
    a1 = NumericActivity(offering=crs, name="Assignment 1", short_name="A1", status="RLS",
        due_date=crs.semester.start + datetime.timedelta(days=60), percent=10, group=False,
        max_grade=10, position=1)
    a1.set_url("http://www.cs.sfu.ca/CC/165/common/a1")
    a1.save()
    a2 = NumericActivity(offering=crs, name="Assignment 2", short_name="A2", status="URLS",
        due_date=crs.semester.start + datetime.timedelta(days=70), percent=10, group=True,
        max_grade=20, position=2)
    a2.save()
    pr = LetterActivity(offering=crs, name="Project", short_name="Proj", status="URLS",
        due_date=crs.semester.start + datetime.timedelta(days=80), percent=40, group=True, position=3)
    pr.save()
    re = LetterActivity(offering=crs, name="Report", short_name="Rep", status="URLS",
        due_date=crs.semester.start + datetime.timedelta(days=81), percent=10, group=False, position=4)
    re.save()
    ex = NumericActivity(offering=crs, name="Final Exam", short_name="Exam", status="URLS",
        due_date=None, percent=30, group=False, max_grade=90, position=5)
    ex.save()
    to = CalNumericActivity(offering=crs, name="Final Percent", short_name="Perc", status="INVI",
        due_date=None, percent=0, group=False, max_grade=100, formula="[[activitytotal]]", position=6)
    to.save()
    to = CalLetterActivity(offering=crs, name="Letter Grade", short_name="Letter", status="INVI",
        due_date=None, percent=0, group=False, numeric_activity=to, position=6)
    to.save()
    
    # make A1 submittable and markable
    s = CodeComponent(activity=a1, title="Code File", description="The code you're submitting.",
        allowed=".py,.java")
    s.save()
    s = PDFComponent(activity=a1, title="Report", description="Report on what you did.",
        specified_filename="report.pdf")
    s.save()
    
    m = ActivityComponent(numeric_activity=a1, max_mark=5, title="Part 1", description="Part 1 was done well and seems to work.", position=1)
    m.save()
    m = ActivityComponent(numeric_activity=a1, max_mark=5, title="Part 2", description="Part 2 was done well and seems to work.", position=2)
    m.save()
    
    # create some groups
    g = Group(name="SomeGroup", courseoffering=crs, manager=Member.objects.get(offering=crs, person__userid="0aaa0", role='STUD'))
    g.save()
    for userid in ['0aaa0', '0aaa1', '0aaa5', '0aaa8']:
        gm = GroupMember(group=g, student=Member.objects.get(offering=crs, person__userid=userid), confirmed=True, activity=a2)
        gm.save()
    
    g = Group(name="AnotherGroup", courseoffering=crs, manager=Member.objects.get(offering=crs, person__userid="0aaa4"))
    g.save()
    for userid in ['0aaa4', '0aaa6', '0aaa7', '0aaa2']:
        gm = GroupMember(group=g, student=Member.objects.get(offering=crs, person__userid=userid), confirmed=True, activity=a2)
        gm.save()
        gm = GroupMember(group=g, student=Member.objects.get(offering=crs, person__userid=userid), confirmed=True, activity=pr)
        gm.save()
示例#30
0
    def test_replace_activity(self):
        """
        Can we safely replace an activity with one of the same name/shortname?
        """
        c = CourseOffering.objects.get(slug=self.course_slug)
        a = NumericActivity(offering=c,
                            name="Assign1",
                            short_name="A1",
                            status="RLS",
                            group=False,
                            deleted=False,
                            max_grade=10,
                            position=1)
        a.save()

        a.safely_delete()
        self.assertEqual(a.deleted, True)
        self.assertNotEqual(a.name, 'Assign1')
        self.assertNotEqual(a.short_name, 'A1')

        # replace with same type
        a = CalNumericActivity(offering=c,
                               name="Assign1",
                               short_name="A1",
                               status="URLS",
                               group=True,
                               deleted=False,
                               max_grade=15,
                               position=2)
        a.save()
        a.safely_delete()

        # replace with a different type
        a = LetterActivity(offering=c,
                           name="Assign1",
                           short_name="A1",
                           status="RLS",
                           group=False,
                           deleted=False,
                           position=3)
        a.save()
示例#31
0
def create_coredata():
    """
    Create enough of the coredata.models stuff to run basic tests
    """
    create_units()

    # restore ggbaker's real emplid so import_offerings will match
    p = find_person('ggbaker')
    p.emplid = find_emplid('ggbaker')

    # import a few more people we definitely need later
    find_person('popowich')
    find_person('dixon')
    find_person('diana')
    find_person('dzhao')
    find_person('pba7')

    # import a limited set of course offerings
    offerings = import_offerings(import_semesters=import_strms, extra_where=
        "(subject='CMPT' AND (catalog_nbr LIKE '%% 12%%')) "
        "OR (subject='ENSC' AND (catalog_nbr LIKE '%% 10%%')) "
        )
    offerings = list(offerings)
    offerings.sort()

    if not CourseOffering.objects.filter(slug=TEST_COURSE_SLUG):
        o = CourseOffering.objects.filter(subject='CMPT', semester__name=import_strms()[0]) \
            .order_by('number', 'section').first()
        raise ValueError, "courselib.testing.TEST_COURSE_SLUG isn't an offering we have. Maybe use '%s'." % (o.slug)

    # import instructors
    for o in offerings:
        import_offering_members(o, students=False)

    # try to guess instructors' userids
    for p in Person.objects.filter(userid__isnull=True):
        p.userid = guess_userid(p.emplid)
        p.save()

    fake_emplids()

    # use/import no real emplids after this

    # create some fake undergrad/grad students
    for i in range(20):
        userid = "0aaa%i" % (i)
        fname = randname(8)
        p = random.randint(1,2)
        if p == 1:
            pref = fname[:4]
        else:
            pref = fname
        p = Person(emplid=300000300+i, userid=userid, last_name='Student', first_name=fname, middle_name=randname(6), pref_first_name=pref)
        p.save()

        userid = "0ggg%i" % (i)
        fname = randname(8)
        p = random.randint(1,2)
        if p == 1:
            pref = fname[:4]
        else:
            pref = fname
        p = Person(emplid=300000500+i, userid=userid, last_name='Grad', first_name=fname, middle_name=randname(6), pref_first_name=pref)
        p.config['gender'] = random.choice(('M','F','U'))
        p.config['gpa'] = round(random.triangular(0.0, 4.33, 2.33), 2)
        p.config['visa'] = random.choice([x for x,_ in VISA_STATUSES])
        p.config['citizen'] = random.choice(('Canadian', 'OtherCountrian'))
        p.save()

    # some memberships/roles/etc assumed by tests
    o = CourseOffering.objects.get(slug=TEST_COURSE_SLUG)
    ensure_member(Person.objects.get(userid='ggbaker'), o, "INST", 0, "AUTO", "NONS")
    ensure_member(Person.objects.get(userid='0ggg0'), o, "TA", 0, "AUTO", "NONS")
    ensure_member(Person.objects.get(userid='0aaa0'), o, "STUD", 3, "AUTO", "UGRD")
    ensure_member(Person.objects.get(userid='0aaa1'), o, "STUD", 3, "AUTO", "UGRD")

    d = Person.objects.get(userid='dzhao')
    set_privacy_signed(d)
    r1 = Role(person=d, role='ADVS', unit=Unit.objects.get(slug='cmpt'))
    r1.save()
    r2 = Role(person=d, role='ADMN', unit=Unit.objects.get(slug='cmpt'))
    r2.save()
    r3 = Role(person=Person.objects.get(userid='pba7'), role='SYSA', unit=Unit.objects.get(slug='univ'))
    r3.save()

    # ensures course appears in menu for students
    a = NumericActivity(offering=o, name='Assignment 1', short_name='A1', status='URLS', position=1, percent=10,
        max_grade=10, due_date=(o.semester.start + datetime.timedelta(days=60)))
    a.save()

    return itertools.chain(
        SemesterWeek.objects.filter(semester__name__gt=SEMESTER_CUTOFF),
        Unit.objects.all(),
        Course.objects.all(),
        CourseOffering.objects.all(),
        Person.objects.order_by('emplid'),
        Member.objects.all(),
        [r1, r2, r3, a.activity_ptr, a],
    )
示例#32
0
def create_test_offering():
    """
    main test course: interesting data for grades, marking, submission, groups
    """
    from grades.models import Activity, LetterActivity, CalNumericActivity, CalLetterActivity
    from submission.models import SubmissionComponent
    from submission.models.code import CodeComponent
    from submission.models.pdf import PDFComponent
    from groups.models import Group, GroupMember
    from marking.models import ActivityComponent

    crs = CourseOffering.objects.get(slug=TEST_COURSE_SLUG)

    crs.set_labtut(True)
    crs.set_url("http://www.cs.sfu.ca/CC/165/common/")
    crs.set_taemail("*****@*****.**")
    crs.save()

    # create example activities
    a1 = NumericActivity.objects.get(offering=crs, slug='a1')
    a2 = NumericActivity(offering=crs, name="Assignment 2", short_name="A2", status="URLS",
        due_date=crs.semester.start + datetime.timedelta(days=70), percent=10, group=True,
        max_grade=20, position=2)
    a2.set_url("http://www.cs.sfu.ca/CC/165/common/a2")
    a2.save()
    pr = LetterActivity(offering=crs, name="Project", short_name="Proj", status="URLS",
        due_date=crs.semester.start + datetime.timedelta(days=80), percent=40, group=True, position=3)
    pr.save()
    re = LetterActivity(offering=crs, name="Report", short_name="Rep", status="URLS",
        due_date=crs.semester.start + datetime.timedelta(days=81), percent=10, group=False, position=4)
    re.save()
    ex = NumericActivity(offering=crs, name="Final Exam", short_name="Exam", status="URLS",
        due_date=None, percent=30, group=False, max_grade=90, position=5)
    ex.save()
    to = CalNumericActivity(offering=crs, name="Final Percent", short_name="Perc", status="INVI",
        due_date=None, percent=0, group=False, max_grade=100, formula="[[activitytotal]]", position=6)
    to.save()
    to = CalLetterActivity(offering=crs, name="Letter Grade", short_name="Letter", status="INVI",
        due_date=None, percent=0, group=False, numeric_activity=to, position=6)
    to.save()

    # make A1 submittable and markable
    s = CodeComponent(activity=a1, title="Code File", description="The code you're submitting.",
        allowed=".py,.java")
    s.save()
    s = PDFComponent(activity=a1, title="Report", description="Report on what you did.",
        specified_filename="report.pdf")
    s.save()

    m = ActivityComponent(numeric_activity=a1, max_mark=5, title="Part 1", description="Part 1 was done well and seems to work.", position=1)
    m.save()
    m = ActivityComponent(numeric_activity=a1, max_mark=5, title="Part 2", description="Part 2 was done well and seems to work.", position=2)
    m.save()

    # create some groups
    members = list(Member.objects.filter(offering=crs, role='STUD'))
    random.shuffle(members)
    m = members.pop()
    g = Group(name="SomeGroup", courseoffering=crs, manager=m)
    g.save()
    for m in [m, members.pop()]:
        gm = GroupMember(group=g, student=m, confirmed=True, activity=a2)
        gm.save()

    m = members.pop()
    g = Group(name="AnotherGroup", courseoffering=crs, manager=m)
    g.save()
    for m in [m, members.pop(), members.pop()]:
        gm = GroupMember(group=g, student=m, confirmed=True, activity=a2)
        gm.save()
        gm = GroupMember(group=g, student=m, confirmed=True, activity=pr)
        gm.save()

    return itertools.chain(
        Activity.objects.all(),
        NumericActivity.objects.all(),
        LetterActivity.objects.all(),
        CalNumericActivity.objects.all(),
        CalLetterActivity.objects.all(),
        SubmissionComponent.objects.all(),
        CodeComponent.objects.all(),
        PDFComponent.objects.all(),
        Group.objects.all(),
        GroupMember.objects.all(),
        ActivityComponent.objects.all(),
    )
示例#33
0
文件: tests.py 项目: sfu-fas/coursys
class TestImportFunctionsNumeric(TestCase):
    fixtures = ['basedata', 'coredata', 'grades']

    def setUp(self):
        self.c_slug = TEST_COURSE_SLUG
        self.client = Client()
        self.c = CourseOffering.objects.get(slug = self.c_slug)
        self.a1 = NumericActivity(offering = self.c, name = 'test_assignment_1', 
                            short_name = 'ta1', status = 'RLS', 
                            due_date = datetime.now(), max_grade = 100,
                            position = 0)
        self.a1.save()
        self.students = self.c.members.filter(person__role='STUD')
        self.userids = [p.userid for p in self.students]
        self.emplids = [p.emplid for p in self.students]

    def get_test_file(self, name):
        with open(name, 'r') as inp:
            r = csv.reader(inp)
            self.values = []
            for line in r:
                self.values.append(line)

    def compare_grade_lists(self, data_returned):
        for sname, grade in self.values:
            sname = _strip_email_userid(sname)
            self.assertIn(sname, list(data_returned.keys()))
            self.assertEqual(data_returned[sname], grade)
        

    def test_import_grades_old_format(self):
        inName = 'marking/testfiles/oldformat_noprob.csv'
        self.get_test_file(inName)
        data_to_return = {}
        with open(inName, 'rb') as inp:
            err = _compose_imported_grades(inp, self.students, data_to_return, self.a1)
        self.assertEqual(err, [])
        self.assertEqual(len(data_to_return), len(self.values))
        self.compare_grade_lists(data_to_return)

    def test_import_grades_old_format_unknown_userid(self):
        inName = 'marking/testfiles/oldformat_unk_uid.csv'
        self.get_test_file(inName)
        bad_id = [n for n,_ in self.values if n not in self.userids] [0]
        data_to_return = {}
        with open(inName, 'rb') as inp:
            err = _compose_imported_grades(inp, self.students, data_to_return, self.a1)
        self.assertEqual(err, ['Error found in the file (row 2): Unmatched student number '
            'or user-id ({0}).'. format(bad_id)])
        self.assertEqual(len(data_to_return), 2)

    def test_import_grades_old_format_unknown_emplid(self):
        inName = 'marking/testfiles/oldformat_unk_emplid.csv'
        self.get_test_file(inName)
        bad_emplid = [e for e,_ in self.values if int(e) not in self.emplids] [0]
        data_to_return = {}
        with open(inName, 'rb') as inp:
            err = _compose_imported_grades(inp, self.students, data_to_return, self.a1)
        self.assertIn('Error found in the file (row 1): Unmatched student number '
                      'or user-id ({0}).'. format(bad_emplid), err)
        self.assertEqual(len(data_to_return), 0)

    def test_import_grades_new_format(self):
        inName = 'marking/testfiles/newformat_noprob_userid.csv'
        self.get_test_file(inName)
        del self.values[0] # Delete header row
        data_to_return = {}
        with open(inName, 'rb') as inp:
             err = _compose_imported_grades(inp, self.students, data_to_return, self.a1)
        self.assertEqual(err, [])
        self.assertEqual(len(data_to_return), len(self.values))
        self.compare_grade_lists(data_to_return)

    def test_import_grades_short_row(self):
        inName = 'marking/testfiles/newformat_shortrow_userid.csv'
        self.get_test_file(inName)
        del self.values[0] # Delete header row
        data_to_return = {}
        with open(inName, 'rb') as inp:
             err = _compose_imported_grades(inp, self.students, data_to_return, self.a1)
        self.assertEqual(err, [])
        self.assertEqual(len(data_to_return), len(self.values)-1)

    def test_import_grades_new_format_junk_cols(self):
        inName = 'marking/testfiles/newformat_noprob_junk_cols.csv'
        self.get_test_file(inName)
        del self.values[0] # Delete header row
        for i, row in enumerate(self.values):
            self.values[i] = [self.values[i][3], self.values[i][1]]
        data_to_return = {}
        with open(inName, 'rb') as inp:
             err = _compose_imported_grades(inp, self.students, data_to_return, self.a1)
        self.assertEqual(err, [])
        self.assertEqual(len(data_to_return), len(self.values))
        self.compare_grade_lists(data_to_return)

    def test_import_grades_new_format_missing_uid_col(self):
        '''
            Judgement call on the design:  If the import file lacks a field
            named 'Userid', we treat it as an old-format file and get an 
            error on the first line.  This unfortunate outcome is required
            if we are to avoid misinterpreting a short assignment name that
            matches a student id and thereby misinterpreting an old-style
            file as though it were a defective (i.e., no 'Userid' column)
            new-style file.
        '''
        inName = 'marking/testfiles/newformat_missing_uid_col.csv'
        data_to_return = {}
        with open(inName, 'rb') as inp:
            err = _compose_imported_grades(inp, self.students, data_to_return, self.a1)
        self.assertIn('Error found in the file (row 1): Unmatched student number or user-id (Junk1).', err)
        self.assertIn('Error found in the file (row 2): Unmatched student number or user-id (w1).', err)
        self.assertIn('Error found in the file (row 3): Unmatched student number or user-id (w2).', err)
        self.assertEqual(len(data_to_return), 0)


    def test_import_grades_new_format_missing_act_col(self):
        inName = 'marking/testfiles/newformat_missing_act_col.csv'
        data_to_return = {}
        with open(inName, 'rb') as inp:
             err = _compose_imported_grades(inp, self.students, data_to_return, self.a1)
        self.assertIn('Error in file header line:  No '
            'column labelled for activity {0}.'.format(self.a1.short_name), err)
        self.assertEqual(len(data_to_return), 0)

    def test_import_grades_new_format_dup_act_col(self):
        inName = 'marking/testfiles/newformat_dup_act_col.csv'
        data_to_return = {}
        with open(inName, 'rb') as inp:
            err = _compose_imported_grades(inp, self.students, data_to_return, self.a1)
        self.assertIn('Error in file header line:  Two columns '
            'labelled {0}.'.format(self.a1.short_name), err)
        self.assertEqual(len(data_to_return), 0)

    def test_import_grades_new_format_missing_values(self):
        ''' OK for students to have no grade assigned. '''
        inName = 'marking/testfiles/newformat_missing_student_grade.csv'
        self.get_test_file(inName)
        del self.values[0] # Delete header row
        for i, row in enumerate(self.values):
            self.values[i] = [self.values[i][6], self.values[i][1]]
        data_to_return = {}
        with open(inName, 'rb') as inp:
            err = _compose_imported_grades(inp, self.students, data_to_return, self.a1)
        self.assertEqual(err, [])
        self.assertEqual(len(data_to_return), len(self.values))
        self.compare_grade_lists(data_to_return)

    def test_import_grades_new_format_bad_utf8(self):
        inName = 'marking/testfiles/newformat_bad_utf8.csv'
        data_to_return = {}
        with open(inName, 'rb') as inp:
            err = _compose_imported_grades(inp, self.students, data_to_return, self.a1)
        self.assertIn('File cannot be decoded as UTF-8 data: make sure it has been saved as UTF-8 text.', err)
        self.assertEqual(len(data_to_return), 0)

    def test_import_grades_new_format_utf8_bom(self):
        inName = 'marking/testfiles/newformat_utf8_bom.csv'
        data_to_return = {}
        with open(inName, 'rb') as inp:
            err = _compose_imported_grades(inp, self.students, data_to_return, self.a1)
        self.assertEqual(err, [])
示例#34
0
 def test_activities(self):
     """
     Test activity classes: subclasses, selection, sorting.
     """
     s, c = create_offering()
    
     a = NumericActivity(name="Assignment 1", short_name="A1", status="RLS", offering=c, position=2, max_grade=15)
     a.save()
     a = NumericActivity(name="Assignment 2", short_name="A2", status="RLS", offering=c, position=6, max_grade=15)
     a.save()
     a = LetterActivity(name="Project", short_name="Proj", status="URLS", offering=c, position=1)
     a.save()
     a = CalNumericActivity(name="Total", short_name="Total", status="URLS", offering=c, position=42, max_grade=30, formula="[A1]+[A2]")
     a.save()
    
     allact = all_activities_filter(offering=c)
     self.assertEqual(len(allact), 4)
     self.assertEqual(allact[0].slug, 'proj') # make sure position=1 is first
     self.assertEqual(type(allact[1]), NumericActivity)
     self.assertEqual(type(allact[3]), CalNumericActivity)
示例#35
0
    def test_activities(self):
        """
        Test activity classes: subclasses, selection, sorting.
        """
        s, c = create_offering()

        a = NumericActivity(name="Assignment 1",
                            short_name="A1",
                            status="RLS",
                            offering=c,
                            position=2,
                            max_grade=15)
        a.save()
        a = NumericActivity(name="Assignment 2",
                            short_name="A2",
                            status="RLS",
                            offering=c,
                            position=6,
                            max_grade=15)
        a.save()
        a = LetterActivity(name="Project",
                           short_name="Proj",
                           status="URLS",
                           offering=c,
                           position=1)
        a.save()
        a = CalNumericActivity(name="Total",
                               short_name="Total",
                               status="URLS",
                               offering=c,
                               position=42,
                               max_grade=30,
                               formula="[A1]+[A2]")
        a.save()

        allact = all_activities_filter(offering=c)
        self.assertEqual(len(allact), 4)
        self.assertEqual(allact[0].slug,
                         'proj')  # make sure position=1 is first
        self.assertEqual(type(allact[1]), NumericActivity)
        self.assertEqual(type(allact[3]), CalNumericActivity)
示例#36
0
def create_coredata():
    """
    Create enough of the coredata.models stuff to run basic tests
    """
    create_units()

    # restore ggbaker's real emplid so import_offerings will match
    p = find_person('ggbaker')
    p.emplid = find_emplid('ggbaker')

    # import a few more people we definitely need later
    find_person('popowich')
    find_person('dixon')
    find_person('diana')
    find_person('dzhao')
    find_person('pba7')

    # import a limited set of course offerings
    offerings = import_offerings(
        import_semesters=import_strms,
        extra_where="(subject='CMPT' AND (catalog_nbr LIKE '%% 12%%')) "
        "OR (subject='CMPT' AND (catalog_nbr LIKE '%% 16%%')) "
        "OR (subject='ENSC' AND (catalog_nbr LIKE '%% 10%%')) ")
    offerings = list(offerings)
    offerings.sort()

    if not CourseOffering.objects.filter(slug=TEST_COURSE_SLUG):
        o = CourseOffering.objects.filter(subject='CMPT', semester__name=import_strms()[0]) \
            .order_by('number', 'section').first()
        raise ValueError, "courselib.testing.TEST_COURSE_SLUG isn't an offering we have. Maybe use '%s'." % (
            o.slug)

    # import instructors
    for o in offerings:
        import_offering_members(o, students=False)

    # try to guess instructors' userids
    for p in Person.objects.filter(userid__isnull=True):
        p.userid = guess_userid(p.emplid)
        p.save()

    fake_emplids()

    # use/import no real emplids after this

    # create some fake undergrad/grad students
    for i in range(20):
        userid = "0aaa%i" % (i)
        fname = randname(8)
        p = random.randint(1, 2)
        if p == 1:
            pref = fname[:4]
        else:
            pref = fname
        p = Person(emplid=300000300 + i,
                   userid=userid,
                   last_name='Student',
                   first_name=fname,
                   middle_name=randname(6),
                   pref_first_name=pref)
        p.save()

        userid = "0ggg%i" % (i)
        fname = randname(8)
        p = random.randint(1, 2)
        if p == 1:
            pref = fname[:4]
        else:
            pref = fname
        p = Person(emplid=300000500 + i,
                   userid=userid,
                   last_name='Grad',
                   first_name=fname,
                   middle_name=randname(6),
                   pref_first_name=pref)
        p.config['gender'] = random.choice(('M', 'F', 'U'))
        p.config['gpa'] = round(random.triangular(0.0, 4.33, 2.33), 2)
        p.config['visa'] = random.choice([x for x, _ in VISA_STATUSES])
        p.config['citizen'] = random.choice(('Canadian', 'OtherCountrian'))
        p.save()

    # some memberships/roles/etc assumed by tests
    o = CourseOffering.objects.get(slug=TEST_COURSE_SLUG)
    ensure_member(Person.objects.get(userid='ggbaker'), o, "INST", 0, "AUTO",
                  "NONS")
    ensure_member(Person.objects.get(userid='0ggg0'), o, "TA", 0, "AUTO",
                  "NONS")
    ensure_member(Person.objects.get(userid='0aaa0'), o, "STUD", 3, "AUTO",
                  "UGRD")
    ensure_member(Person.objects.get(userid='0aaa1'), o, "STUD", 3, "AUTO",
                  "UGRD")

    d = Person.objects.get(userid='dzhao')
    set_privacy_signed(d)
    u = Unit.objects.get(slug='cmpt')
    r1 = Role(person=d, role='ADVS', unit=u, expiry=role_expiry)
    r1.save()
    r2 = Role(person=d, role='ADMN', unit=u, expiry=role_expiry)
    r2.save()
    r3 = Role(person=Person.objects.get(userid='pba7'),
              role='SYSA',
              unit=Unit.objects.get(slug='univ'),
              expiry=role_expiry)
    r3.save()
    r4 = Role(person=d, role='INV', unit=u, expiry=role_expiry)
    r4.save()
    r5 = Role(person=d, role='OUTR', unit=u, expiry=role_expiry)
    r5.save()

    # ensures course appears in menu for students
    a = NumericActivity(offering=o,
                        name=u'Assignmenț 1',
                        short_name='A1',
                        status='URLS',
                        position=1,
                        percent=10,
                        max_grade=10,
                        due_date=(o.semester.start +
                                  datetime.timedelta(days=60)))
    a.save()

    return itertools.chain(
        SemesterWeek.objects.filter(semester__name__gt=SEMESTER_CUTOFF),
        Unit.objects.all(),
        Course.objects.all(),
        CourseOffering.objects.all(),
        Person.objects.order_by('emplid'),
        Member.objects.all(),
        [r1, r2, r3, r4, r5, a.activity_ptr, a],
    )
示例#37
0
文件: tests.py 项目: sfu-fas/coursys
    def test_frontend(self):
        client = Client()
        client.login_user('ggbaker')
        
        # set up a course
        c = CourseOffering.objects.get(slug = self.c_slug)
        a1 = NumericActivity(offering = c, name = 'test_assignment_1', \
                            short_name = 'ta1', status = 'RLS', \
                            due_date = datetime.now(), max_grade = 100, position = 0, group=True)
        a1.save()
        a2 = NumericActivity(offering = c, name = 'test_assignment_1', \
                            short_name = 'ta1', status = 'RLS', \
                            due_date = datetime.now(), max_grade = 100, position = 0, group=False)
        a2.save()
        
        stud1 = Member.objects.get(person = Person.objects.get(userid = '0aaa0'), offering = c)
        stud2 = Member.objects.get(person = Person.objects.get(userid = '0aaa1'), offering = c)
        instr = Member.objects.get(person = Person.objects.get(userid = 'ggbaker'), offering = c)
        group = Group.objects.create(courseoffering = c, name = 'hello', manager = stud1)
        member1 = GroupMember.objects.create(group = group, student = stud1, confirmed = True, activity=a1)
        member2 = GroupMember.objects.create(group = group, student = stud2, confirmed = True, activity=a1)
        
        # marking form (student)
        url = reverse('offering:marking:marking_student', kwargs={'course_slug':c.slug, 'activity_slug':a2.slug, 'userid':stud1.person.userid})

        response = basic_page_tests(self, client, url)
        
        ac = ActivityComponent(numeric_activity=a2, max_mark=5, title="AC Title", description="AC Description", position=1, deleted=False)
        ac.save()
        ac = ActivityComponent(numeric_activity=a2, max_mark=5, title="AC Title2", description="AC Description2", position=2, deleted=False)
        ac.save()
        cp = CommonProblem(activity_component=ac, title="CP title", penalty=2, description="Cp description", deleted=False)
        cp.save()

        response = basic_page_tests(self, client, url)
        
        # submit the form and check that objects were created
        PENALTY = '12.5' # Percentage
        CMP_1_VALUE = '5.5'
        CMP_2_VALUE = '3'
        ADJ = '1.25'# Adjustments are subtracted
        TOTAL_MARK = ((Decimal(CMP_1_VALUE) + Decimal(CMP_2_VALUE) - Decimal(ADJ)) *
            (1 - (Decimal(PENALTY) / 100))).quantize(Decimal('.01'), rounding=ROUND_HALF_EVEN)

        response = client.post(url, {'cmp-1-value': float(CMP_1_VALUE), 'cmp-1-comment': 'perfect part 1',
            'cmp-2-value': float(CMP_2_VALUE), 'cmp-2-comment': 'ok', 'mark_adjustment': float(ADJ),
            'mark_adjustment_reason': 'reason', 'late_penalty': float(PENALTY),
            'overall_comment': 'overall'})
        self.assertEqual(response.status_code, 302)
        sam = StudentActivityMark.objects.filter(activity=a2, numeric_grade__member=stud1)
        self.assertEqual(len(sam), 1)
        sam = sam[0]
        self.assertEqual(sam.mark_adjustment, Decimal(ADJ))
        self.assertEqual(sam.late_penalty, Decimal(PENALTY))
        self.assertEqual(sam.overall_comment, 'overall')
        self.assertEqual(sam.mark, TOTAL_MARK)
        acms = sam.activitycomponentmark_set.all()
        self.assertEqual(len(acms), 2)
        self.assertEqual(acms[0].value, Decimal(CMP_1_VALUE))
        self.assertEqual(acms[0].comment, 'perfect part 1')
        g = NumericGrade.objects.get(activity=a2, member=stud1)
        self.assertEqual(g.value, TOTAL_MARK)
        
        # make sure we get old data for "mark based on"
        response = basic_page_tests(self, client, url + "?base_activity_mark="+str(sam.id))
        #self.assertContains(response, 'name="cmp-1-value" type="text" value="{0}'.format(CMP_1_VALUE))
        #self.assertContains(response, 'name="late_penalty" type="text" value="{0}'.format(PENALTY))

        # look at the "view details" page
        url = reverse('offering:marking:mark_summary_student', kwargs={'course_slug':c.slug, 'activity_slug':a2.slug, 'userid':stud1.person.userid})
        response = basic_page_tests(self, client, url)
        self.assertContains(response, 'perfect part 1')

        # marking form (group)
        url = reverse('offering:marking:marking_student', kwargs={'course_slug':c.slug,
            'activity_slug':a1.slug, 'userid':stud1.person.userid})
        response = basic_page_tests(self, client, url)
        
        ac = ActivityComponent(numeric_activity=a1, max_mark=5, title="AC Title",
            description="AC Description", position=1, deleted=False)
        ac.save()
        ac = ActivityComponent(numeric_activity=a1, max_mark=5, title="AC Title2",
            description="AC Description2", position=2, deleted=False)
        ac.save()
        cp = CommonProblem(activity_component=ac, title="CP title", penalty=2,
            description="Cp description", deleted=False)
        cp.save()

        response = basic_page_tests(self, client, url)

        # common problem form
        url = reverse('offering:marking:manage_common_problems', kwargs={'course_slug':c.slug, 'activity_slug':a2.slug})
        response = basic_page_tests(self, client, url)
        
        # mark all (student and group)
        url = reverse('offering:mark_all_students', kwargs={'course_slug':c.slug, 'activity_slug':a2.slug})
        response = basic_page_tests(self, client, url)
        # mark all (student and group)
        url = reverse('offering:mark_all_groups', kwargs={'course_slug':c.slug, 'activity_slug':a1.slug})
        response = basic_page_tests(self, client, url)
示例#38
0
    def test_group_change(self):
        """
        Test changing group <-> individual on an activity.  Should only be possible in some conditions.
        """
        s, c = create_offering()

        # add some assignments and members
        due = datetime.datetime.now() + datetime.timedelta(days=1)
        due_date = str(due.date())
        due_time = due.time().strftime("%H:%M:%S")
        a = NumericActivity(name="Assignment 1", short_name="A1", status="RLS", offering=c, position=2, max_grade=15, percent=10, due_date=due, group=False)
        a.save()
        p = Person.objects.get(userid="ggbaker")
        m = Member(person=p, offering=c, role="INST", added_reason="UNK")
        m.save()
        p = Person.objects.get(userid="0aaa0")
        m = Member(person=p, offering=c, role="STUD", added_reason="UNK")
        m.save()
        
        client = Client()
        client.login_user("ggbaker")
        url = reverse('grades.views.edit_activity', kwargs={'course_slug': c.slug, 'activity_slug': a.slug})

        # for whatever reason, '0' is group and '1' is individual for the group value
        submit_dict = {'name': a.name, 'short_name': a.short_name, 'status': a.status, 'due_date_0': due_date, 'due_date_1': due_time, 'percent': a.percent, 'max_grade': a.max_grade, 'group': '1', 'extend_group': 'None'}
        # no change
        response = client.post(url, submit_dict)
        self.assertEquals(response.status_code, 302) # successful submit -> redirect
        self.assertEquals(NumericActivity.objects.get(id=a.id).group, False)

        # change indiv -> group
        submit_dict['group'] = '0'
        response = client.post(url, submit_dict)
        self.assertEquals(response.status_code, 302)
        self.assertEquals(NumericActivity.objects.get(id=a.id).group, True)
        
        # try with activity past due
        a.due_date = datetime.datetime.now() - datetime.timedelta(days=1)
        a.save()
        submit_dict['due_date_0'] = str(a.due_date.date())
        submit_dict['group'] = '0'
        response = client.post(url, submit_dict)
        self.assertEquals(response.status_code, 200) # error on form -> 200 and back to form with error
        self.assertContains(response, "due date has passed")
        
        # try with a mark in the system
        a.due_date = datetime.datetime.now() + datetime.timedelta(days=1)
        a.save()
        submit_dict['due_date_0'] = str(a.due_date.date())
        submit_dict['group'] = '0'
        g = NumericGrade(activity=a, member=m, value=2, flag="GRAD")
        g.save(entered_by='ggbaker')
        response = client.post(url, submit_dict)
        self.assertEquals(response.status_code, 200)
        self.assertContains(response, "grades have already been given")
        
        # try with a submission in the system
        g.flag = "NOGR"
        g.save(entered_by='ggbaker')
        s = StudentSubmission(activity=a, member=m)
        s.save()
        response = client.post(url, submit_dict)
        self.assertEquals(response.status_code, 200)
        self.assertContains(response, "submissions have already been made")
示例#39
0
def create_test_offering():
    """
    main test course: interesting data for grades, marking, submission, groups
    """
    from grades.models import Activity, LetterActivity, CalNumericActivity, CalLetterActivity
    from submission.models import SubmissionComponent
    from submission.models.code import CodeComponent
    from submission.models.pdf import PDFComponent
    from groups.models import Group, GroupMember
    from marking.models import ActivityComponent

    crs = CourseOffering.objects.get(slug=TEST_COURSE_SLUG)

    crs.set_labtut(True)
    crs.set_url("http://www.cs.sfu.ca/CC/165/common/")
    crs.set_taemail("*****@*****.**")
    crs.save()

    # create example activities
    a1 = NumericActivity.objects.get(offering=crs, slug='a1')
    a2 = NumericActivity(offering=crs,
                         name="Assignment 2",
                         short_name="A2",
                         status="URLS",
                         due_date=crs.semester.start +
                         datetime.timedelta(days=70),
                         percent=10,
                         group=True,
                         max_grade=20,
                         position=2)
    a2.set_url("http://www.cs.sfu.ca/CC/165/common/a2")
    a2.save()
    pr = LetterActivity(offering=crs,
                        name="Project",
                        short_name="Proj",
                        status="URLS",
                        due_date=crs.semester.start +
                        datetime.timedelta(days=80),
                        percent=40,
                        group=True,
                        position=3)
    pr.save()
    re = LetterActivity(offering=crs,
                        name="Report",
                        short_name="Rep",
                        status="URLS",
                        due_date=crs.semester.start +
                        datetime.timedelta(days=81),
                        percent=10,
                        group=False,
                        position=4)
    re.save()
    ex = NumericActivity(offering=crs,
                         name="Final Exam",
                         short_name="Exam",
                         status="URLS",
                         due_date=None,
                         percent=30,
                         group=False,
                         max_grade=90,
                         position=5)
    ex.save()
    to = CalNumericActivity(offering=crs,
                            name="Final Percent",
                            short_name="Perc",
                            status="INVI",
                            due_date=None,
                            percent=0,
                            group=False,
                            max_grade=100,
                            formula="[[activitytotal]]",
                            position=6)
    to.save()
    to = CalLetterActivity(offering=crs,
                           name="Letter Grade",
                           short_name="Letter",
                           status="INVI",
                           due_date=None,
                           percent=0,
                           group=False,
                           numeric_activity=to,
                           position=6)
    to.save()

    # make A1 submittable and markable
    s = CodeComponent(activity=a1,
                      title=u"Cöde File",
                      description="The code you're submitting.",
                      allowed=".py,.java")
    s.save()
    s = PDFComponent(activity=a1,
                     title="Report",
                     description="Report on what you did.",
                     specified_filename="report.pdf")
    s.save()

    m = ActivityComponent(
        numeric_activity=a1,
        max_mark=5,
        title=u"Part ➀",
        description="Part ➀ was done well and seems to work.",
        position=1,
        slug='part-1')
    m.save()
    m = ActivityComponent(
        numeric_activity=a1,
        max_mark=5,
        title="Part 2",
        description="Part 2 was done well and seems to work.",
        position=2)
    m.save()

    # create some groups
    members = list(Member.objects.filter(offering=crs, role='STUD'))
    random.shuffle(members)
    m = members.pop()
    g = Group(name="SomeGroup", courseoffering=crs, manager=m)
    g.save()
    for m in [m, members.pop()]:
        gm = GroupMember(group=g, student=m, confirmed=True, activity=a2)
        gm.save()

    m = members.pop()
    g = Group(name="AnotherGroup", courseoffering=crs, manager=m)
    g.save()
    for m in [m, members.pop(), members.pop()]:
        gm = GroupMember(group=g, student=m, confirmed=True, activity=a2)
        gm.save()
        gm = GroupMember(group=g, student=m, confirmed=True, activity=pr)
        gm.save()

    return itertools.chain(
        Activity.objects.all(),
        NumericActivity.objects.all(),
        LetterActivity.objects.all(),
        CalNumericActivity.objects.all(),
        CalLetterActivity.objects.all(),
        SubmissionComponent.objects.all(),
        CodeComponent.objects.all(),
        PDFComponent.objects.all(),
        Group.objects.all(),
        GroupMember.objects.all(),
        ActivityComponent.objects.all(),
    )
示例#40
0
    def test_formulas(self):
        """
        Test the formula parsing & evaluation.
        """
        # set up course and related data
        s, c = create_offering()
        p = Person.objects.get(userid="0aaa0")
        m = Member(person=p, offering=c, role="STUD", credits=3, added_reason="UNK")
        m.save()
       
        a = NumericActivity(name="Paragraph", short_name=u"\u00b6", status="RLS", offering=c, position=3, max_grade=40, percent=5)
        a.save()
        g = NumericGrade(activity=a, member=m, value="4.5", flag="CALC")
        g.save(entered_by='ggbaker')
        a1 = NumericActivity(name="Assignment #1", short_name="A1", status="RLS", offering=c, position=1, max_grade=15, percent=10)
        a1.save()
        g = NumericGrade(activity=a1, member=m, value=10, flag="GRAD")
        g.save(entered_by='ggbaker')
        a2 = NumericActivity(name="Assignment #2", short_name="A2", status="URLS", offering=c, position=2, max_grade=40, percent=20)
        a2.save(entered_by='ggbaker')
        g = NumericGrade(activity=a2, member=m, value=30, flag="GRAD")
        g.save(entered_by='ggbaker')
        
        ca = CalNumericActivity(name="Final Grade", short_name=u"FG", status="RLS", offering=c, position=4, max_grade=1)
        ca.save()
        
        activities = NumericActivity.objects.filter(offering=c)
        act_dict = activities_dictionary(activities)
        
        # make sure a formula can be pickled and unpickled safely (i.e. can be cached)
        tree = parse("sum([Assignment #1], [A1], [A2])/20*-3", c, ca)
        p = pickle.dumps(tree)
        tree2 = pickle.loads(p)
        self.assertEqual(tree, tree2)
        # check that it found the right list of columns used
        self.assertEqual(cols_used(tree), set(['A1', 'A2', 'Assignment #1']))
        
        # test parsing and evaluation to make sure we get the right values out
        for expr, correct in test_formulas:
            tree = parse(expr, c, ca)
            res = eval_parse(tree, ca, act_dict, m, False)
            self.assertAlmostEqual(correct, res, msg=u"Incorrect result for %s"%(expr,))

        # test some badly-formed stuff for appropriate exceptions
        tree = parse("1 + BEST(3, [A1], [A2])", c, ca)
        self.assertRaises(EvalException, eval_parse, tree, ca, act_dict, m, True)
        tree = parse("1 + BEST(0, [A1], [A2])", c, ca)
        self.assertRaises(EvalException, eval_parse, tree, ca, act_dict, m, True)
        tree = parse("[Foo] /2", c, ca)
        self.assertRaises(KeyError, eval_parse, tree, ca, act_dict, m, True)
        tree = parse("[a1] /2", c, ca)
        self.assertRaises(KeyError, eval_parse, tree, ca, act_dict, m, True)
        
        self.assertRaises(ParseException, parse, "AVG()", c, ca)
        self.assertRaises(ParseException, parse, "(2+3*84", c, ca)
        self.assertRaises(ParseException, parse, "2+3**84", c, ca)
        self.assertRaises(ParseException, parse, "AVG(2,3,4", c, ca)
        self.assertRaises(ParseException, parse, "{something}", c, ca)
        
        # test visible/invisible switching
        tree = parse("[Assignment #2]", c, ca)
        res = eval_parse(tree, ca, act_dict, m, True)
        self.assertAlmostEqual(res, 0.0)
        res = eval_parse(tree, ca, act_dict, m, False)
        self.assertAlmostEqual(res, 30.0)

        # test unreleased/missing grade conditions
        expr = "[Assignment #2]"
        tree = parse(expr, c, ca)
        
        # unreleased assignment (with grade)
        a2.status='URLS'
        a2.save()
        activities = NumericActivity.objects.filter(offering=c)
        act_dict = activities_dictionary(activities)
        res = eval_parse(tree, ca, act_dict, m, True)
        self.assertAlmostEqual(res, 0.0)
        
        # explicit no grade (released assignment)
        g.flag="NOGR"
        g.save(entered_by='ggbaker')
        a2.status='RLS'
        a2.save(entered_by='ggbaker')
        activities = NumericActivity.objects.filter(offering=c)
        act_dict = activities_dictionary(activities)
        res = eval_parse(tree, ca, act_dict, m, True)
        self.assertAlmostEqual(res, 0.0)

        # no grade in database (released assignment)
        g.delete()
        activities = NumericActivity.objects.filter(offering=c)
        act_dict = activities_dictionary(activities)
        res = eval_parse(tree, ca, act_dict, m, True)
        self.assertAlmostEqual(res, 0.0)
        
        # test [[activitytotal]]
        expr = "[[activitytotal]]"
        tree = parse(expr, c, ca)
        res = eval_parse(tree, ca, act_dict, m, True)
        self.assertAlmostEqual(res, 7.229166666)
示例#41
0
    def test_group_change(self):
        """
        Test changing group <-> individual on an activity.  Should only be possible in some conditions.
        """
        s, c = create_offering()

        # add some assignments and members
        due = datetime.datetime.now() + datetime.timedelta(days=1)
        due_date = str(due.date())
        due_time = due.time().strftime("%H:%M:%S")
        a = NumericActivity(name="Assignment 1",
                            short_name="A1",
                            status="RLS",
                            offering=c,
                            position=2,
                            max_grade=15,
                            percent=10,
                            due_date=due,
                            group=False)
        a.save()
        p = Person.objects.get(userid="ggbaker")
        m = Member(person=p, offering=c, role="INST", added_reason="UNK")
        m.save()
        p = Person.objects.get(userid="0aaa0")
        m = Member(person=p, offering=c, role="STUD", added_reason="UNK")
        m.save()

        client = Client()
        client.login_user("ggbaker")
        url = reverse('offering:edit_activity',
                      kwargs={
                          'course_slug': c.slug,
                          'activity_slug': a.slug
                      })

        # for whatever reason, '0' is group and '1' is individual for the group value
        submit_dict = {
            'name': a.name,
            'short_name': a.short_name,
            'status': a.status,
            'due_date_0': due_date,
            'due_date_1': due_time,
            'percent': a.percent,
            'max_grade': a.max_grade,
            'group': '1',
            'extend_group': 'None'
        }
        # no change
        response = client.post(url, submit_dict)
        self.assertEqual(response.status_code,
                         302)  # successful submit -> redirect
        self.assertEqual(NumericActivity.objects.get(id=a.id).group, False)

        # change indiv -> group
        submit_dict['group'] = '0'
        response = client.post(url, submit_dict)
        self.assertEqual(response.status_code, 302)
        self.assertEqual(NumericActivity.objects.get(id=a.id).group, True)

        # try with activity past due
        a.due_date = datetime.datetime.now() - datetime.timedelta(days=1)
        a.save()
        submit_dict['due_date_0'] = str(a.due_date.date())
        submit_dict['group'] = '0'
        response = client.post(url, submit_dict)
        self.assertEqual(
            response.status_code,
            200)  # error on form -> 200 and back to form with error
        self.assertContains(response, "due date has passed")

        # try with a mark in the system
        a.due_date = datetime.datetime.now() + datetime.timedelta(days=1)
        a.save()
        submit_dict['due_date_0'] = str(a.due_date.date())
        submit_dict['group'] = '0'
        g = NumericGrade(activity=a, member=m, value=2, flag="GRAD")
        g.save(entered_by='ggbaker')
        response = client.post(url, submit_dict)
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "grades have already been given")

        # try with a submission in the system
        g.flag = "NOGR"
        g.save(entered_by='ggbaker')
        s = StudentSubmission(activity=a, member=m)
        s.save()
        response = client.post(url, submit_dict)
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "submissions have already been made")
示例#42
0
 def test_replace_activity(self):
     """
     Can we safely replace an activity with one of the same name/shortname?
     """
     c = CourseOffering.objects.get(slug=self.course_slug)
     a = NumericActivity(offering=c, name="Assign1", short_name="A1", status="RLS", group=False, deleted=False, max_grade=10, position=1)
     a.save()
     
     a.safely_delete()
     self.assertEqual(a.deleted, True)
     self.assertNotEqual(a.name, 'Assign1')
     self.assertNotEqual(a.short_name, 'A1')
     
     # replace with same type
     a = CalNumericActivity(offering=c, name="Assign1", short_name="A1", status="URLS", group=True, deleted=False, max_grade=15, position=2)
     a.save()
     a.safely_delete()
     
     # replace with a different type
     a = LetterActivity(offering=c, name="Assign1", short_name="A1", status="RLS", group=False, deleted=False, position=3)
     a.save()
示例#43
0
    def test_upload(self):
        _, course = create_offering()
        a1 = NumericActivity(name="Assignment 1",
                             short_name="A1",
                             status="RLS",
                             offering=course,
                             position=2,
                             max_grade=15,
                             due_date=datetime.datetime.now() +
                             datetime.timedelta(hours=1),
                             group=False)
        a1.save()
        p = Person.objects.get(userid="ggbaker")
        member = Member(person=p,
                        offering=course,
                        role="INST",
                        career="NONS",
                        added_reason="UNK")
        member.save()
        c = Code.Component(activity=a1,
                           title="Code File",
                           position=3,
                           max_size=2000,
                           allowed=".py")
        c.save()

        userid1 = "0aaa0"
        userid2 = "0aaa1"
        userid3 = "0aaa2"
        for u in [userid1, userid2, userid3]:
            p = Person.objects.get(userid=u)
            m = Member(person=p,
                       offering=course,
                       role="STUD",
                       credits=3,
                       career="UGRD",
                       added_reason="UNK")
            m.save()

        # submit as student
        client = Client()
        client.login_user("0aaa0")
        url = reverse('offering:submission:show_components',
                      kwargs={
                          'course_slug': course.slug,
                          'activity_slug': a1.slug
                      })
        response = basic_page_tests(self, client, url)

        # submit a file
        tmpf = tempfile.NamedTemporaryFile(suffix=".py", delete=False)
        codecontents = 'print "Hello World!"\n'
        tmpf.write(codecontents)
        tmpf.close()

        try:
            fh = open(tmpf.name, "r")
            data = {"%i-code" % (c.id): fh}
            response = client.post(url, data)
            self.assertEquals(response.status_code, 302)

        finally:
            os.unlink(tmpf.name)

        # make sure it's there and correct
        subs = StudentSubmission.objects.all()
        self.assertEquals(len(subs), 1)
        sub = subs[0]
        self.assertEquals(sub.member.person.userid, '0aaa0')

        codes = SubmittedCode.objects.all()
        self.assertEquals(len(codes), 1)
        code = codes[0]
        code.code.open()
        self.assertEquals(code.code.read(), codecontents)