Source code for grader.wrappers

""" Wrappers to make writing tests easier """

#from macropy.tracing import macros, require
from .core import *
from .utils import *
from .assertions import *
from .decorators import *


[docs]def io_test(description, writes_list, expected_read): """ Tests whether after writing each element of writes_list to stdin we can find expected_read in the resulting output. Note that this also tests whether the program is waiting for before each write and that it's not after the last one. """ def f(module): for i, write in enumerate(writes_list): assert not module.finished, \ "Did you forget to use input()? Writes so far: %s" % writes_list[:i] module.stdout.reset() module.stdin.write(write) require_contains(module.stdout.new(), expected_read) assert module.finished, \ "Make sure there isn't a stray input() after your code" setDescription(f, description) return test(f)
[docs]def check_function(function_name, args, expected_result, description=None): """ Tests that calling function with the given name exists and calling it with args gives expected_result. If description is given, it is used as test name, else the description will before similar to "Check add(1, 2, 3) == 6" """ def f(m): assert hasattr(m, "module"), "Do not use input() in this solution" assert hasattr(m.module, function_name), \ "Please define the function with name " + function_name function = getattr(m.module, function_name) assertEquals(function(*args), expected_result) if description is None: description = "Check " + function_name + \ "(" + ", ".join(map(repr, args)) + ") == " + repr(expected_result) setDescription(f, description) return test(f)
[docs]def test_cases(test_args, description=None, **arg_functions): """ Decorator for generating multiple tests with additional arguments. :param test_args: Each element of the list is a list of arguments to add to test function call. :type test_args: [args...] :param str description: String or function, gets passed in keywords and arguments. :keyword function arg_functions: Keyword arguments for the test function. :return: list of test functions Example usage:: @test_cases( [[1, 2], [3, 4]], expected=lambda x, y: x+y, description="Adding {0} and {1} should yield {expected}" ) def t(m, a, b, expected): # a and b are either 1 and 2 or 3 and 4 assert a + b == expected This is equivelent to:: @test @set_description("Adding 1 and 2 should yield 3") def t_1(m): assert 1+2 == 3 @test @set_description("Adding 3 and 4 should yield 7") def t_2(m): assert 3+4 == 7 """ if description is None: description = ", ".join(str(i)+"={"+key+"}" for i, key in enumerate(test_args[0])) def calc_function_kwargs(values): out = {} for k, fun in arg_functions.items(): out[k] = fun(*values) return out def _inner(function): # remove from tests if there def make_f(args, kw): if is_function(description): test_desc = description(*args, **kw) else: test_desc = description.format(*args, **kw) @test @set_description(test_desc) def _inner(m, *extra_args, **extra_kw): _kw = dict(list(kw.items()) + list(extra_kw.items())) _args = list(args) + list(extra_args) function(m, *_args, **_kw) return _inner tests = [] for args in test_args: if not isinstance(args, list) and not isinstance(args, tuple): args = [args] kw = calc_function_kwargs(args) tests.append(make_f(args, kw)) return tests return _inner