Skip to content

Commit

Permalink
Added tests for timeout configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
tuncbkose committed Jun 14, 2023
1 parent 810ab99 commit 851fe2a
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 9 deletions.
70 changes: 70 additions & 0 deletions nbgrader/tests/apps/files/timeout.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"deletable": false,
"nbgrader": {
"cell_type": "code",
"checksum": "cc6463a7b1770423bdf8bc8b01bee931",
"grade": false,
"grade_id": "squares",
"locked": false,
"schema_version": 3,
"solution": true
}
},
"outputs": [],
"source": [
"import time\n",
"def foo():\n",
" time.sleep(5)\n",
" return True"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"deletable": false,
"editable": false,
"nbgrader": {
"cell_type": "code",
"checksum": "a6a51275965b572fa21c2f06be0fccff",
"grade": true,
"grade_id": "correct_squares",
"locked": false,
"points": 1,
"schema_version": 3,
"solution": false
}
},
"outputs": [],
"source": [
"assert foo()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.10"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
24 changes: 24 additions & 0 deletions nbgrader/tests/apps/test_nbgrader_autograde.py
Original file line number Diff line number Diff line change
Expand Up @@ -1081,3 +1081,27 @@ def test_grade_with_validating_envvar(self, db, course_dir):
submission = gb.find_submission("ps1", "foo")
nb1, = submission.notebooks
assert nb1.score == 0

def test_autograde_timeout(self, db, course_dir):
"""Does autograde accept timeout configuration correctly?"""
run_nbgrader(["db", "assignment", "add", "ps1", "--db", db, "--duedate",
"2015-02-02 14:58:23.948203 America/Los_Angeles"])
run_nbgrader(["db", "student", "add", "foo", "--db", db])
run_nbgrader(["db", "student", "add", "bar", "--db", db])

self._copy_file(join("files", "timeout.ipynb"), join(course_dir, "source", "ps1", "p1.ipynb"))
run_nbgrader(["generate_assignment", "ps1", "--db", db])

self._copy_file(join("files", "timeout.ipynb"), join(course_dir, "submitted", "foo", "ps1", "p1.ipynb"))
self._copy_file(join("files", "timeout.ipynb"), join(course_dir, "submitted", "bar", "ps1", "p1.ipynb"))

output = run_nbgrader(["autograde", "ps1", "--db", db, "--student", "foo"])
# timeout=2 secs, 1 was causing an asyncio error on Windows
output = run_nbgrader(["autograde", "ps1", "--db", db, "--student", "bar", "--Execute.timeout=2"])

# Check timeout config changes function based on timeout config
with Gradebook(db) as gb:
notebook = gb.find_submission_notebook("p1", "ps1", "foo")
assert notebook.score == 1
notebook = gb.find_submission_notebook("p1", "ps1", "bar")
assert notebook.score == 0
72 changes: 63 additions & 9 deletions nbgrader/tests/apps/test_nbgrader_validate.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from os.path import join
from textwrap import dedent

from .. import run_nbgrader
from .base import BaseTestApp
Expand All @@ -14,7 +15,10 @@ def test_validate_unchanged(self):
"""Does the validation fail on an unchanged notebook?"""
self._copy_file(join("files", "submitted-unchanged.ipynb"), "submitted-unchanged.ipynb")
output = run_nbgrader(["validate", "submitted-unchanged.ipynb"], stdout=True)
assert output.splitlines()[0] == "VALIDATION FAILED ON 3 CELL(S)! If you submit your assignment as it is, you WILL NOT"
assert (
output.splitlines()[0]
== "VALIDATION FAILED ON 3 CELL(S)! If you submit your assignment as it is, you WILL NOT"
)

def test_validate_changed(self):
"""Does the validation pass on an changed notebook?"""
Expand All @@ -33,7 +37,10 @@ def test_validate_zero_points(self):
"""Does validation correctly fail when cell has zero points?"""
self._copy_file(join("files", "validation-zero-points.ipynb"), "validation-zero-points.ipynb")
output = run_nbgrader(["validate", "validation-zero-points.ipynb"], stdout=True)
assert output.splitlines()[0] == "VALIDATION FAILED ON 1 CELL(S)! If you submit your assignment as it is, you WILL NOT"
assert (
output.splitlines()[0]
== "VALIDATION FAILED ON 1 CELL(S)! If you submit your assignment as it is, you WILL NOT"
)

def test_invert_validate_unchanged(self):
"""Does the inverted validation pass on an unchanged notebook?"""
Expand All @@ -51,7 +58,10 @@ def test_grade_cell_changed(self):
"""Does the validate fail if a grade cell has changed?"""
self._copy_file(join("files", "submitted-grade-cell-changed.ipynb"), "submitted-grade-cell-changed.ipynb")
output = run_nbgrader(["validate", "submitted-grade-cell-changed.ipynb"], stdout=True)
assert output.splitlines()[0] == "THE CONTENTS OF 1 TEST CELL(S) HAVE CHANGED! This might mean that even though the tests"
assert (
output.splitlines()[0]
== "THE CONTENTS OF 1 TEST CELL(S) HAVE CHANGED! This might mean that even though the tests"
)

def test_grade_cell_changed_ignore_checksums(self):
"""Does the validate pass if a grade cell has changed but we're ignoring checksums?"""
Expand All @@ -66,7 +76,10 @@ def test_invert_grade_cell_changed(self):
"""Does the validate fail if a grade cell has changed, even with --invert?"""
self._copy_file(join("files", "submitted-grade-cell-changed.ipynb"), "submitted-grade-cell-changed.ipynb")
output = run_nbgrader(["validate", "submitted-grade-cell-changed.ipynb", "--invert"], stdout=True)
assert output.splitlines()[0] == "THE CONTENTS OF 1 TEST CELL(S) HAVE CHANGED! This might mean that even though the tests"
assert (
output.splitlines()[0]
== "THE CONTENTS OF 1 TEST CELL(S) HAVE CHANGED! This might mean that even though the tests"
)

def test_invert_grade_cell_changed_ignore_checksums(self):
"""Does the validate fail if a grade cell has changed with --invert and ignoring checksums?"""
Expand All @@ -85,13 +98,19 @@ def test_validate_unchanged_ignore_checksums(self):
"validate", "submitted-unchanged.ipynb",
"--Validator.ignore_checksums=True"
], stdout=True)
assert output.splitlines()[0] == "VALIDATION FAILED ON 1 CELL(S)! If you submit your assignment as it is, you WILL NOT"
assert (
output.splitlines()[0]
== "VALIDATION FAILED ON 1 CELL(S)! If you submit your assignment as it is, you WILL NOT"
)

