devilry.apps.core.testhelper — Create core test data¶
Deprecated since version 1.4: See How to unit-test Devilry.
Example¶
from devilry.apps.core.testhelper import TestHelper
testhelper = TestHelper()
testhelper.add(nodes='uni:admin(mortend)',
subjects=['cs101:admin(admin1,admin2):ln(Basic OO programming)',
'cs110:admin(admin3,admin4):ln(Basic scientific programming)',
'cs111:admin(admin1,damin3):ln(Advanced OO programming)'],
periods=['fall11', 'spring11:begins(6)'])
# add 4 assignments to inf101 and inf110 in fall and spring
testhelper.add(nodes='uni',
subjects=['cs101', 'cs110'],
periods=['fall11', 'spring11'],
assignments=['a1', 'a2'])
# add 12 assignments to inf111 fall and spring.
testhelper.add(nodes='uni',
subjects=['cs111'],
periods=['fall11', 'spring11'],
assignments=['week1', 'week2', 'week3', 'week4'])
# set up some students with descriptive names
# inf101 is so easy, everyone passes
testhelper.add_to_path('uni;cs101.fall11.a1.g1:candidate(goodStud1):examiner(examiner1).dl:ends(5)')
testhelper.add_to_path('uni;cs101.fall11.a1.g2:candidate(goodStud2):examiner(examiner1).dl:ends(5)')
testhelper.add_to_path('uni;cs101.fall11.a1.g3:candidate(badStud3):examiner(examiner2).dl:ends(5)')
testhelper.add_to_path('uni;cs101.fall11.a1.g4:candidate(okStud4):examiner(examiner2).dl:ends(5)')
testhelper.add_to_path('uni;cs101.fall11.a2.g1:candidate(goodStud1):examiner(examiner1).dl:ends(5)')
testhelper.add_to_path('uni;cs101.fall11.a2.g2:candidate(goodStud2):examiner(examiner1).dl:ends(5)')
testhelper.add_to_path('uni;cs101.fall11.a2.g3:candidate(badStud3):examiner(examiner2).dl:ends(5)')
testhelper.add_to_path('uni;cs101.fall11.a2.g4:candidate(okStud4):examiner(examiner2).dl:ends(5)')
# inf110 is an easy group-project, everyone passes
testhelper.add_to_path('uni;cs110.fall11.a1.g1:candidate(goodStud1,goodStud2):examiner(examiner1).dl:ends(14)')
testhelper.add_to_path('uni;cs110.fall11.a1.g2:candidate(badStud3,okStud4):examiner(examiner2).dl.ends(14)')
testhelper.add_to_path('uni;cs110.fall11.a2.g1:candidate(goodStud1,goodStud2):examiner(examiner1).dl:ends(14)')
testhelper.add_to_path('uni;cs110.fall11.a2.g2:candidate(badStud3,okStud4):examiner(examiner2).dl.ends(14)')
# inf111 is hard! Everyone passes week1
testhelper.add_to_path('uni;cs111.fall11.week1.g1:candidate(goodStud1):examiner(examiner3).dl:ends(5)')
testhelper.add_to_path('uni;cs111.fall11.week1.g2:candidate(goodStud2):examiner(examiner3).dl:ends(5)')
testhelper.add_to_path('uni;cs111.fall11.week1.g3:candidate(badStud3):examiner(examiner3).dl:ends(5)')
testhelper.add_to_path('uni;cs111.fall11.week1.g4:candidate(okStud4):examiner(examiner3).dl:ends(5)')
# and 2
testhelper.add_to_path('uni;cs111.fall11.week2.g1:candidate(goodStud1):examiner(examiner3).dl:ends(5)')
testhelper.add_to_path('uni;cs111.fall11.week2.g2:candidate(goodStud2):examiner(examiner3).dl:ends(5)')
testhelper.add_to_path('uni;cs111.fall11.week2.g3:candidate(badStud3):examiner(examiner3).dl:ends(5)')
testhelper.add_to_path('uni;cs111.fall11.week2.g4:candidate(okStud4):examiner(examiner3).dl:ends(5)')
# badStud4 fails at week3
testhelper.add_to_path('uni;cs111.fall11.week3.g1:candidate(goodStud1):examiner(examiner3).dl:ends(5)')
testhelper.add_to_path('uni;cs111.fall11.week3.g2:candidate(goodStud2):examiner(examiner3).dl:ends(5)')
testhelper.add_to_path('uni;cs111.fall11.week3.g4:candidate(okStud2):examiner(examiner3).dl:ends(5)')
# and okStud4 fails at week4
testhelper.add_to_path('uni;cs111.fall11.week4.g1:candidate(goodStud1):examiner(examiner3).dl:ends(5)')
testhelper.add_to_path('uni;cs111.fall11.week4.g2:candidate(goodStud2):examiner(examiner3).dl:ends(5)')
# deliveries
goodFile = {'good.py': ['print ', 'awesome']}
okFile = {'ok.py': ['print ', 'meh']}
badFile = {'bad.py': ['print ', 'bah']}
# cs101
testhelper.add_delivery('cs101.fall11.a1.g1', goodFile)
testhelper.add_delivery('cs101.fall11.a1.g2', goodFile)
testhelper.add_delivery('cs101.fall11.a1.g3', badFile)
testhelper.add_delivery('cs101.fall11.a1.g4', okFile)
testhelper.add_delivery('cs101.fall11.a2.g1', goodFile)
testhelper.add_delivery('cs101.fall11.a2.g2', goodFile)
testhelper.add_delivery('cs101.fall11.a2.g3', badFile)
testhelper.add_delivery('cs101.fall11.a2.g4', okFile)
# cs110
testhelper.add_delivery('cs110.fall11.a1.g1', goodFile)
testhelper.add_delivery('cs110.fall11.a1.g1', goodFile)
testhelper.add_delivery('cs110.fall11.a2.g2', badFile)
testhelper.add_delivery('cs110.fall11.a2.g2', okFile)
# cs111
testhelper.add_delivery('cs111.fall11.week1.g1', goodFile)
testhelper.add_delivery('cs111.fall11.week1.g2', goodFile)
testhelper.add_delivery('cs111.fall11.week1.g3', badFile)
testhelper.add_delivery('cs111.fall11.week1.g4', okFile)
# g3's delivery fails here
testhelper.add_delivery('cs111.fall11.week2.g1', goodFile)
testhelper.add_delivery('cs111.fall11.week2.g2', goodFile)
testhelper.add_delivery('cs111.fall11.week2.g3', badFile)
testhelper.add_delivery('cs111.fall11.week2.g4', okFile)
# g4's delivery fails here
testhelper.add_delivery('cs111.fall11.week3.g1', goodFile)
testhelper.add_delivery('cs111.fall11.week3.g2', goodFile)
testhelper.add_delivery('cs111.fall11.week3.g4', okFile)
# g4 fails
testhelper.add_delivery('cs111.fall11.week4.g1', goodFile)
testhelper.add_delivery('cs111.fall11.week4.g2', goodFile)
# feedbacks
# an empty verdict defaults to max score
goodVerdict = None
okVerdict = {'grade': 'C', 'points': 85, 'is_passing_grade': True}
badVerdict = {'grade': 'E', 'points': 60, 'is_passing_grade': True}
failVerdict = {'grade': 'F', 'points': 30, 'is_passing_grade': False}
testhelper.add_feedback('cs101.fall11.a1.g1', verdict=goodVerdict)
testhelper.add_feedback('cs101.fall11.a1.g2', verdict=goodVerdict)
testhelper.add_feedback('cs101.fall11.a1.g3', verdict=badVerdict)
testhelper.add_feedback('cs101.fall11.a1.g4', verdict=okVerdict)
testhelper.add_feedback('cs101.fall11.a2.g1', verdict=goodVerdict)
testhelper.add_feedback('cs101.fall11.a2.g2', verdict=goodVerdict)
testhelper.add_feedback('cs101.fall11.a2.g3', verdict=badVerdict)
testhelper.add_feedback('cs101.fall11.a2.g4', verdict=okVerdict)
# cs110
testhelper.add_feedback('cs110.fall11.a1.g1', verdict=goodVerdict)
testhelper.add_feedback('cs110.fall11.a1.g1', verdict=badVerdict)
testhelper.add_feedback('cs110.fall11.a2.g2', verdict=goodVerdict)
testhelper.add_feedback('cs110.fall11.a2.g2', verdict=okVerdict)
# cs111
testhelper.add_feedback('cs111.fall11.week1.g1', verdict=goodVerdict)
testhelper.add_feedback('cs111.fall11.week1.g2', verdict=goodVerdict)
testhelper.add_feedback('cs111.fall11.week1.g3', verdict=badVerdict)
testhelper.add_feedback('cs111.fall11.week1.g4', verdict=okVerdict)
# g3's feedback fails here
testhelper.add_feedback('cs111.fall11.week2.g1', verdict=goodVerdict)
testhelper.add_feedback('cs111.fall11.week2.g2', verdict=goodVerdict)
testhelper.add_feedback('cs111.fall11.week2.g3', verdict=failVerdict)
testhelper.add_feedback('cs111.fall11.week2.g4', verdict=okVerdict)
# g4's feedback fails here
testhelper.add_feedback('cs111.fall11.week3.g1', verdict=goodVerdict)
testhelper.add_feedback('cs111.fall11.week3.g2', verdict=goodVerdict)
testhelper.add_feedback('cs111.fall11.week3.g4', verdict=failVerdict)
# g4 fails
testhelper.add_feedback('cs111.fall11.week4.g1', verdict=goodVerdict)
testhelper.add_feedback('cs111.fall11.week4.g2', verdict=goodVerdict)
TestHelper API¶
-
class
devilry.apps.core.testhelper.
TestHelper
¶ Bases:
object
This class helps generate test data.
-
exception
IllegalTypeException
¶ Bases:
Exception
-
create_user
(name, fullname=None)¶ Create a user with the given username. Adds the user to
self.<name>
.Returns: The created user object.
-
reload_from_db
(obj)¶ Reload the given
django.db.Model
object from the database usingobj.__class__.get(pk=obj.pk)
. Updates the cache entry on this testhelper object if the object was created using this testhelper.Returns: The object that was re-loaded from the database.
-
create_superuser
(name)¶ Create a superuser with the given username. Adds the user to
self.<name>
.Returns: The created user object.
-
add_delivery
(assignmentgroup, files={}, after_last_deadline=False, delivered_by=None, successful=True, time_of_delivery=None)¶ Parameters: - assignmentgroup – Expects either an AssignmentGroup object or a string path to an assignmentgroup. This is a mandatory parameter.
- files – A dictionary with key/values as file name and file content as described in Delivery.add_file()
- after_last_deadline – If True, sets time_of_delivery 1 day later than the
assignmentgroups active deadline. Effectively the same as
setting
time_of_delivery=1
. Ignored itime_of_delivery
is used. - time_of_delivery – Set time_of_delivery to this number of days after the active deadline. Use a negative number to add a delivery before the active deadline. Can also be a datetime.datetime object that specifies an exact timestamp.
-
add_feedback
(delivery=None, verdict=None, examiner=None, timestamp=None, rendered_view='This is a default static feedback')¶ Parameters: - delivery – Either a Delivery object or a string path to an assignmentgroup, where we take the last delivery made. This is the only mandatory parameter
- verdict –
E dict containing grade, score and passing grade. Defaults to:
dict(grade='A', points=100, is_passing_grade=True)
- examiner – A User object. Defaults to the first examiner for the delivery’s assignment group.
- timestamp – A datetime object for when the feedback was saved. Defaults to same time the delivery was made
- rendered_view – The rendered view of the feedback. Defaults to
"This is a default static feedback"
.
-
add
(subjects=None, periods=None, assignments=None, assignmentgroups=None, deadlines=None)¶ Smart add.
Each attribute is normally just a list of names. The names are
short_name
, for nodeish types, and a virtual name for assignmentgroups, and deadlines.Names can be supplemented by extras, which are parameters that tunes the created items. Extras are separated by colon (
:
), and each extra has the following format:<name>(<args>)
Parameters: - subjects –
List of subjects. Extras:
- admin
- Comma-separated list of admins (usernames) to add to the node.
- ln
- Long name of the period. Defaults to capitalize short name.
- periods –
List of nodes. Extras:
- admin
- Comma-separated list of admins (usernames) to add to the node.
- ln
- Long name of the period. Defaults to capitalize short name.
- begins
- Number of months after now that the period begins. Can be a negative number. Defaults to now.
- ends
- Number of months after
begins
that the period ends. Can be a negative number. Defaults to6
.
- assignments –
List of assignments.
- admin
- Comma-separated list of admins (usernames) to add to the node.
- ln
- Long name of the period. Defaults to capitalize short name.
- anon
- Should the assignment be anonymous?
true
orfalse
, and defaults tofalse
. - pub
- Number of days after the start time of the period that the assignment should be published. Can be a negative number. Defaults to 0.
- delivery_types
electronic
ornonelectronic
.- first_deadline
- The offset of the
first_deadline
from thepublishing_time
in days. If this is0
, we automatically add1
second to thepublishing_time
to ensure that they are not equal.
- assignmentgroups –
List of assignmentgroups. Extras:
- candidate
- Comma-separated list of candidates (usernames) to add to the
group. Optionally, you can add a candidate_id by suffixing the
username with
;<candidate_id>
. Example:candidate(student0;2345,student1;5673)
- examiner
- Comma-separated list of examiners (usernames) to add to the group.
- deadlines –
List of deadlines. Extras:
- ends
- Number of days after the publishing_time of the deadline ends.
Can be a negative number. Defaults to
10
days. - text
- Deadline text.
- subjects –
-
get_object_from_path
(path)¶ Get a
Node
,Subject
,Period
,Assignment
,AssignmentGroup
,Deadline
,Delivery
orFeedback
that was added withadd()
,add_feedback()
,add_to_path()
, oradd_delivery()
.The path does not have to contain the node path (unless you are looking up a node), since subject shortnames are unique.
-
set_attributes_from_path
(path, **attributes)¶ Shortcut to
get_object_from_path()
, set the given attributes on the object, and callobj.save()
.
-
create_feedbacks
(*args)¶ Create feedbacks on groups from the given list of
(group, feedback, delivery)
-tuples.Parameters: args – Each item in the arguments list is a
(group, feedback[, delivery])
tuple where:group
- is the
devilry.apps.core.models.AssignmentGroup
-object that it to be given feedback feedbacks
- is a dict with attributes for the
devilry.apps.core.models.StaticFeedback
with the following keys:grade
- See
devilry.apps.core.models.StaticFeedback.grade
. points
- See
devilry.apps.core.models.StaticFeedback.points
. is_passing_grade
- See
devilry.apps.core.models.StaticFeedback.is_passing_grade
.
delivery
- Is an optional dict of files to make a delivery from. Defaults to:
{'test.py': ['print ', 'tst']}
A delivery to save the feedback on is created automatically, so all that is needed of the groups is an examiner, a candidate and a deadline.
Example
self.create_feedbacks( (group1, {'grade': 'B', 'points': 86, 'is_passing_grade': True}), (group2, {'grade': 'A', 'points': 96, 'is_passing_grade': True}, {'hello.txt', ['Hello']}), (group3, {'grade': 'F', 'points': 12, 'is_passing_grade': False}) )
-
exception