Make sure you have pip installed (eg. on Debian/Ubuntu, apt-get install python-pip
).
Then, run pip install gradescope-utils
See the Releases page.
Follow https://packaging.python.org/tutorials/packaging-projects/, but in brief:
git tag vX.Y.Z COMMIT_SHA
Contact us at [email protected] if you need help with these packages.
Hello, I figured out how to pass parameters to the JSONTestRunner from settings.py file in Django. I was able to test it locally with no issues.
I am wondering, when would anyone else be able to download these updates? Furthermore, I figure this could be useful for anyone teaching courses on either developing Django applications or in my case, use a buggy Django implementation for a CTF.
Description
Naming test cases with a new-line character on the first line causes the name of the function to be placed in the results.json
file instead of the human-readable name in the docstring of the testcase.
To Reproduce
Create a testcase and name it with a docstring that has a new-line character on the first line. This file is called tests.py
.
```python import unittest from gradescope_utils.autograder_utils.decorators import weight, number
class TestAutograder(unittest.TestCase): @weight(1.0) @number("1") def test_prob1(self): """ A human-readable name. """ pass ```
Running the above with the JSONTestRunner
provided in gradescope_utils
produces the following results.json:
json
{
"tests": [
{
"name": "test_prob1 (tests.TestAutograder)",
"score": 1.0,
"max_score": 1.0,
"number": "1"
},
],
"leaderboard": [],
"execution_time": "0.00",
"score": 10.0
}
Expected behavior
Should have produced the following results.json
file:
json
{
"tests": [
{
"name": "A human-readable name.",
"score": 1.0,
"max_score": 1.0,
"number": "1"
},
],
"leaderboard": [],
"execution_time": "0.00",
"score": 10.0
}
Additional context Removing the new-line character seems to fix the issue. I.e. the following produces the expected result. ```python import unittest from gradescope_utils.autograder_utils.decorators import weight, number
class TestAutograder(unittest.TestCase): @weight(1.0) @number("1") def test_prob1(self): """A human-readable name.""" pass ``` This also seems to only be the case inside of Gradescope's docker containers used for actually grading student submissions. This did not happen when I ran the code on my macbook.
When a student submits code that breaks a test but it's not due to an assertion error, the feedback is either confusing or misleading.
For example, if a student has a simple KeyError mistake
def my_code(dataframe):
return dataframe['SalesPerson'] # assume SalesPerson is not a valid key
The test will fail but with the message:
"Test Failed: 'SalesPerson'
That really offers no help
Describe the solution you'd like An easy solution is to provide the class of the exception or error:
"Test Failed: <class 'KeyError'> 'SalesPerson'\n"
The fix is simply in json_test_runner.py (buildResult)
line 77
``` if err: if err[0] is AssertionError: output += "Test Failed: {0}\n".format(err[1]) else: output += "Test Failed: {0} {1}\n".format(err[0], err[1])
```
Describe alternatives you've considered A similar pull request
However with that solution you get the following:
"Test Failed: 'SalesPerson'\nhashtable_class_helper.pxi:pandas._libs.hashtable.PyObjectHashTable.get_item line 1627: \n"
In this context, the backtrace is not helpful to the student. Perhaps a config option?
Also, in that pull request it should not use isinstance()
to test the error class.
(tested in python3.6).
Additional context
When student code generates exceptions, e.g. IndexError, tests fail without any indication of the root cause, making it difficult for students to debug their code. This change to the JSON test runner provides context by outputting the last stack frame (easy to change for last N frames).
One of the issues with Python testing, is that it's easy for students to read directories and figure out what files to potentially read. Although one could argue that a student who has figured this out probably should deserve to pass the tests. However, this kind of information then spreads.
There's many ways we mitigate this but all of them involve a lot of jumping through hoops (dynamically renaming the tests, removing the test files after they are loaded but before the students code is loaded), etc (which only work if in a sandboxed environment).
A simple and effective way to prevent this would be to allow the initialization of JSONTestRunner to take a parameter(s) to limit how much stdout and stderr is written out in the results. That's the most likely way for students to get information back. If both stdout and stderr are truncated to a specified maximum amount, then it allows both the framework to print relevant messages, but also keeps students from reading the test files.
Another option would be allow tests cases to write to a logfile that is then sent back to stdout first and anything else truncated.
https://docs.python.org/3/library/unittest.html#distinguishing-test-iterations-using-subtests
Makes it easier to script parametrized tests.
@number
to a string by @trombonehero in https://github.com/gradescope/gradescope-utils/pull/20Full Changelog: https://github.com/gradescope/gradescope-utils/compare/v0.4.0...v0.5.0
Adds a callback function to JSONTestRunner which can be used to modify the autograder results at the end of the test suite but before they are written to disk.
Usage Example:
```python def post_process(results): results["score"] = 9001
if name == 'main': suite = unittest.defaultTestLoader.discover('tests')
JSONTestRunner(visibility='visible', post_processor=post_process).run(suite)
```
https://github.com/gradescope/gradescope-utils/pull/16
The @number
decorator allows setting the "number" field on tests, which is used to sort the tests when displayed on Gradescope. See the format specification for more information.
Adds a new decorator, @partial_credit
, which allows setting the final score directly for cases where you want to give partial credit.
When using it, you don't need to use the @weight
decorator (you pass in the test weight to @partial_credit
).
https://github.com/gradescope/gradescope-utils/pull/8
JSONTestRunner now accepts options for setting the top-level visibility
and stdout_visibility
fields (see the docs for more details).
gradescope python autograder