def test_locked_cell_changed(self):
"""Does the validate fail if a locked cell has changed?"""
self._copy_file(join("files", "submitted-locked-cell-changed.ipynb"), "submitted-locked-cell-changed.ipynb")
output = run_nbgrader(["validate", "submitted-locked-cell-changed.ipynb"], stdout=True)
assert output.splitlines()[0] == "THE CONTENTS OF 2 TEST CELL(S) HAVE CHANGED! This might mean that even though the tests"
assert (
output.splitlines()[0]
== "THE CONTENTS OF 2 TEST CELL(S) HAVE CHANGED! This might mean that even though the tests"
)

def test_locked_cell_changed_ignore_checksums(self):
"""Does the validate pass if a locked cell has changed but we're ignoring checksums?"""
Expand All @@ -100,13 +119,19 @@ def test_locked_cell_changed_ignore_checksums(self):
"validate", "submitted-locked-cell-changed.ipynb",
"--Validator.ignore_checksums=True"
], stdout=True)
assert output.splitlines()[0] == "VALIDATION FAILED ON 1 CELL(S)! If you submit your assignment as it is, you WILL NOT"
assert (
output.splitlines()[0]
== "VALIDATION FAILED ON 1 CELL(S)! If you submit your assignment as it is, you WILL NOT"
)

def test_invert_locked_cell_changed(self):
"""Does the validate fail if a locked cell has changed, even with --invert?"""
self._copy_file(join("files", "submitted-locked-cell-changed.ipynb"), "submitted-locked-cell-changed.ipynb")
output = run_nbgrader(["validate", "submitted-locked-cell-changed.ipynb", "--invert"], stdout=True)
assert output.splitlines()[0] == "THE CONTENTS OF 2 TEST CELL(S) HAVE CHANGED! This might mean that even though the tests"
assert (
output.splitlines()[0]
== "THE CONTENTS OF 2 TEST CELL(S) HAVE CHANGED! This might mean that even though the tests"
)

def test_invert_locked_cell_changed_ignore_checksums(self):
"""Does the validate fail if a locked cell has changed with --invert and ignoring checksums?"""
Expand All @@ -131,5 +156,34 @@ def test_validate_glob(self):
def test_validate_with_validating_envvar(self, db, course_dir):
self._copy_file(join("files", "validating-environment-variable.ipynb"), "nb1.ipynb")
output = run_nbgrader(["validate", "nb1.ipynb"], stdout=True)
assert output.splitlines()[0] == "VALIDATION FAILED ON 1 CELL(S)! If you submit your assignment as it is, you WILL NOT"
assert (
output.splitlines()[0]
== "VALIDATION FAILED ON 1 CELL(S)! If you submit your assignment as it is, you WILL NOT"
)

def test_validate_timeout(self, db, course_dir):
"""Does validate accept timeout configuration correctly?"""
self._copy_file(join("files", "timeout.ipynb"), "nb1.ipynb")
output = run_nbgrader(["validate", "nb1.ipynb"], stdout=True)
assert output.strip() == "Success! Your notebook passes all the tests."

# timeout=1 leads to an asyncio error on Windows
output = run_nbgrader(["validate", "--Execute.timeout=2", "nb1.ipynb"], stdout=True)
assert output.splitlines()[-2].strip() == "CellTimeoutError: No reply from kernel before timeout"

def test_validate_timeout_config(self, db, course_dir):
"""Is the timeout error message configurable"""
self._copy_file(join("files", "timeout.ipynb"), "nb1.ipynb")
# supplying a list as dict value (for traceback) on cli was annoying
# writing this into a config file is easier
self._make_file("nbgrader_config.py",
dedent("""
c = get_config()
c.Execute.error_on_timeout = {
"ename": "CustomError",
"evalue": "",
"traceback": ["Custom"],
}
"""))
output = run_nbgrader(["validate", "--Execute.timeout=2", "nb1.ipynb"], stdout=True)
assert output.splitlines()[-2].strip() == "Custom"

0 comments on commit 851fe2a

Please sign in to comment.