MUSA Graderv0.1.0

Developer guide

Testing and CI

Running the tests#

python -m pytest                  # the full suite, about 40 s
python -m pytest -m "not slow"    # skip the tests that run real kernels
python -m pytest -m docker        # grade a notebook in the sandbox image (needs it built)
ruff check .                      # syntax errors and undefined names
MarkerMeaning
slowRuns a real notebook kernel (a few seconds each)
dockerRuns in the sandbox image. Skipped unless musa-grader:latest is built.

Ruff is limited to the checks that mean the grader would crash (E9, F63, F7, F82). assignment_template/ and notebooks are excluded because the templates are deliberately unfinished code.

What the suite covers#

FileCovers
test_discovery.pyFolder and Canvas layouts, notebook choice, ambiguous submissions
test_data_supply.pyPlacing instructor data at the paths each notebook reads, path safety
test_execution.py, test_docker_execution.pyLocal and sandboxed execution, timeouts, probe stripping
test_hw1.py, test_hw2.py, test_hw3.pyPer-assignment checks and named near-misses
test_hw2_integration.py, test_integration.pyEnd-to-end grading of demo classes
test_answers.py, test_charts.pyReading answers and chart specs from saved outputs
test_real_submission_patterns.pyFailure patterns seen in real classes, reproduced synthetically
test_results.pySession persistence, overrides, exports

Continuous integration#

.github/workflows/ci.yml runs on every push to main and every pull request:

  1. Tests on Python 3.10, 3.11, 3.12 and 3.13: install, ruff, python cli.py rubrics, then the full suite with real kernels in local mode.
  2. Docker images: build the sandbox, import every package the assignments use, build the app image, grade a real notebook inside the sandbox, grade the demo class from inside the app container (and assert student_001 scores 100), and check that the app answers its health check.

Dependabot opens weekly update PRs for the grader's packages, the sandbox's pinned packages, the base images and the Actions. Each one goes through the same CI.

Building these docs#

The site is static HTML in docs/. Guide pages are written by hand as fragments in docs/_pages/. The API reference is generated from the docstrings in grader/ and assignments/. The build reads the source with ast instead of importing it, so it needs only the standard library:

python docs/build.py

Rebuild after changing a docstring or a page, and commit the output. To preview locally:

python -m http.server -d docs 8000

To publish, enable GitHub Pages for the repository with Deploy from a branch → main → /docs.

To changeEdit
A guide pagedocs/_pages/<page>.html, then rebuild
Page order or the API module listGUIDE and API_MODULES in docs/build.py
An API descriptionThe docstring in the source, then rebuild
Styling or behaviourdocs/assets/style.css, docs/assets/main.js