Skip to content

Commit

Permalink
Added new test description and feedback fields.
Browse files Browse the repository at this point in the history
  • Loading branch information
James Perretta committed Aug 6, 2024
1 parent 224aae3 commit 46b78e6
Show file tree
Hide file tree
Showing 9 changed files with 194 additions and 20 deletions.
48 changes: 48 additions & 0 deletions autograder/core/migrations/0106_test_descriptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Generated by Django 3.2.2 on 2024-08-05 21:52

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('core', '0105_tz_validation_update'),
]

operations = [
migrations.AddField(
model_name='agtestcase',
name='staff_description',
field=models.TextField(blank=True, help_text='Text description shown only to staff. Rendered as markdown.'),
),
migrations.AddField(
model_name='agtestcase',
name='student_description',
field=models.TextField(blank=True, help_text='Text description shown to students. Rendered as markdown.'),
),
migrations.AddField(
model_name='agtestcommand',
name='staff_description',
field=models.TextField(blank=True, help_text='Text description shown only to staff. Rendered as markdown.'),
),
migrations.AddField(
model_name='agtestcommand',
name='student_description',
field=models.TextField(blank=True, help_text='Text description shown to students. Rendered as markdown.'),
),
migrations.AddField(
model_name='agtestcommand',
name='student_on_fail_description',
field=models.TextField(blank=True, help_text='Additional text shown to students failing this test. Rendered as markdown.'),
),
migrations.AddField(
model_name='agtestsuite',
name='staff_description',
field=models.TextField(blank=True, help_text='Text description shown only to staff. Rendered as markdown.'),
),
migrations.AddField(
model_name='agtestsuite',
name='student_description',
field=models.TextField(blank=True, help_text='Text description shown to students. Rendered as markdown.'),
),
]
26 changes: 23 additions & 3 deletions autograder/core/models/ag_test/ag_test_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,21 @@ class AGTestCaseFeedbackConfig(DictSerializable):
"""
Contains feedback options for an AGTestCase.
"""
def __init__(self, visible: bool = True, show_individual_commands: bool = True):
def __init__(
self,
visible: bool = True,
show_individual_commands: bool = True,
show_student_description: bool = True,
):
self.visible = visible
self.show_individual_commands = show_individual_commands
self.show_student_description = show_student_description

SERIALIZABLE_FIELDS = ('visible', 'show_individual_commands', 'show_student_description',)

SERIALIZABLE_FIELDS = ('visible', 'show_individual_commands',)

def _past_limit_fdbk() -> AGTestCaseFeedbackConfig:
return AGTestCaseFeedbackConfig(show_student_description=False)


class AGTestCase(AutograderModel):
Expand Down Expand Up @@ -46,12 +56,22 @@ class Meta:
help_text='''The suite this autograder test belongs to.
This field is REQUIRED.''')

staff_description = models.TextField(
blank=True,
help_text='Text description shown only to staff. Rendered as markdown.'
)

student_description = models.TextField(
blank=True,
help_text='Text description shown to students. Rendered as markdown.'
)

normal_fdbk_config = ag_fields.ValidatedJSONField(
AGTestCaseFeedbackConfig, default=AGTestCaseFeedbackConfig)
ultimate_submission_fdbk_config = ag_fields.ValidatedJSONField(
AGTestCaseFeedbackConfig, default=AGTestCaseFeedbackConfig)
past_limit_submission_fdbk_config = ag_fields.ValidatedJSONField(
AGTestCaseFeedbackConfig, default=AGTestCaseFeedbackConfig)
AGTestCaseFeedbackConfig, default=_past_limit_fdbk)
staff_viewer_fdbk_config = ag_fields.ValidatedJSONField(
AGTestCaseFeedbackConfig, default=AGTestCaseFeedbackConfig)

Expand Down
25 changes: 23 additions & 2 deletions autograder/core/models/ag_test/ag_test_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ def __init__(self,
show_actual_return_code: bool = False,
show_actual_stdout: bool = False,
show_actual_stderr: bool = False,
show_whether_timed_out: bool = False):
show_whether_timed_out: bool = False,
show_student_description: bool = False):
self.visible = visible

