Skip to main content

Grading Utils

A collection of utilities for grading Python assignments.

Utilities are based off some common unit testing patterns. Overall, syntax is modelled off JavaScript's Jest syntax, with some modifications (hence camelCase, for example).

Design Philosophy:

  • security
  • simplicity
  • immutability

Matchers and Modifiers

The most common operations with this module will involve matching test values to expected values. All matchers begin with the expect(value) syntax, and are chained by some matcher. For example, if we want to test $f(x) = x^2$, we write:

from grading_utils.GradingUtils import expect

expect(f(2)).toEqual(4)

In this case, we could also write:

expect(f(2)).toBe(4)

which will check for referential equality amonst the two objects. However, use caution when using .toBe() to compare objects for equality, as this will not use obj.__eq__ or obj.__hash__ to compare objects. Matchers behave similarly to Python's assert, but provide more context on error.

Generally, matchers accept any type for which they are logically defined. For example, .toBeApprox(2.5, eps=0.1) works for numeric types.

Matchers with Callable Objects

Typically, we want to check the output of a function, so we call the function and pass its result to the expectation (expect(f(x))). Occasionally, matchers need to track the way functions behave. For example, let avg(l: iter) = sum(iter) / len(iter). If we want to check whether [] throws ZeroDivisionError, we can write:

expect(avg).toThrow(ZeroDivisionError, [])

Thus, we pass the function (uncalled) to our expect call, then we pass toThrow's custom argument (the exception to except), and then all arguments to the function to the .toThrow call. This is an unfortunate limitation, but this works for the time being. In the future, some decorator workaround may be implemented.

List of Matchers

The following matchers are currently defined:

  • toBe
  • toEqual
  • toBeApprox
  • toMatchType
  • toMatch
  • toContain
  • toBeGreaterThan
  • toBeLessThan
  • toThrow

Modifiers

Modifiers are used to modify the behavior of matchers, by modifying the underling "Expectation" object. Most commonly, we may want to expect that a certain condition is not met. We can chain modifiers for thus purpose. Modifiers use ._modifier_name syntax, with () if arguments are needed. There are currently only 3 modifiers:

._not

This modifier negates the expectation. For $$f(x) = x^2$$:

expect(f(2))._not.toBeGreaterThan(2) # throws GradingError
._exception(e)

If we want to throw a custom exception when a matcher fails.

expect(f(2))._exception(UrAnAwfulProgrammerError).toBe(4)
._maxtime(s)

This is one of 3 existing options for timing. The _maxtime modifier should be used similarly to a matcher with callables. To set a 2-second time limit on slow_reducer(some_set), and expect a result of True we write:

expect(slow_reducer)._maxtime(2, some_set).toBe(True)

For all timing semantics, see the dedicated timing section.

Looking Forward

_and and _or are some potential future modifiers.

Timing

One critical aspect of any timer implementation is that for long running functions, we want to keep grading time down; execution should be immediately stopped when the time limit is reached, with a fail error. This avoids functions from taking needlessly long times when they will fail anyways. All times are given in seconds.

Three methods are provided for time limiting functions:

with timer(5):
    expect(slow_reducer(some_set)).toBe(True)

Or, when defining functions:

@time_limit(5)
def slow_reducer(some_set):
    pass # implementation here
expect(slow_reducer(some_set)).toBe(True)

Naturally, this can be easily used to wrap student solutions.

Finally, the _maxtime modifier can be used directly:

expect(slow_reducer)._maxtime(2, some_set).toBe(True)

Release files for grading-utils 0.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for grading-utils 0.2
File Size Uploaded
grading-utils-0.2.tar.gz 5.1 kB Details

Release files / grading-utils-0.2.tar.gz

Download URL grading-utils-0.2.tar.gz
Size 5.1 kB
Tags Source
SHA-256 checksum
How to use checksums
7c1398f282070652dc91113d90b49d5a4bc269f0a1fbe3c10c75cfe9abed3260
BLAKE2b-256 checksum
How to use checksums
fc83f861567848f27f6061df0586296be18fc3e5b0f80cb4c08214af39333416
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.7.1 importlib_metadata/4.10.0 pkginfo/1.8.2 requests/2.27.1 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.10.0

Release history Release notifications | RSS feed

This release

0.2 This release

1 release file

0.1.1

1 release file

0.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page