Package: mcautograder
Multiple Choice AutograderThis 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.InstallationYou can installmcautograderusing pip.pipinstallmcautograderUsageTo use the autograder, import themcautograderpackage and make sure to yourtests fileis 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 theNotebookclass:importmcautogradergrader=mcautograder.Notebook()The autpgrader automatically assumes that the tests file is stored as"./.tests.py".More detailsbelow.If you want the autograder to score the questions, make sure to setscored=Truein yourNotebookcall.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 themax_attemptsargument to an integer, the maximum number of retakes allowed. If this is the case, when students hit that ceiling, the check cells will throw anAssertionErrorbecause 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 theNotebook.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, thenCorrect.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 anAssertionErrorwith a descriptive message.To get the score on a scored autograder, simply callNotebook.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 ourBinder.TestsThe autograder relies on a tests file to get the answers for the questions. In this repo, the file istests.pyand 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.TheNotebookconstructor 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 thetestsargument of the constructor:grader=Notebook(tests=SOME_OTHER_PATH)In the file, we define a variableanswerswhich 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:KeyValue TypeValue Description"identifier"stra unique question identifier"answer"str,intthe answer to the question; specifications below"points"intoptional; the number of points assigned to that questionAnswersmustbe of length 1 (i.e. a single-character string or a single-digit integer). The autograder is currently set up to throw anAssertionErrorif 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 toNotebook.check()when you call it in the notebook.BranchesThemasterbranch contains the current state ofmcautograderas it is hosted on PyPI. Thedevbranch contains the next version ofmcautograderin development.Do not commit directly to themasterbranch.Make commits in thedevbranch and then PR to themasterbranch before uploading to PyPI.Changelogv0.0.6:Added state serialization to prevent dead kernels from resetting notebooksAdded".tests.py"as default argument value forNotebookconstructorAddedAssertionErrorfor scored notebooks with 0 pointsAdded try/except statement for scored notebook identifiers without"points"keyv0.0.5:Changedmcautograder.pytonotebook.pyfor less confusionChangedmax_retakesparam tomax_attemptsfor better understandingUpadted docstring format for sphinx autodocAdded license field for setuptoolsv0.0.4:Moved utils to separate file for documentationv0.0.3:Changed structure of tests file to be more intuitiveAdded docstrings and better documentation