self.return_code_fdbk_level = return_code_fdbk_level
Expand All @@ -50,6 +51,8 @@ def __init__(self,

self.show_whether_timed_out = show_whether_timed_out

self.show_student_description = show_student_description

@classmethod
def default_ultimate_submission_fdbk_config(cls) -> AGTestCommandFeedbackConfig:
return AGTestCommandFeedbackConfig(
Expand All @@ -60,7 +63,8 @@ def default_ultimate_submission_fdbk_config(cls) -> AGTestCommandFeedbackConfig:
show_actual_return_code=True,
show_actual_stdout=False,
show_actual_stderr=False,
show_whether_timed_out=True
show_whether_timed_out=True,
show_student_description=True,
)

@classmethod
Expand Down Expand Up @@ -90,6 +94,7 @@ def max_fdbk_config(cls) -> AGTestCommandFeedbackConfig:
'show_actual_stdout',
'show_actual_stderr',
'show_whether_timed_out',
'show_student_description',
)


Expand Down Expand Up @@ -150,6 +155,22 @@ class Meta:
on_delete=models.CASCADE,
help_text="""The AGTestCase that this command belongs to.""")

staff_description = models.TextField(
blank=True,
help_text='Text description shown only to staff. Rendered as markdown.'
)

student_description = models.TextField(
blank=True,
help_text='Text description shown to students. Rendered as markdown.'
)

student_on_fail_description = models.TextField(
blank=True,
help_text='Additional text shown to students failing this test. '
'Rendered as markdown.'
)

stdin_source = models.TextField(
choices=StdinSource.choices, default=StdinSource.none,
help_text='''Specifies what kind of source stdin will be redirected from.''')
Expand Down
23 changes: 21 additions & 2 deletions autograder/core/models/ag_test/ag_test_suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@ def __init__(self,
show_setup_return_code: bool = True,
show_setup_timed_out: bool = True,
show_setup_stdout: bool = True,
show_setup_stderr: bool = True):
show_setup_stderr: bool = True,
show_student_description: bool = True):
self.visible = visible
self.show_individual_tests = show_individual_tests
self.show_setup_return_code = show_setup_return_code
self.show_setup_timed_out = show_setup_timed_out
self.show_setup_stdout = show_setup_stdout
self.show_setup_stderr = show_setup_stderr
self.show_student_description = show_student_description

