Small multiple choice question autograding library
Project description
Multiple Choice Autograder
This repository contains a small Python-based multiple-choice question autograder inteded for use in Jupyter Notebooks. It is meant to be packaged with each assignment so that they are easier for use on third-party servers, e.g. MyBinder.
Installation
You can install mcautograder using pip.
pip install mcautograder
Usage
To use the autograder, import the mcautograder package and make sure to your tests file is in the same directory as your notebook. When you load the notebook dependencies, import the file and initialize the grader by creating an instance of the Notebook class:
import mcautograder
grader = mcautograder.Notebook()
The autpgrader automatically assumes that the tests file is stored as "./.tests.py". More details below.
If you want the autograder to score the questions, make sure to set scored=True in your Notebook call. The default behavior of the autograder is to allow students to submit answers until they get the correct one. If you want to change this behavior, you must set the max_attempts argument to an integer, the maximum number of retakes allowed. If this is the case, when students hit that ceiling, the check cells will throw an AssertionError because they've hit the retake ceiling.
An example call for a scored notebook with a retake ceiling of 5 is given below.
grader = Notebook(scored=True, max_attempts=5)
To use the autograder to check answers, have students assign their answers to variables in the notebook; these answers can strings of length 1 or single-digit integers. Then call the Notebook.check() function; the first argument should be the question identifier in your tests file and the second should be the variable the student created.
my_answer = "A"
grader.check("q1", my_answer)
If the student's response matches the test file, then Correct. will be printed; otherwise, Try again. will be printed. If the student enters an invalid response (e.g. float, answer of > 1 character, hit retake ceiling), the grader will throw an AssertionError with a descriptive message.
To get the score on a scored autograder, simply call Notebook.score():
grader.score()
The output will contain the fraction of earned points out of possible points and the percentage.
For a more descriptive introduction to the autograder, launch our Binder.
Tests
The autograder relies on a tests file to get the answers for the questions. In this repo, the file is tests.py and it is public; in practice, I usually distribute the answers as a hidden file, .tests.py. It is unhidden here so that you can peruse its structure and contents.
The Notebook constructor by default assumes that your tests are in the file .tests.py. If you have a different preferred location, you can pass the path to the file by setting the tests argument of the constructor:
grader = Notebook(tests=SOME_OTHER_PATH)
In the file, we define a variable answers which is a list containing dictionaries, each of which represents a single question. Each dictionary should contain 3 keys: "identifier", "answer", and, optionally, "points". If your assignment is unscored, you can leave off the "points" key. A description of the keys' values is given below:
| Key | Value Type | Value Description |
|---|---|---|
"identifier" |
str |
a unique question identifier |
"answer" |
str, int |
the answer to the question; specifications below |
"points" |
int |
optional; the number of points assigned to that question |
Answers must be of length 1 (i.e. a single-character string or a single-digit integer). The autograder is currently set up to throw an AssertionError if an answer of length > 1 is submitted, although we do intend to add this functionality later.
An example of a file is given below.
answers = [
{
"identifier": "q1",
"answer": 3,
"points": 1,
}, {
"identifier": "q2",
"answer": 2,
"points": 2,
}, {
"identifier": "q3",
"answer": "D",
"points": 3,
}
]
The identifiers have no set format. This is because the identifier is passed to Notebook.check() when you call it in the notebook.
Branches
The master branch contains the current state of mcautograder as it is hosted on PyPI. The dev branch contains the next version of mcautograder in development. Do not commit directly to the master branch. Make commits in the dev branch and then PR to the master branch before uploading to PyPI.
Changelog
v0.0.6:
- Added state serialization to prevent dead kernels from resetting notebooks
- Added
".tests.py"as default argument value forNotebookconstructor - Added
AssertionErrorfor scored notebooks with 0 points - Added try/except statement for scored notebook identifiers without
"points"key
v0.0.5:
- Changed
mcautograder.pytonotebook.pyfor less confusion - Changed
max_retakesparam tomax_attemptsfor better understanding - Upadted docstring format for sphinx autodoc
- Added license field for setuptools
v0.0.4:
- Moved utils to separate file for documentation
v0.0.3:
- Changed structure of tests file to be more intuitive
- Added docstrings and better documentation
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mcautograder-0.0.6.tar.gz.
File metadata
- Download URL: mcautograder-0.0.6.tar.gz
- Upload date:
- Size: 5.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.21.0 setuptools/39.0.1 requests-toolbelt/0.9.1 tqdm/4.31.1 CPython/3.6.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7e911513646a99edeb28535170dab0c797cf6d2971ffc79f47fb0deba03e3369
|
|
| MD5 |
09d72d6ac5af71060ff82dc0c86cf45b
|
|
| BLAKE2b-256 |
d1e5bd5102dd17d7302705dc94d7491cd657b7db4d438544a18cc157ed5628be
|
File details
Details for the file mcautograder-0.0.6-py3-none-any.whl.
File metadata
- Download URL: mcautograder-0.0.6-py3-none-any.whl
- Upload date:
- Size: 7.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.21.0 setuptools/39.0.1 requests-toolbelt/0.9.1 tqdm/4.31.1 CPython/3.6.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6fb59e45e144ee7b11383cdb5045b79c2e6036a1785549ec26f21664ee349291
|
|
| MD5 |
16f5bc003634348337648f538ac941f8
|
|
| BLAKE2b-256 |
53c4d2431555f0663f853eaa02084495af485ac9c586e30e8cf0b32a4b485ff5
|