devilry.apps.core.testhelper — Create core test data¶
Deprecated since version 1.4: Use corebuilder — Setup devilry core data structures for tests instead.
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.
- 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 using obj.__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 i time_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(nodes=None, 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: - nodes –
List of nodes.
- admin
- Comma-separated list of admins (usernames) to add to the node.
- ln
- Long name of the period. Defaults to capitalize short name.
- 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 to 6.
- 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 or false, and defaults to false.
- 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 or nonelectronic.
- first_deadline
- The offset of the first_deadline from the publishing_time in days. If this is 0, we automatically add 1 second to the publishing_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.
- nodes –
- get_object_from_path(path)¶
Get a Node, Subject, Period, Assignment, AssignmentGroup, Deadline, Delivery or Feedback that was added with add(), add_feedback(), add_to_path(), or add_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 call obj.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}) )