SERIALIZABLE_FIELDS = [
'visible',
Expand All @@ -40,6 +42,7 @@ def __init__(self,
'show_setup_timed_out',
'show_setup_stdout',
'show_setup_stderr',
'show_student_description',
]

FIELD_DESCRIPTIONS = {
Expand All @@ -50,9 +53,15 @@ def __init__(self,
"Whether to show stdout content from a suite's setup command."),
'show_setup_stderr': (
"Whether to show stderr content from a suite's setup command."),
'show_student_description': (
"Whether to show the student-facing test suite description."),
}


def _past_limit_fdbk() -> AGTestSuiteFeedbackConfig:
return AGTestSuiteFeedbackConfig(show_student_description=False)


class AGTestSuite(AutograderModel):
"""
A group of autograder test cases to be run inside the same sandbox.
Expand Down Expand Up @@ -152,12 +161,22 @@ def set_order(project: Project, order: List[int]) -> None:
have yet to be graded do not prevent members of a group from submitting
again.''')

staff_description = models.TextField(
blank=True,
help_text='Text description shown only to staff. Rendered as markdown.'
)

student_description = models.TextField(
blank=True,
help_text='Text description shown to students. Rendered as markdown.'
)

normal_fdbk_config = ag_fields.ValidatedJSONField(
AGTestSuiteFeedbackConfig, default=AGTestSuiteFeedbackConfig)
ultimate_submission_fdbk_config = ag_fields.ValidatedJSONField(
AGTestSuiteFeedbackConfig, default=AGTestSuiteFeedbackConfig)
past_limit_submission_fdbk_config = ag_fields.ValidatedJSONField(
AGTestSuiteFeedbackConfig, default=AGTestSuiteFeedbackConfig)
AGTestSuiteFeedbackConfig, default=_past_limit_fdbk)
staff_viewer_fdbk_config = ag_fields.ValidatedJSONField(
AGTestSuiteFeedbackConfig, default=AGTestSuiteFeedbackConfig)

Expand Down
12 changes: 6 additions & 6 deletions autograder/core/submission_feedback.py
Original file line number Diff line number Diff line change
Expand Up @@ -483,12 +483,12 @@ def ag_test_suite_results(self) -> List[AGTestSuiteResultFeedback]:
if fdbk.fdbk_conf.visible:
visible.append(fdbk)
except KeyError:
# In certain rare cases, possibly caused by race condition when
# deleting a suite/test/command at just the right time, a
# In certain rare cases (such as deleting a suite/test/command
# after a submission has already been loaded), a
# submissions's denormalized AG test results can end up
# contaning the PK for a suite/test/command that no longer
# exists. Since this is unlikely to happen on a large scale,
# we'll just ignore those elements.
# exists. Since this will be resolved the next time the
# submission is loaded, we'll just ignore those elements.
continue

visible.sort(key=lambda item: item.ag_test_suite_order)
Expand Down Expand Up @@ -710,7 +710,7 @@ def _visible_ag_test_case_results(self) -> List[AGTestCaseResultFeedback]:

if fdbk.fdbk_conf.visible:
visible.append(fdbk)
except KeyError: # See comment in AGTestSuiteResultFeedback.ag_test_suite_results
except KeyError: # See comment in SubmissionResultFeedback.ag_test_suite_results
continue

visible.sort(key=lambda item: item.ag_test_case_order)
Expand Down Expand Up @@ -826,7 +826,7 @@ def _visible_cmd_results(self) -> Iterable[AGTestCommandResultFeedback]:
)
if fdbk.fdbk_conf.visible:
visible.append(fdbk)
except KeyError: # See comment in AGTestSuiteResultFeedback.ag_test_suite_results
except KeyError: # See comment in SubmissionResultFeedback.ag_test_suite_results
continue

visible.sort(key=lambda item: item.ag_test_command_order)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,19 @@ def test_valid_create(self):

self.assertTrue(ag_test.normal_fdbk_config.visible)
self.assertTrue(ag_test.normal_fdbk_config.show_individual_commands)
self.assertTrue(ag_test.normal_fdbk_config.show_student_description)

self.assertTrue(ag_test.ultimate_submission_fdbk_config.visible)
self.assertTrue(ag_test.ultimate_submission_fdbk_config.show_individual_commands)
self.assertTrue(ag_test.ultimate_submission_fdbk_config.show_student_description)

self.assertTrue(ag_test.past_limit_submission_fdbk_config.visible)
self.assertTrue(ag_test.past_limit_submission_fdbk_config.show_individual_commands)
self.assertFalse(ag_test.past_limit_submission_fdbk_config.show_student_description)

self.assertTrue(ag_test.staff_viewer_fdbk_config.visible)
self.assertTrue(ag_test.staff_viewer_fdbk_config.show_individual_commands)
self.assertTrue(ag_test.staff_viewer_fdbk_config.show_student_description)

def test_error_ag_test_name_not_unique(self):
name = 'stove'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ def test_normal_fdbk_default(self):
self.assertFalse(ag_cmd.normal_fdbk_config.show_actual_stdout)
self.assertFalse(ag_cmd.normal_fdbk_config.show_actual_stderr)
self.assertFalse(ag_cmd.normal_fdbk_config.show_whether_timed_out)
self.assertFalse(ag_cmd.normal_fdbk_config.show_student_description)

def test_ultimate_fdbk_default(self):
ag_cmd = ag_models.AGTestCommand.objects.validate_and_create(
Expand All @@ -108,6 +109,7 @@ def test_ultimate_fdbk_default(self):
self.assertFalse(ag_cmd.ultimate_submission_fdbk_config.show_actual_stdout)
self.assertFalse(ag_cmd.ultimate_submission_fdbk_config.show_actual_stderr)
self.assertTrue(ag_cmd.ultimate_submission_fdbk_config.show_whether_timed_out)
self.assertTrue(ag_cmd.normal_fdbk_config.show_student_description)

def test_past_limit_fdbk_default(self):
ag_cmd = ag_models.AGTestCommand.objects.validate_and_create(
Expand All @@ -125,6 +127,7 @@ def test_past_limit_fdbk_default(self):
self.assertFalse(ag_cmd.past_limit_submission_fdbk_config.show_actual_stdout)
self.assertFalse(ag_cmd.past_limit_submission_fdbk_config.show_actual_stderr)
self.assertFalse(ag_cmd.past_limit_submission_fdbk_config.show_whether_timed_out)
self.assertFalse(ag_cmd.normal_fdbk_config.show_student_description)

def test_staff_viewer_fdbk_default(self):
ag_cmd = ag_models.AGTestCommand.objects.validate_and_create(
Expand All @@ -142,6 +145,7 @@ def test_staff_viewer_fdbk_default(self):
self.assertTrue(ag_cmd.staff_viewer_fdbk_config.show_actual_stdout)
self.assertTrue(ag_cmd.staff_viewer_fdbk_config.show_actual_stderr)
self.assertTrue(ag_cmd.staff_viewer_fdbk_config.show_whether_timed_out)
self.assertTrue(ag_cmd.normal_fdbk_config.show_student_description)

def test_some_valid_non_defaults(self):
points_for_correct_return_code = 1
Expand Down Expand Up @@ -180,7 +184,8 @@ def test_normal_fdbk_non_default(self):
'show_actual_return_code': True,
'show_actual_stdout': False,
'show_actual_stderr': True,
'show_whether_timed_out': False
'show_whether_timed_out': False,
'show_student_description': True,
}

ag_cmd = ag_models.AGTestCommand.objects.validate_and_create(
Expand All @@ -200,7 +205,8 @@ def test_first_failure_fdbk_non_default(self):
'show_actual_return_code': True,
'show_actual_stdout': True,
'show_actual_stderr': False,
'show_whether_timed_out': False
'show_whether_timed_out': False,
'show_student_description': True,
}

ag_cmd = ag_models.AGTestCommand.objects.validate_and_create(
Expand All @@ -221,7 +227,8 @@ def test_ultimate_fdbk_non_default(self):
'show_actual_return_code': True,
'show_actual_stdout': True,
'show_actual_stderr': False,
'show_whether_timed_out': True
'show_whether_timed_out': True,
'show_student_description': False,
}

ag_cmd = ag_models.AGTestCommand.objects.validate_and_create(
Expand All @@ -241,7 +248,8 @@ def test_staff_viewer_fdbk_non_default(self):
'show_actual_return_code': True,
'show_actual_stdout': True,
'show_actual_stderr': False,
'show_whether_timed_out': False
'show_whether_timed_out': False,
'show_student_description': False,
}

ag_cmd = ag_models.AGTestCommand.objects.validate_and_create(
Expand All @@ -261,7 +269,8 @@ def test_past_limit_fdbk_non_default(self):
'show_actual_return_code': True,
'show_actual_stdout': False,
'show_actual_stderr': True,
'show_whether_timed_out': False
'show_whether_timed_out': False,
'show_student_description': True,
}

ag_cmd = ag_models.AGTestCommand.objects.validate_and_create(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,28 +46,31 @@ def test_valid_create_with_defaults(self):
self.assertTrue(suite.normal_fdbk_config.show_setup_timed_out)
self.assertTrue(suite.normal_fdbk_config.show_setup_stdout)
self.assertTrue(suite.normal_fdbk_config.show_setup_stderr)
self.assertTrue(suite.normal_fdbk_config.show_student_description)

self.assertTrue(suite.ultimate_submission_fdbk_config.visible)
self.assertTrue(suite.ultimate_submission_fdbk_config.show_individual_tests)
self.assertTrue(suite.ultimate_submission_fdbk_config.show_setup_return_code)
self.assertTrue(suite.ultimate_submission_fdbk_config.show_setup_timed_out)
self.assertTrue(suite.ultimate_submission_fdbk_config.show_setup_stdout)
self.assertTrue(suite.ultimate_submission_fdbk_config.show_setup_stderr)
self.assertTrue(suite.ultimate_submission_fdbk_config.show_student_description)

self.assertTrue(suite.past_limit_submission_fdbk_config.visible)
self.assertTrue(suite.past_limit_submission_fdbk_config.show_individual_tests)
self.assertTrue(
suite.past_limit_submission_fdbk_config.show_setup_return_code)
self.assertTrue(suite.past_limit_submission_fdbk_config.show_setup_timed_out)
self.assertTrue(suite.past_limit_submission_fdbk_config.show_setup_stdout)
self.assertTrue(suite.past_limit_submission_fdbk_config.show_setup_stderr)
self.assertFalse(suite.past_limit_submission_fdbk_config.show_setup_stderr)

self.assertTrue(suite.staff_viewer_fdbk_config.visible)
self.assertTrue(suite.staff_viewer_fdbk_config.show_individual_tests)
self.assertTrue(suite.staff_viewer_fdbk_config.show_setup_return_code)
self.assertTrue(suite.staff_viewer_fdbk_config.show_setup_timed_out)
self.assertTrue(suite.staff_viewer_fdbk_config.show_setup_stdout)
self.assertTrue(suite.staff_viewer_fdbk_config.show_setup_stderr)
self.assertTrue(suite.staff_viewer_fdbk_config.show_student_description)

def test_valid_create_non_defaults(self):
student_file = ag_models.ExpectedStudentFile.objects.validate_and_create(
Expand Down Expand Up @@ -103,6 +106,7 @@ def test_valid_create_non_defaults(self):
'show_setup_timed_out': False,
'show_setup_stdout': False,
'show_setup_stderr': False,
'show_student_description': False,
}
)

Expand Down
Loading

0 comments on commit 46b78e6

Please sign in to comment.