Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
07fb1645
Commit
07fb1645
authored
May 06, 2016
by
Clinton Blackburn
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #12381 from edx/clintonb/credit-fix
Multiple Credit Fixes
parents
16213573
bcd762ef
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
145 additions
and
71 deletions
+145
-71
openedx/core/djangoapps/credit/admin.py
+21
-1
openedx/core/djangoapps/credit/api/eligibility.py
+19
-14
openedx/core/djangoapps/credit/models.py
+3
-0
openedx/core/djangoapps/credit/signals.py
+37
-12
openedx/core/djangoapps/credit/tests/test_api.py
+32
-19
openedx/core/djangoapps/credit/tests/test_signals.py
+33
-25
No files found.
openedx/core/djangoapps/credit/admin.py
View file @
07fb1645
...
@@ -2,8 +2,10 @@
...
@@ -2,8 +2,10 @@
Django admin page for credit eligibility
Django admin page for credit eligibility
"""
"""
from
ratelimitbackend
import
admin
from
ratelimitbackend
import
admin
from
openedx.core.djangoapps.credit.models
import
(
from
openedx.core.djangoapps.credit.models
import
(
CreditConfig
,
CreditCourse
,
CreditProvider
,
CreditEligibility
,
CreditRequest
CreditConfig
,
CreditCourse
,
CreditProvider
,
CreditEligibility
,
CreditRequest
,
CreditRequirement
,
CreditRequirementStatus
)
)
...
@@ -47,8 +49,26 @@ class CreditRequestAdmin(admin.ModelAdmin):
...
@@ -47,8 +49,26 @@ class CreditRequestAdmin(admin.ModelAdmin):
model
=
CreditRequest
model
=
CreditRequest
class
CreditRequirementAdmin
(
admin
.
ModelAdmin
):
""" Admin for CreditRequirement. """
list_display
=
(
'course'
,
'namespace'
,
'name'
,
'display_name'
,
'active'
,)
class
Meta
(
object
):
model
=
CreditRequirement
class
CreditRequirementStatusAdmin
(
admin
.
ModelAdmin
):
""" Admin for CreditRequirementStatus. """
list_display
=
(
'username'
,
'requirement'
,
'status'
,)
class
Meta
(
object
):
model
=
CreditRequirementStatus
admin
.
site
.
register
(
CreditCourse
,
CreditCourseAdmin
)
admin
.
site
.
register
(
CreditCourse
,
CreditCourseAdmin
)
admin
.
site
.
register
(
CreditProvider
,
CreditProviderAdmin
)
admin
.
site
.
register
(
CreditProvider
,
CreditProviderAdmin
)
admin
.
site
.
register
(
CreditEligibility
,
CreditEligibilityAdmin
)
admin
.
site
.
register
(
CreditEligibility
,
CreditEligibilityAdmin
)
admin
.
site
.
register
(
CreditRequest
,
CreditRequestAdmin
)
admin
.
site
.
register
(
CreditRequest
,
CreditRequestAdmin
)
admin
.
site
.
register
(
CreditConfig
)
admin
.
site
.
register
(
CreditConfig
)
admin
.
site
.
register
(
CreditRequirement
,
CreditRequirementAdmin
)
admin
.
site
.
register
(
CreditRequirementStatus
,
CreditRequirementStatusAdmin
)
openedx/core/djangoapps/credit/api/eligibility.py
View file @
07fb1645
...
@@ -7,13 +7,10 @@ import logging
...
@@ -7,13 +7,10 @@ import logging
from
opaque_keys.edx.keys
import
CourseKey
from
opaque_keys.edx.keys
import
CourseKey
from
openedx.core.djangoapps.credit.exceptions
import
InvalidCreditRequirements
,
InvalidCreditCourse
from
openedx.core.djangoapps.credit.email_utils
import
send_credit_notifications
from
openedx.core.djangoapps.credit.email_utils
import
send_credit_notifications
from
openedx.core.djangoapps.credit.exceptions
import
InvalidCreditRequirements
,
InvalidCreditCourse
from
openedx.core.djangoapps.credit.models
import
(
from
openedx.core.djangoapps.credit.models
import
(
CreditCourse
,
CreditCourse
,
CreditRequirement
,
CreditRequirementStatus
,
CreditEligibility
,
CreditRequest
CreditRequirement
,
CreditRequirementStatus
,
CreditEligibility
,
)
)
# TODO: Cleanup this mess! ECOM-2908
# TODO: Cleanup this mess! ECOM-2908
...
@@ -228,13 +225,21 @@ def set_credit_requirement_status(username, course_key, req_namespace, req_name,
...
@@ -228,13 +225,21 @@ def set_credit_requirement_status(username, course_key, req_namespace, req_name,
)
)
"""
"""
# Check if we're already eligible for credit.
# Do not allow students who have requested credit to change their eligibility
# If so, short-circuit this process.
if
CreditRequest
.
get_user_request_status
(
username
,
course_key
):
if
CreditEligibility
.
is_user_eligible_for_credit
(
course_key
,
username
):
log
.
info
(
u'Refusing to set status of requirement with namespace "
%
s" and name "
%
s" because the '
u'user "
%
s" has already requested credit for the course "
%
s".'
,
req_namespace
,
req_name
,
username
,
course_key
)
return
# Do not allow a student who has earned eligibility to un-earn eligibility
eligible_before_update
=
CreditEligibility
.
is_user_eligible_for_credit
(
course_key
,
username
)
if
eligible_before_update
and
status
==
'failed'
:
log
.
info
(
log
.
info
(
u'Skipping update of credit requirement with namespace "
%
s" '
u'Refusing to set status of requirement with namespace "
%
s" and name "
%
s" to "failed" because the '
u'and name "
%
s" because the user "
%
s" is already eligible for credit '
u'user "
%
s" is already eligible for credit in the course "
%
s".'
,
u'in the course "
%
s".'
,
req_namespace
,
req_name
,
username
,
course_key
req_namespace
,
req_name
,
username
,
course_key
)
)
return
return
...
@@ -273,9 +278,9 @@ def set_credit_requirement_status(username, course_key, req_namespace, req_name,
...
@@ -273,9 +278,9 @@ def set_credit_requirement_status(username, course_key, req_namespace, req_name,
username
,
req_to_update
,
status
=
status
,
reason
=
reason
username
,
req_to_update
,
status
=
status
,
reason
=
reason
)
)
# If we're marking this requirement as "satisfied", there's a chance
# If we're marking this requirement as "satisfied", there's a chance
that the user has met all eligibility
#
that the user has met all eligibility requirements
.
#
requirements, and should be notified. However, if the user was already eligible, do not send another notification
.
if
status
==
"satisfied"
:
if
status
==
"satisfied"
and
not
eligible_before_update
:
is_eligible
,
eligibility_record_created
=
CreditEligibility
.
update_eligibility
(
reqs
,
username
,
course_key
)
is_eligible
,
eligibility_record_created
=
CreditEligibility
.
update_eligibility
(
reqs
,
username
,
course_key
)
if
eligibility_record_created
and
is_eligible
:
if
eligibility_record_created
and
is_eligible
:
try
:
try
:
...
...
openedx/core/djangoapps/credit/models.py
View file @
07fb1645
...
@@ -294,6 +294,9 @@ class CreditRequirement(TimeStampedModel):
...
@@ -294,6 +294,9 @@ class CreditRequirement(TimeStampedModel):
unique_together
=
(
'namespace'
,
'name'
,
'course'
)
unique_together
=
(
'namespace'
,
'name'
,
'course'
)
ordering
=
[
"order"
]
ordering
=
[
"order"
]
def
__unicode__
(
self
):
return
self
.
display_name
@classmethod
@classmethod
def
add_or_update_course_requirement
(
cls
,
credit_course
,
requirement
,
order
):
def
add_or_update_course_requirement
(
cls
,
credit_course
,
requirement
,
order
):
"""
"""
...
...
openedx/core/djangoapps/credit/signals.py
View file @
07fb1645
...
@@ -7,11 +7,10 @@ import logging
...
@@ -7,11 +7,10 @@ import logging
from
django.dispatch
import
receiver
from
django.dispatch
import
receiver
from
django.utils
import
timezone
from
django.utils
import
timezone
from
opaque_keys.edx.keys
import
CourseKey
from
opaque_keys.edx.keys
import
CourseKey
from
openedx.core.djangoapps.signals.signals
import
GRADES_UPDATED
from
openedx.core.djangoapps.credit.verification_access
import
update_verification_partitions
from
xmodule.modulestore.django
import
SignalHandler
from
xmodule.modulestore.django
import
SignalHandler
from
openedx.core.djangoapps.credit.verification_access
import
update_verification_partitions
from
openedx.core.djangoapps.signals.signals
import
GRADES_UPDATED
log
=
logging
.
getLogger
(
__name__
)
log
=
logging
.
getLogger
(
__name__
)
...
@@ -55,8 +54,7 @@ def on_pre_publish(sender, course_key, **kwargs): # pylint: disable=unused-argu
...
@@ -55,8 +54,7 @@ def on_pre_publish(sender, course_key, **kwargs): # pylint: disable=unused-argu
@receiver
(
GRADES_UPDATED
)
@receiver
(
GRADES_UPDATED
)
def
listen_for_grade_calculation
(
sender
,
username
,
grade_summary
,
course_key
,
deadline
,
**
kwargs
):
# pylint: disable=unused-argument
def
listen_for_grade_calculation
(
sender
,
username
,
grade_summary
,
course_key
,
deadline
,
**
kwargs
):
# pylint: disable=unused-argument
"""Receive 'MIN_GRADE_REQUIREMENT_STATUS' signal and update minimum grade
"""Receive 'MIN_GRADE_REQUIREMENT_STATUS' signal and update minimum grade requirement status.
requirement status.
Args:
Args:
sender: None
sender: None
...
@@ -81,12 +79,39 @@ def listen_for_grade_calculation(sender, username, grade_summary, course_key, de
...
@@ -81,12 +79,39 @@ def listen_for_grade_calculation(sender, username, grade_summary, course_key, de
criteria
=
requirements
[
0
]
.
get
(
'criteria'
)
criteria
=
requirements
[
0
]
.
get
(
'criteria'
)
if
criteria
:
if
criteria
:
min_grade
=
criteria
.
get
(
'min_grade'
)
min_grade
=
criteria
.
get
(
'min_grade'
)
if
grade_summary
[
'percent'
]
>=
min_grade
:
passing_grade
=
grade_summary
[
'percent'
]
>=
min_grade
reason_dict
=
{
'final_grade'
:
grade_summary
[
'percent'
]}
now
=
timezone
.
now
()
api
.
set_credit_requirement_status
(
status
=
None
username
,
course_id
,
'grade'
,
'grade'
,
status
=
"satisfied"
,
reason
=
reason_dict
reason
=
None
)
elif
deadline
and
deadline
<
timezone
.
now
():
if
(
deadline
and
now
<
deadline
)
or
not
deadline
:
# Student completed coursework on-time
if
passing_grade
:
# Student received a passing grade
status
=
'satisfied'
reason
=
{
'final_grade'
:
grade_summary
[
'percent'
]}
else
:
# Submission after deadline
if
passing_grade
:
# Grade was good, but submission arrived too late
status
=
'failed'
reason
=
{
'current_date'
:
now
,
'deadline'
:
deadline
}
else
:
# Student failed to receive minimum grade
status
=
'failed'
reason
=
{
'final_grade'
:
grade_summary
[
'percent'
],
'minimum_grade'
:
min_grade
}
# We do not record a status if the user has not yet earned the minimum grade, but still has
# time to do so.
if
status
and
reason
:
api
.
set_credit_requirement_status
(
api
.
set_credit_requirement_status
(
username
,
course_id
,
'grade'
,
'grade'
,
status
=
"failed"
,
reason
=
{}
username
,
course_id
,
'grade'
,
'grade'
,
status
=
status
,
reason
=
reason
)
)
openedx/core/djangoapps/credit/tests/test_api.py
View file @
07fb1645
...
@@ -33,7 +33,8 @@ from openedx.core.djangoapps.credit.models import (
...
@@ -33,7 +33,8 @@ from openedx.core.djangoapps.credit.models import (
CreditProvider
,
CreditProvider
,
CreditRequirement
,
CreditRequirement
,
CreditRequirementStatus
,
CreditRequirementStatus
,
CreditEligibility
CreditEligibility
,
CreditRequest
)
)
from
student.tests.factories
import
UserFactory
from
student.tests.factories
import
UserFactory
from
util.date_utils
import
from_timestamp
from
util.date_utils
import
from_timestamp
...
@@ -371,8 +372,16 @@ class CreditRequirementApiTests(CreditApiTestBase):
...
@@ -371,8 +372,16 @@ class CreditRequirementApiTests(CreditApiTestBase):
eligibilities
=
api
.
get_eligibilities_for_user
(
"staff"
)
eligibilities
=
api
.
get_eligibilities_for_user
(
"staff"
)
self
.
assertEqual
(
eligibilities
,
[])
self
.
assertEqual
(
eligibilities
,
[])
def
assert_grade_requirement_status
(
self
,
expected_status
,
expected_order
):
""" Assert the status and order of the grade requirement. """
req_status
=
api
.
get_credit_requirement_status
(
self
.
course_key
,
'staff'
,
namespace
=
"grade"
,
name
=
"grade"
)
self
.
assertEqual
(
req_status
[
0
][
"status"
],
expected_status
)
self
.
assertEqual
(
req_status
[
0
][
"order"
],
expected_order
)
return
req_status
def
test_set_credit_requirement_status
(
self
):
def
test_set_credit_requirement_status
(
self
):
self
.
add_credit_course
()
username
=
"staff"
credit_course
=
self
.
add_credit_course
()
requirements
=
[
requirements
=
[
{
{
"namespace"
:
"grade"
,
"namespace"
:
"grade"
,
...
@@ -395,40 +404,44 @@ class CreditRequirementApiTests(CreditApiTestBase):
...
@@ -395,40 +404,44 @@ class CreditRequirementApiTests(CreditApiTestBase):
self
.
assertEqual
(
len
(
course_requirements
),
2
)
self
.
assertEqual
(
len
(
course_requirements
),
2
)
# Initially, the status should be None
# Initially, the status should be None
req_status
=
api
.
get_credit_requirement_status
(
self
.
course_key
,
"staff"
,
namespace
=
"grade"
,
name
=
"grade"
)
self
.
assert_grade_requirement_status
(
None
,
0
)
self
.
assertEqual
(
req_status
[
0
][
"status"
],
None
)
self
.
assertEqual
(
req_status
[
0
][
"order"
],
0
)
# Requirement statuses cannot be changed if a CreditRequest exists
credit_request
=
CreditRequest
.
objects
.
create
(
course
=
credit_course
,
provider
=
CreditProvider
.
objects
.
first
(),
username
=
username
,
)
api
.
set_credit_requirement_status
(
username
,
self
.
course_key
,
"grade"
,
"grade"
)
self
.
assert_grade_requirement_status
(
None
,
0
)
credit_request
.
delete
()
# Set the requirement to "satisfied" and check that it's actually set
# Set the requirement to "satisfied" and check that it's actually set
api
.
set_credit_requirement_status
(
"staff"
,
self
.
course_key
,
"grade"
,
"grade"
)
api
.
set_credit_requirement_status
(
username
,
self
.
course_key
,
"grade"
,
"grade"
)
req_status
=
api
.
get_credit_requirement_status
(
self
.
course_key
,
"staff"
,
namespace
=
"grade"
,
name
=
"grade"
)
self
.
assert_grade_requirement_status
(
'satisfied'
,
0
)
self
.
assertEqual
(
req_status
[
0
][
"status"
],
"satisfied"
)
self
.
assertEqual
(
req_status
[
0
][
"order"
],
0
)
# Set the requirement to "failed" and check that it's actually set
# Set the requirement to "failed" and check that it's actually set
api
.
set_credit_requirement_status
(
"staff"
,
self
.
course_key
,
"grade"
,
"grade"
,
status
=
"failed"
)
api
.
set_credit_requirement_status
(
username
,
self
.
course_key
,
"grade"
,
"grade"
,
status
=
"failed"
)
req_status
=
api
.
get_credit_requirement_status
(
self
.
course_key
,
"staff"
,
namespace
=
"grade"
,
name
=
"grade"
)
self
.
assert_grade_requirement_status
(
'failed'
,
0
)
self
.
assertEqual
(
req_status
[
0
][
"status"
],
"failed"
)
self
.
assertEqual
(
req_status
[
0
][
"order"
],
0
)
req_status
=
api
.
get_credit_requirement_status
(
self
.
course_key
,
"staff"
)
req_status
=
api
.
get_credit_requirement_status
(
self
.
course_key
,
"staff"
)
self
.
assertEqual
(
req_status
[
0
][
"status"
],
"failed"
)
self
.
assertEqual
(
req_status
[
0
][
"status"
],
"failed"
)
self
.
assertEqual
(
req_status
[
0
][
"order"
],
0
)
self
.
assertEqual
(
req_status
[
0
][
"order"
],
0
)
# make sure the 'order' on the 2nd requi
emtn
is set correctly (aka 1)
# make sure the 'order' on the 2nd requi
rement
is set correctly (aka 1)
self
.
assertEqual
(
req_status
[
1
][
"status"
],
None
)
self
.
assertEqual
(
req_status
[
1
][
"status"
],
None
)
self
.
assertEqual
(
req_status
[
1
][
"order"
],
1
)
self
.
assertEqual
(
req_status
[
1
][
"order"
],
1
)
# Set the requirement to "declined" and check that it's actually set
# Set the requirement to "declined" and check that it's actually set
api
.
set_credit_requirement_status
(
api
.
set_credit_requirement_status
(
"staff"
,
self
.
course_key
,
username
,
self
.
course_key
,
"reverification"
,
"reverification"
,
"i4x://edX/DemoX/edx-reverification-block/assessment_uuid"
,
"i4x://edX/DemoX/edx-reverification-block/assessment_uuid"
,
status
=
"declined"
status
=
"declined"
)
)
req_status
=
api
.
get_credit_requirement_status
(
req_status
=
api
.
get_credit_requirement_status
(
self
.
course_key
,
self
.
course_key
,
"staff"
,
username
,
namespace
=
"reverification"
,
namespace
=
"reverification"
,
name
=
"i4x://edX/DemoX/edx-reverification-block/assessment_uuid"
name
=
"i4x://edX/DemoX/edx-reverification-block/assessment_uuid"
)
)
...
@@ -530,7 +543,7 @@ class CreditRequirementApiTests(CreditApiTestBase):
...
@@ -530,7 +543,7 @@ class CreditRequirementApiTests(CreditApiTestBase):
user
=
UserFactory
.
create
(
username
=
self
.
USER_INFO
[
'username'
],
password
=
self
.
USER_INFO
[
'password'
])
user
=
UserFactory
.
create
(
username
=
self
.
USER_INFO
[
'username'
],
password
=
self
.
USER_INFO
[
'password'
])
# Satisfy one of the requirements, but not the other
# Satisfy one of the requirements, but not the other
with
self
.
assertNumQueries
(
1
1
):
with
self
.
assertNumQueries
(
1
2
):
api
.
set_credit_requirement_status
(
api
.
set_credit_requirement_status
(
user
.
username
,
user
.
username
,
self
.
course_key
,
self
.
course_key
,
...
@@ -542,7 +555,7 @@ class CreditRequirementApiTests(CreditApiTestBase):
...
@@ -542,7 +555,7 @@ class CreditRequirementApiTests(CreditApiTestBase):
self
.
assertFalse
(
api
.
is_user_eligible_for_credit
(
"bob"
,
self
.
course_key
))
self
.
assertFalse
(
api
.
is_user_eligible_for_credit
(
"bob"
,
self
.
course_key
))
# Satisfy the other requirement
# Satisfy the other requirement
with
self
.
assertNumQueries
(
19
):
with
self
.
assertNumQueries
(
20
):
api
.
set_credit_requirement_status
(
api
.
set_credit_requirement_status
(
"bob"
,
"bob"
,
self
.
course_key
,
self
.
course_key
,
...
@@ -596,7 +609,7 @@ class CreditRequirementApiTests(CreditApiTestBase):
...
@@ -596,7 +609,7 @@ class CreditRequirementApiTests(CreditApiTestBase):
# Delete the eligibility entries and satisfy the user's eligibility
# Delete the eligibility entries and satisfy the user's eligibility
# requirement again to trigger eligibility notification
# requirement again to trigger eligibility notification
CreditEligibility
.
objects
.
all
()
.
delete
()
CreditEligibility
.
objects
.
all
()
.
delete
()
with
self
.
assertNumQueries
(
1
5
):
with
self
.
assertNumQueries
(
1
6
):
api
.
set_credit_requirement_status
(
api
.
set_credit_requirement_status
(
"bob"
,
"bob"
,
self
.
course_key
,
self
.
course_key
,
...
...
openedx/core/djangoapps/credit/tests/test_signals.py
View file @
07fb1645
...
@@ -2,24 +2,23 @@
...
@@ -2,24 +2,23 @@
Tests for minimum grade requirement status
Tests for minimum grade requirement status
"""
"""
import
pytz
import
ddt
import
ddt
import
pytz
from
datetime
import
timedelta
,
datetime
from
datetime
import
timedelta
,
datetime
from
nose.plugins.attrib
import
attr
from
unittest
import
skipUnless
from
django.conf
import
settings
from
django.conf
import
settings
from
django.test.client
import
RequestFactory
from
django.test.client
import
RequestFactory
from
unittest
import
skipUnless
from
nose.plugins.attrib
import
attr
from
student.tests.factories
import
UserFactory
from
xmodule.modulestore.tests.django_utils
import
ModuleStoreTestCase
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
openedx.core.djangoapps.credit.api
import
(
from
openedx.core.djangoapps.credit.api
import
(
set_credit_requirements
,
get_credit_requirement_status
set_credit_requirements
,
get_credit_requirement_status
)
)
from
openedx.core.djangoapps.credit.models
import
CreditCourse
,
CreditProvider
from
openedx.core.djangoapps.credit.models
import
CreditCourse
,
CreditProvider
from
openedx.core.djangoapps.credit.signals
import
listen_for_grade_calculation
from
openedx.core.djangoapps.credit.signals
import
listen_for_grade_calculation
from
student.tests.factories
import
UserFactory
from
xmodule.modulestore.tests.django_utils
import
ModuleStoreTestCase
from
xmodule.modulestore.tests.factories
import
CourseFactory
@attr
(
'shard_2'
)
@attr
(
'shard_2'
)
...
@@ -67,20 +66,35 @@ class TestMinGradedRequirementStatus(ModuleStoreTestCase):
...
@@ -67,20 +66,35 @@ class TestMinGradedRequirementStatus(ModuleStoreTestCase):
# Add a single credit requirement (final grade)
# Add a single credit requirement (final grade)
set_credit_requirements
(
self
.
course
.
id
,
requirements
)
set_credit_requirements
(
self
.
course
.
id
,
requirements
)
def
assert_requirement_status
(
self
,
grade
,
due_date
,
expected_status
):
""" Verify the user's credit requirement status is as expected after simulating a grading calculation. """
listen_for_grade_calculation
(
None
,
self
.
user
.
username
,
{
'percent'
:
grade
},
self
.
course
.
id
,
due_date
)
req_status
=
get_credit_requirement_status
(
self
.
course
.
id
,
self
.
request
.
user
.
username
,
'grade'
,
'grade'
)
self
.
assertEqual
(
req_status
[
0
][
'status'
],
expected_status
)
if
expected_status
==
'satisfied'
:
expected_reason
=
{
'final_grade'
:
grade
}
self
.
assertEqual
(
req_status
[
0
][
'reason'
],
expected_reason
)
@ddt.data
(
@ddt.data
(
(
0.6
,
VALID_DUE_DATE
),
(
0.6
,
VALID_DUE_DATE
),
(
0.52
,
VALID_DUE_DATE
),
(
0.52
,
None
),
(
0.70
,
EXPIRED_DUE_DATE
),
)
)
@ddt.unpack
@ddt.unpack
def
test_min_grade_requirement_with_valid_grade
(
self
,
grade_achieved
,
due_date
):
def
test_min_grade_requirement_with_valid_grade
(
self
,
grade
,
due_date
):
"""Test with valid grades. Deadline date does not effect in case
"""Test with valid grades submitted before deadline"""
of valid grade.
self
.
assert_requirement_status
(
grade
,
due_date
,
'satisfied'
)
"""
listen_for_grade_calculation
(
None
,
self
.
user
.
username
,
{
'percent'
:
grade_achieved
},
self
.
course
.
id
,
due_date
)
def
test_grade_changed
(
self
):
req_status
=
get_credit_requirement_status
(
self
.
course
.
id
,
self
.
request
.
user
.
username
,
'grade'
,
'grade'
)
""" Verify successive calls to update a satisfied grade requirement are recorded. """
self
.
assertEqual
(
req_status
[
0
][
"status"
],
'satisfied'
)
self
.
assert_requirement_status
(
0.6
,
self
.
VALID_DUE_DATE
,
'satisfied'
)
self
.
assert_requirement_status
(
0.75
,
self
.
VALID_DUE_DATE
,
'satisfied'
)
self
.
assert_requirement_status
(
0.70
,
self
.
VALID_DUE_DATE
,
'satisfied'
)
def
test_min_grade_requirement_with_valid_grade_and_expired_deadline
(
self
):
""" Verify the status is set to failure if a passing grade is received past the submission deadline. """
self
.
assert_requirement_status
(
0.70
,
self
.
EXPIRED_DUE_DATE
,
'failed'
)
@ddt.data
(
@ddt.data
(
(
0.50
,
None
),
(
0.50
,
None
),
...
@@ -88,16 +102,10 @@ class TestMinGradedRequirementStatus(ModuleStoreTestCase):
...
@@ -88,16 +102,10 @@ class TestMinGradedRequirementStatus(ModuleStoreTestCase):
(
0.40
,
VALID_DUE_DATE
),
(
0.40
,
VALID_DUE_DATE
),
)
)
@ddt.unpack
@ddt.unpack
def
test_min_grade_requirement_failed_grade_valid_deadline
(
self
,
grade
_achieved
,
due_date
):
def
test_min_grade_requirement_failed_grade_valid_deadline
(
self
,
grade
,
due_date
):
"""Test with failed grades and deadline is still open or not defined."""
"""Test with failed grades and deadline is still open or not defined."""
self
.
assert_requirement_status
(
grade
,
due_date
,
None
)
listen_for_grade_calculation
(
None
,
self
.
user
.
username
,
{
'percent'
:
grade_achieved
},
self
.
course
.
id
,
due_date
)
req_status
=
get_credit_requirement_status
(
self
.
course
.
id
,
self
.
request
.
user
.
username
,
'grade'
,
'grade'
)
self
.
assertEqual
(
req_status
[
0
][
"status"
],
None
)
def
test_min_grade_requirement_failed_grade_expired_deadline
(
self
):
def
test_min_grade_requirement_failed_grade_expired_deadline
(
self
):
"""Test with failed grades and deadline expire"""
"""Test with failed grades and deadline expire"""
self
.
assert_requirement_status
(
0.22
,
self
.
EXPIRED_DUE_DATE
,
'failed'
)
listen_for_grade_calculation
(
None
,
self
.
user
.
username
,
{
'percent'
:
0.22
},
self
.
course
.
id
,
self
.
EXPIRED_DUE_DATE
)
req_status
=
get_credit_requirement_status
(
self
.
course
.
id
,
self
.
request
.
user
.
username
,
'grade'
,
'grade'
)
self
.
assertEqual
(
req_status
[
0
][
"status"
],
'failed'
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment