Assertions Reference
All assertion functions follow the same pattern: they take (case, outputs, *args, **kwargs)
and return (pytest.ExitCode.OK, "") on success or (pytest.ExitCode.TESTS_FAILED, error_info)
on failure. The case and outputs arguments are supplied automatically by the harness;
the *args and **kwargs come from the assertions dict in your TestSubtask.
Summary
Function |
Purpose |
Typical Submission Type |
|---|---|---|
|
Exact equality |
Function, code string |
|
Approximate equality (numpy) |
Function, code string |
|
Same variable names in scope |
Code string |
|
Same types for named variables |
Code string |
|
Container contents match (with type coercion) |
Code string, function |
|
Expected exception was raised |
Function (with |
|
Written file contents match |
Path/module |
|
Execution time within bounds |
Any |
|
Object attribute values match |
Class |
|
Object attributes approximately match |
Class |
|
Object has required methods/attributes |
Class |
|
Function calls expected callees |
Path/module (advanced) |
|
Objects imported from correct modules |
Path/module (experimental) |
Value Assertions
equal_value
equal_value(case, outputs, *vars, **kwargs)
Tests for exact equality between expected and actual outputs.
Positional outputs (functions): compares return values element-by-element.
Named outputs (code strings): pass variable names as *vars to compare specific variables.
# Function: compare return value
assertions = {equal_value: ((), {})}
# Code string: compare variables a and b
assertions = {equal_value: (("a", "b"), {})}
almost_equal
almost_equal(case, outputs, *vars, atol=1e-7, rtol=1e-7, **kwargs)
Tests for approximate equality using numpy.testing.assert_allclose.
Falls back to exact equality for non-numeric types.
Parameters:
*vars: variable names to compare (for named outputs)atol: absolute tolerance (default1e-7)rtol: relative tolerance (default1e-7)
# Function returning floats
assertions = {almost_equal: ((), {"atol": 1e-6, "rtol": 1e-6})}
# Code string: check variable "result" with tolerance
assertions = {almost_equal: (("result",), {"atol": 1e-4})}
equal_contents
equal_contents(case, outputs, *vars, **kwargs)
Compares container contents with type coercion — the actual output is cast to the
expected type before comparison. Useful when students might return a list where a
tuple was expected.
assertions = {equal_contents: (("my_list",), {})}
Scope Assertions
equal_scope
equal_scope(case, outputs, *args, **kwargs)
Tests that the set of variable names in the output scope matches the expected scope exactly. No extra arguments needed.
assertions = {equal_scope: ((), {})}
equal_types
equal_types(case, outputs, *vars, **kwargs)
Tests that the types of named variables match between expected and actual outputs.
assertions = {equal_types: (("a", "b"), {})}
Exception Assertions
raises
raises(case, outputs, *exception_types, **kwargs)
When TestCase.raises=True, the harness catches the exception and passes it as outputs.
This assertion verifies the exception is an instance of one of the given types.
case = TestCase(inputs=((1, 0), {}), expected=((), {}), raises=True)
assertions = {raises: ((ZeroDivisionError,), {})}
File Assertions
file_contents
file_contents(case, *args, **kwargs)
Compares the contents of files listed in case.expected[1] (a dict mapping filenames to
expected bytes) against the actual file contents on disk. The comparison is byte-for-byte.
case = TestCase(
inputs=((), {}),
expected=((), {"output.txt": b"Hello, World!\n"}),
)
assertions = {file_contents: ((), {})}
Timing Assertions
time_bounds
time_bounds(case, outputs, *args, **kwargs)
Tests that the execution time (outputs[2]) falls within case.timing bounds.
The timing tuple is (lower_bound, upper_bound) in seconds; use None for unbounded.
case = TestCase(
inputs=((large_input,), {}),
expected=((result,), {}),
timing=(None, 2.0), # must finish within 2 seconds
)
assertions = {time_bounds: ((), {})}
Object Assertions
equal_attributes
equal_attributes(case, outputs, *attrs, **kwargs)
Compares attribute values between expected and actual class instances.
The expected instance comes from case.expected[0][0], the actual from outputs[0][0].
assertions = {equal_attributes: (("x", "y"), {})}
close_attributes
close_attributes(case, outputs, *attrs, **kwargs)
Like equal_attributes but uses numpy.testing.assert_allclose for comparison.
Accepts atol and rtol keyword arguments.
assertions = {close_attributes: (("x", "y"), {"atol": 1e-6, "rtol": 1e-6})}
has_method
has_method(case, outputs, *method_names, **type_hints)
Tests that the return object has the specified methods or attributes.
Optional **type_hints map attribute names to expected types.
assertions = {has_method: (("__repr__", "__add__"), {"x": float, "y": float})}
Advanced Assertions
calls
calls(case, outputs, caller, **callees)
Tests that calling caller on the return object triggers the expected calls to callees.
Uses unittest.mock.patch.object internally.
assertions = {calls: (("main",), {"helper": [((1, 2), {})]})}
This verifies that calling obj.main() causes obj.helper(1, 2) to be called.
has_import
Warning
has_import is experimental and has known compatibility issues.
It uses case.return_object (a dynamic attribute not declared on TestCase)
and is not wrapped with the standard @_log decorator pipeline.
Use with caution.
Tests whether objects in a module were imported from the correct locations.