Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Feature: Automatic generation of test code #1650

Closed
wants to merge 113 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
113 commits
Select commit Hold shift + click to select a range
8323a66
added autotest files
Alireza-Iranpour Jun 24, 2022
f431e99
Merge branch 'autotest' of https://github.com/UBC-DSCI/nbgrader into …
Alireza-Iranpour Jun 24, 2022
38bd011
Merge branch 'autotest' of https://github.com/UBC-DSCI/nbgrader into …
Alireza-Iranpour Jun 26, 2022
42b1133
added AutoTest sample problem set and tests.yml
Alireza-Iranpour Jun 26, 2022
8feca53
added PyYAML to requirements.txt
Alireza-Iranpour Jun 26, 2022
a730aaf
updated instantiatetests to reflect the latest changes in nbgrader
Alireza-Iranpour Jun 26, 2022
a6a1d71
Create problem3.ipynb
Alireza-Iranpour Jun 26, 2022
b7c56f9
Update instantiate_tests.py
Alireza-Iranpour Jul 4, 2022
3e6e6b0
added initial commit of R notebook example
trevorcampbell Jul 6, 2022
ceeefec
added test support for R
Alireza-Iranpour Jul 10, 2022
a0d003f
Fixed the issue regarding the kernel_name identified in the nbgrader …
Alireza-Iranpour Jul 17, 2022
75a9ac9
Merge branch 'jupyter:main' into autotest
trevorcampbell Jul 18, 2022
98c7ad0
added tests for instantiatetests preprocessor
Alireza-Iranpour Jul 20, 2022
1f83e9a
Merge branch 'jupyter:main' into autotest
trevorcampbell Jul 20, 2022
5ad7555
Update limittestcellheights.py
Alireza-Iranpour Jul 25, 2022
fe2e7fe
added tests
Alireza-Iranpour Jul 25, 2022
520d4e8
Update tests.yml
Alireza-Iranpour Jul 26, 2022
7cf9b31
Update tests.yml
Alireza-Iranpour Jul 26, 2022
b9d2283
Update tests.yml
Alireza-Iranpour Jul 26, 2022
d703e8f
Update tests.yml
Alireza-Iranpour Jul 26, 2022
203fd96
modifying the instantiatetests app/converter to remove generate_assig…
trevorcampbell Jul 28, 2022
593b9d8
fixed apps/api to remove old generate_assignment stuff
trevorcampbell Jul 28, 2022
aa423f8
minor ed
trevorcampbell Jul 28, 2022
bb8720f
minor ed to doc
trevorcampbell Jul 28, 2022
7c556b7
removed old r test yml
trevorcampbell Jul 28, 2022
1494175
instantiated both test notebooks in user guide; clarified tests yml w…
trevorcampbell Jul 28, 2022
9511da7
added R stub to clearsolns; instantiated/released all notebooks in us…
trevorcampbell Jul 28, 2022
c0fba44
removed pyyaml from reqmts.txt
trevorcampbell Jul 29, 2022
0654354
add pyyaml to setup.cfg
trevorcampbell Jul 29, 2022
7593403
added jupyter images to docs notebooks
trevorcampbell Jul 29, 2022
441b5f7
added limit test cell heights to nbextension tests
trevorcampbell Jul 29, 2022
d5ae9be
made instantiatetests preproc not run / avoid starting kernel if no a…
trevorcampbell Jul 29, 2022
6018e07
reinstantiated/generated notebooks in user_guide after jupyter.png copy
trevorcampbell Jul 29, 2022
846522f
remove copy/pasted deprecation test for instantiate_tests
trevorcampbell Jul 29, 2022
502e54e
removed cell save db check; not used for instantiate tests
trevorcampbell Jul 29, 2022
c9f0b84
removed db interaction from instantiate_tests converter; removed/modi…
trevorcampbell Jul 29, 2022
c0d65ed
minor bugfix in instantiate_tests test
trevorcampbell Jul 29, 2022
efc4d58
minor bugfix instantiate_tests tests
trevorcampbell Jul 29, 2022
0e9c09d
added checkcellmetadata preproc to instantiate_tests converter
trevorcampbell Jul 29, 2022
b5cce35
package import fix
trevorcampbell Jul 29, 2022
432f176
remove ps2/ps3 demo assignments from formgrader tests
trevorcampbell Jul 29, 2022
bd734cb
fixed limit test cell height tests (css selector was wrong)
trevorcampbell Jul 30, 2022
a8be0a8
fix check metadata test for instantiate_tests
trevorcampbell Jul 30, 2022
068ffce
fixed json errors in new test nb
trevorcampbell Jul 30, 2022
ef2820a
added tests.yml to tests folder; added a default tests and specific t…
trevorcampbell Jul 30, 2022
5e18afe
removed specific test (should just be a separate test later on); fixe…
trevorcampbell Jul 30, 2022
b0a0ceb
removed unused options from instantiatetestsapp
trevorcampbell Jul 30, 2022
7a55f96
added 'python' kernel to test tests.yml
trevorcampbell Jul 30, 2022
8d7c3e7
added disable checkmetadata to instantiatetests no-metadata
trevorcampbell Jul 30, 2022
c10aca6
bugfix in instantiatetests app -- returned none instead of nb, resources
trevorcampbell Jul 30, 2022
2bdf242
added traitlets for comment_strs and sanitizers to instantiatetests p…
trevorcampbell Jul 31, 2022
015171b
working on more comprehensive autotest test code
trevorcampbell Jul 31, 2022
8212393
implemented a number of tests for generate_assignment and instantiate…
trevorcampbell Aug 1, 2022
7804654
fixed gen_asgn -> instant_tests in test code
trevorcampbell Aug 1, 2022
d682764
minor ed
trevorcampbell Aug 1, 2022
c125aa9
minor spacing bugfix instantiate tests
trevorcampbell Aug 1, 2022
35ad594
minor bugfix in test code (filenames)
trevorcampbell Aug 1, 2022
56500f9
copied tests.yml into genfeedback tests
trevorcampbell Aug 1, 2022
bfc26b5
removed first cell run (seems redundant...WIP)
trevorcampbell Aug 1, 2022
a97686f
bugfix: added run of trailing non-autotest code lines in test cells
trevorcampbell Aug 1, 2022
70027df
removed execution metainfo after instantiatetests
trevorcampbell Aug 1, 2022
1e489bb
minor test bugfix
trevorcampbell Aug 1, 2022
a0518ca
simplified multi autotest notebook
trevorcampbell Aug 1, 2022
7bd9619
simplified tests.yml behavior for dicts to use sets instead of sorted…
trevorcampbell Aug 1, 2022
10e473c
reverted autotest-multi book to use lists/dicts with different types
trevorcampbell Aug 1, 2022
42b69a4
tests.yml using sorted string lists instead of sets (to avoid nonhash…
trevorcampbell Aug 1, 2022
2446b36
split autotest multi tests into multiple cells
trevorcampbell Aug 1, 2022
85f5019
fixed minor message flaw in tests.yml
trevorcampbell Aug 1, 2022
aff7af5
changed list comp in tests.yml to map to avoid temp variables collidi…
trevorcampbell Aug 1, 2022
79e850c
bugfix: escaping double quotes in failure messages autotest
trevorcampbell Aug 1, 2022
eac75b3
added autograding tests for autotest notebooks
trevorcampbell Aug 1, 2022
49e1ee5
added right/wrong changed nbs for hidden autotests
trevorcampbell Aug 1, 2022
61b9adb
minor tests bugfix in hidden tests autograding autotest
trevorcampbell Aug 1, 2022
475f537
more minor bugfix in hidden tests autotest code
trevorcampbell Aug 1, 2022
aa3c020
added python kernel to tests.yml
trevorcampbell Aug 1, 2022
cb70ebf
Merge branch 'jupyter:main' into autotest
trevorcampbell Aug 1, 2022
0e93295
fleshing out preproc tests for instantiate_tests
trevorcampbell Aug 1, 2022
567ac05
minor ed
trevorcampbell Aug 1, 2022
bc6bbb2
removed create option from apps/api.py instantiate_tests
trevorcampbell Aug 3, 2022
f07a5fa
Added CodeExecutionError() to raise an exception when there is a prob…
Alireza-Iranpour Aug 8, 2022
ce46b0c
Implemented additional tests
Alireza-Iranpour Aug 8, 2022
fb85dd9
removed test_no_remove_autotest_nongrade from the tests
Alireza-Iranpour Aug 8, 2022
1916fed
Added generate_source_with_tests flag to the GenerateAssignmentApp
Alireza-Iranpour Aug 20, 2022
0a7e523
Added code to copy the tests.yml file in the quickstartapp
Alireza-Iranpour Aug 20, 2022
30dae71
renamed instantiated_directory to source_with_tests_directory
Alireza-Iranpour Aug 20, 2022
02adbe3
renamed instantiated_directory to source_with_tests_directory
Alireza-Iranpour Aug 20, 2022
56b2f26
Added documentation for the autotes feature (tests-cell-automatic-tes…
Alireza-Iranpour Aug 20, 2022
c29d72f
added autotest images to be used in the documentation
Alireza-Iranpour Aug 20, 2022
b498f23
Organized user_guide directories
Alireza-Iranpour Aug 20, 2022
6e77364
Changed PyYAML==6.0 to PyYAML>=6.0
Alireza-Iranpour Aug 20, 2022
984a73e
Removed template comments
Alireza-Iranpour Aug 20, 2022
f5b7371
Removed instantiatetestsapp
Alireza-Iranpour Aug 20, 2022
077ed64
Removed limit test cell height files from this branch and moved it to…
Alireza-Iranpour Aug 20, 2022
7583e0e
Removed InstantiateTestsApp
Alireza-Iranpour Aug 20, 2022
0c45fed
Merge branch 'jupyter:main' into autotest
Alireza-Iranpour Aug 20, 2022
3ac334c
Merge branch 'autotest' of https://github.com/UBC-DSCI/nbgrader into …
Alireza-Iranpour Aug 20, 2022
61cd35a
Update creating_and_grading_assignments.ipynb
Alireza-Iranpour Aug 20, 2022
d15d26a
modifications as a result of running python tasks.py docs
Alireza-Iranpour Aug 20, 2022
9d0063c
Generated release and source_with_tests notebooks for ps2 (R problem …
Alireza-Iranpour Aug 20, 2022
c79c92f
Added DataFrame comparison tests to tests.yml
Alireza-Iranpour Aug 20, 2022
cfc3a19
Update requirements.txt
Alireza-Iranpour Aug 24, 2022
15e94ae
Merge branch 'jupyter:main' into autotest
Alireza-Iranpour Aug 24, 2022
6505031
Added dictionary tests to ps1/pronlem3.ipynb
Alireza-Iranpour Aug 29, 2022
bb0fb3c
Update tests.yml
Alireza-Iranpour Aug 29, 2022
9f479dd
Added the test for setting the flag --generate_source_with_tests
Alireza-Iranpour Aug 29, 2022
c77d109
Delete main.js
Alireza-Iranpour Oct 13, 2022
90ec761
Removed limit_cell_height extension
Alireza-Iranpour Oct 13, 2022
862f517
replaced problem1 and 2 in the release folder with the original from …
Alireza-Iranpour Oct 14, 2022
66411bd
removed setup.cfg and added pyyaml to pyproject.toml; merge conflict …
trevorcampbell Oct 15, 2022
8587b95
Delete limited_test_cell_height.ipynb
Alireza-Iranpour Oct 17, 2022
e44c2c1
Fixed the test_nbextension_linux
Alireza-Iranpour Oct 17, 2022
7d05c08
Fixed extension related tests
Alireza-Iranpour Oct 17, 2022
2e22e64
Fixed path issue when copying tests.yml file into the course director…
Alireza-Iranpour Oct 17, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion nbgrader/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def _jupyter_nbextension_paths():
src=os.path.join('nbextensions', 'validate_assignment'),
dest="validate_assignment",
require="validate_assignment/main"
),
)
]

if sys.platform != 'win32':
Expand Down
28 changes: 27 additions & 1 deletion nbgrader/apps/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from traitlets import Instance, Enum, Unicode, observe

from ..coursedir import CourseDirectory
from ..converters import GenerateAssignment, Autograde, GenerateFeedback, GenerateSolution
from ..converters import GenerateAssignment, Autograde, GenerateFeedback, GenerateSolution, InstantiateTests
from ..exchange import ExchangeFactory, ExchangeError
from ..api import MissingEntry, Gradebook, Student, SubmittedAssignment
from ..utils import parse_utc, temp_attrs, capture_log, as_timezone, to_numeric_tz
Expand Down Expand Up @@ -917,6 +917,32 @@ def generate_assignment(self, assignment_id, force=True, create=True):
app.create_assignment = create
return capture_log(app)

def instantiate_tests(self, assignment_id, force=True):
"""Run ``nbgrader instantiate_tests`` for a particular assignment.

Arguments
---------
assignment_id: string
The name of the assignment
force: bool
Whether to force creating the instantiated version, even if it already
exists.

Returns
-------
result: dict
A dictionary with the following keys (error and log may or may not be present):

- success (bool): whether or not the operation completed successfully
- error (string): formatted traceback
- log (string): captured log output

"""
with temp_attrs(self.coursedir, assignment_id=assignment_id):
app = InstantiateTests(coursedir=self.coursedir, parent=self)
app.force = force
return capture_log(app)

def unrelease(self, assignment_id):
"""Run ``nbgrader list --remove`` for a particular assignment.

Expand Down
31 changes: 28 additions & 3 deletions nbgrader/apps/generateassignmentapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

import sys

from traitlets import default
from traitlets import default, Bool
from textwrap import dedent

from .baseapp import NbGrader, nbgrader_aliases, nbgrader_flags
from ..converters import BaseConverter, GenerateAssignment, NbGraderException
from ..converters import BaseConverter, GenerateAssignment, NbGraderException, InstantiateTests
from traitlets.traitlets import MetaHasTraits
from typing import List, Any
from traitlets.config.loader import Config
Expand Down Expand Up @@ -51,6 +52,13 @@
{'BaseConverter': {'force': True}},
"Overwrite an assignment/submission if it already exists."
),
'generate_source_with_tests': (
{'GenerateAssignmentApp': {'instantiate_tests': True}},
"Generate an intermediate notebooks that contain the solutions as well as the tests "
"to be used for debugging purposes by the instructors\n"
"results saved according to\n"
"source_with_tests/./{assignment_id}/{notebook_id}.ipynb"
)
})


Expand All @@ -62,6 +70,16 @@ class GenerateAssignmentApp(NbGrader):
aliases = aliases
flags = flags

instantiate_tests = Bool(
False,
help=dedent(
"""
Generate an intermediate notebook that contains both solutions as well as the tests
to be used for debugging purposes"
"""
)
).tag(config=True)

examples = """
Produce the version of the assignment that is intended to be released to
students. This performs several modifications to the original assignment:
Expand Down Expand Up @@ -112,7 +130,7 @@ class GenerateAssignmentApp(NbGrader):
@default("classes")
def _classes_default(self) -> List[MetaHasTraits]:
classes = super(GenerateAssignmentApp, self)._classes_default()
classes.extend([BaseConverter, GenerateAssignment])
classes.extend([BaseConverter, GenerateAssignment, InstantiateTests])
return classes

def _load_config(self, cfg: Config, **kwargs: Any) -> None:
Expand Down Expand Up @@ -141,6 +159,13 @@ def start(self) -> None:
elif len(self.extra_args) == 1:
self.coursedir.assignment_id = self.extra_args[0]

if self.instantiate_tests:
converter = InstantiateTests(coursedir=self.coursedir, parent=self)
try:
converter.start()
except NbGraderException:
sys.exit(1)

converter = GenerateAssignment(coursedir=self.coursedir, parent=self)
try:
converter.start()
Expand Down
1 change: 1 addition & 0 deletions nbgrader/apps/nbgraderapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ class NbGraderApp(NbGrader):
"""
).strip()
),

autograde=(
AutogradeApp,
dedent(
Expand Down
5 changes: 5 additions & 0 deletions nbgrader/apps/quickstartapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,11 @@ def start(self):
ignore_html = shutil.ignore_patterns("*.html")
shutil.copytree(example, os.path.join(course_path, "source"), ignore=ignore_html)

# copying the tests.yml file to the course directory
tests_file_path = os.path.abspath(os.path.join(
os.path.dirname(__file__), '..', 'docs', 'source', 'user_guide', 'tests.yml'))
shutil.copyfile(tests_file_path, os.path.join(course_path, 'tests.yml'))

# create the config file
self.log.info("Generating example config file...")
currdir = os.getcwd()
Expand Down
4 changes: 3 additions & 1 deletion nbgrader/converters/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from .feedback import Feedback
from .generate_feedback import GenerateFeedback
from .generate_solution import GenerateSolution
from .instantiate_tests import InstantiateTests

__all__ = [
"BaseConverter",
Expand All @@ -14,5 +15,6 @@
"Autograde",
"Feedback",
"GenerateFeedback",
"GenerateSolution"
"GenerateSolution",
"InstantiateTests"
]
2 changes: 2 additions & 0 deletions nbgrader/converters/generate_assignment.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from .base import BaseConverter, NbGraderException
from ..preprocessors import (
IncludeHeaderFooter,
InstantiateTests,
ClearSolutions,
LockCells,
ComputeChecksums,
Expand Down Expand Up @@ -57,6 +58,7 @@ def _output_directory(self) -> str:

preprocessors = List([
IncludeHeaderFooter,
InstantiateTests,
LockCells,
ClearSolutions,
ClearOutput,
Expand Down
51 changes: 51 additions & 0 deletions nbgrader/converters/instantiate_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import os
import re
from textwrap import dedent

from traitlets import List, Bool, default

from ..api import Gradebook, MissingEntry
from .base import BaseConverter, NbGraderException
from ..preprocessors import (
InstantiateTests,
ClearOutput,
CheckCellMetadata
)
from traitlets.config.loader import Config
from typing import Any
from ..coursedir import CourseDirectory


class InstantiateTests(BaseConverter):

@default("permissions")
def _permissions_default(self) -> int:
return 664 if self.coursedir.groupshared else 644

@property
def _input_directory(self) -> str:
return self.coursedir.source_directory

@property
def _output_directory(self) -> str:
return self.coursedir.source_with_tests_directory

preprocessors = List([
InstantiateTests,
ClearOutput,
CheckCellMetadata,
]).tag(config=True)

def _load_config(self, cfg: Config, **kwargs: Any) -> None:
super(InstantiateTests, self)._load_config(cfg, **kwargs)

def __init__(self, coursedir: CourseDirectory = None, **kwargs: Any) -> None:
super(InstantiateTests, self).__init__(coursedir=coursedir, **kwargs)

def start(self) -> None:
old_student_id = self.coursedir.student_id
self.coursedir.student_id = '.'
try:
super(InstantiateTests, self).start()
finally:
self.coursedir.student_id = old_student_id
13 changes: 13 additions & 0 deletions nbgrader/coursedir.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,19 @@ def _validate_notebook_id(self, proposal: Bunch) -> str:
)
).tag(config=True)

source_with_tests_directory = Unicode(
'source_with_tests',
help=dedent(
"""
The name of the directory that contains the version of the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This help string seems wrong

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Help sting is fixed
source_with_tests_directory = Unicode( 'source_with_tests', help=dedent( """ The name of the directory that contains the version of the assignment that will contain both the solutions and the instantiated test cases to be used by instructors. This corresponds to thenbgrader_stepvariable in thedirectory_structure config option. """ ) ).tag(config=True)

assignment that will contain both the solutions and the instantiated
test cases to be used by instructors. This corresponds to
the `nbgrader_step` variable in the `directory_structure` config
option.
"""
)
).tag(config=True)

submitted_directory = Unicode(
'submitted',
help=dedent(
Expand Down
Loading