def test_lambda_function(index, arg_names=True, arg_defaults=True, body=None, results=[], errors=[], not_called_msg=None, nb_args_msg=None, arg_names_msg=None, arg_defaults_msg=None, wrong_result_msg=None, no_error_msg=None, expand_message=True, state=None): """Test a lambda function definition. This function helps you test a lambda function definition. Generally four things can be tested: 1) The argument names of the function (including if the correct defaults are used) 2) The body of the functions (does it output correctly, are the correct functions used) 3) The return value with a certain input 4) Whether certain inputs generate an error Custom feedback messages can be set for all these parts, default messages are generated automatically if none are set. Args: index (int): the number of the lambda function you want to test. arg_names (bool): if True, the argument names will be tested, if False they won't be tested. Defaults to True. arg_defaults (bool): if True, the default values of the arguments will be tested, if False they won't be tested. Defaults to True. body: this arguments holds the part of the code that will be ran to check the body of the function definition. It should be passed as a lambda expression or a function. The functions that are ran should be other pythonwhat test functions, and they will be tested specifically on only the body of the for loop. Defaults to None. results (list(str)): a list of strings representing function calls to the lam function. The lam function will be replaced by the actual lambda function from the student and solution code. The result of calling the lambda function will be compared between student and solution. errors (list(str)): a list of strings representing function calls to the lam function. The lam function will be replaced by the actual lambda function from the student and solution code. It will be checked if an error is generated appropriately for the specified inputs. not_called_msg (str): message if the function is not defined. nb_args_msg (str): message if the number of arguments do not matched. arg_names_msg (str): message if the argument names do not match. arg_defaults_msg (str): message if the argument default values do not match. wrong_result_msg (str): message if one of the tested function calls' result did not match. no_error_msg (str): message if one of the tested function calls' result did not generate an error. expand_message (bool): only relevant if there is a body test. If True, feedback messages defined in the body test will be preceded by 'In your definition of ___, '. If False, :code:`test_function_definition()` will generate no extra feedback if the body test fails. Defaults to True. """ rep = Reporter.active_reporter rep.set_tag("fun", "test_lambda_function") # what the lambda will be referred to as typestr = "the {} lambda function".format(get_ord(index)) get_func_child = partial(check_node, 'lambda_functions', index - 1, typestr, not_called_msg or MSG_MISSING, state=state) child = get_func_child(expand_msg=MSG_PREPEND if expand_message else "") # make a temporary child states, to reflect that there were two types of # messages prepended in the original function quiet_child = get_func_child(expand_msg="") prep_child2 = get_func_child( expand_msg=MSG_PREPEND_ARG if expand_message else "") test_args(arg_names, arg_defaults, nb_args_msg, arg_names_msg, arg_defaults_msg, prep_child2, quiet_child) multi(body, state=check_part('body', "", child)) # Test function calls ----------------------------------------------------- student_fun = state.student_lambda_functions[index - 1]['node'] solution_fun = state.solution_lambda_functions[index - 1]['node'] for el in results: argstr = el.replace('lam', '') call(el, incorrect_msg=wrong_result_msg or MSG_RES_INCORRECT, error_msg=wrong_result_msg or MSG_RES_ERROR, argstr=argstr, state=child) for el in errors: argstr = el.replace('lam', '') call(el, 'error', incorrect_msg=no_error_msg or MSG_ERR_WRONG, error_msg=no_error_msg or MSG_ERR_WRONG, argstr=argstr, state=child)
def test_lambda_function(index, arg_names=True, arg_defaults=True, body=None, results=[], errors=[], not_called_msg=None, nb_args_msg=None, arg_names_msg=None, arg_defaults_msg=None, wrong_result_msg=None, no_error_msg=None, expand_message=True, state=None): """Test a lambda function definition. This function helps you test a lambda function definition. Generally four things can be tested: 1) The argument names of the function (including if the correct defaults are used) 2) The body of the functions (does it output correctly, are the correct functions used) 3) The return value with a certain input 4) Whether certain inputs generate an error Custom feedback messages can be set for all these parts, default messages are generated automatically if none are set. Args: index (int): the number of the lambda function you want to test. arg_names (bool): if True, the argument names will be tested, if False they won't be tested. Defaults to True. arg_defaults (bool): if True, the default values of the arguments will be tested, if False they won't be tested. Defaults to True. body: this arguments holds the part of the code that will be ran to check the body of the function definition. It should be passed as a lambda expression or a function. The functions that are ran should be other pythonwhat test functions, and they will be tested specifically on only the body of the for loop. Defaults to None. results (list(str)): a list of strings representing function calls to the lam function. The lam function will be replaced by the actual lambda function from the student and solution code. The result of calling the lambda function will be compared between student and solution. errors (list(str)): a list of strings representing function calls to the lam function. The lam function will be replaced by the actual lambda function from the student and solution code. It will be checked if an error is generated appropriately for the specified inputs. not_called_msg (str): message if the function is not defined. nb_args_msg (str): message if the number of arguments do not matched. arg_names_msg (str): message if the argument names do not match. arg_defaults_msg (str): message if the argument default values do not match. wrong_result_msg (str): message if one of the tested function calls' result did not match. no_error_msg (str): message if one of the tested function calls' result did not generate an error. expand_message (bool): only relevant if there is a body test. If True, feedback messages defined in the body test will be preceded by 'In your definition of ___, '. If False, :code:`test_function_definition()` will generate no extra feedback if the body test fails. Defaults to True. """ rep = Reporter.active_reporter rep.set_tag("fun", "test_lambda_function") # what the lambda will be referred to as typestr = "the {} lambda function".format(get_ord(index)) get_func_child = partial(check_node, 'lambda_functions', index-1, typestr, not_called_msg or MSG_MISSING, state=state) child = get_func_child(expand_msg = MSG_PREPEND if expand_message else "") # make a temporary child states, to reflect that there were two types of # messages prepended in the original function quiet_child = get_func_child(expand_msg = "") prep_child2 = get_func_child(expand_msg = MSG_PREPEND_ARG if expand_message else "") test_args(arg_names, arg_defaults, nb_args_msg, arg_names_msg, arg_defaults_msg, prep_child2, quiet_child) multi(body, state=check_part('body', "", child)) # Test function calls ----------------------------------------------------- student_fun = state.student_lambda_functions[index-1]['node'] solution_fun = state.solution_lambda_functions[index-1]['node'] for el in results: argstr = el.replace('lam', '') call(el, incorrect_msg = wrong_result_msg or MSG_RES_INCORRECT, error_msg = wrong_result_msg or MSG_RES_ERROR, argstr = argstr, state = child) for el in errors: argstr = el.replace('lam', '') call(el, 'error', incorrect_msg = no_error_msg or MSG_ERR_WRONG, error_msg = no_error_msg or MSG_ERR_WRONG, argstr = argstr, state = child)
def test_function_definition(name, arg_names=True, arg_defaults=True, body=None, results=None, outputs=None, errors=None, not_called_msg=None, nb_args_msg=None, other_args_msg=None, arg_names_msg=None, arg_defaults_msg=None, wrong_result_msg=None, wrong_output_msg=None, no_error_msg=None, wrong_error_msg=None, state=None): """Test a function definition. This function helps you test a function definition. Generally four things can be tested: 1) The argument names of the function (including if the correct defaults are used) 2) The body of the functions (does it output correctly, are the correct functions used) 3) The return value with a certain input 4) The output value with a certain input 5) Whether certain inputs generate an error and what type of error Custom feedback messages can be set for all these parts, default messages are generated automatically if none are set. Args: name (str): the name of the function definition to be tested. arg_names (bool): if True, the argument names will be tested, if False they won't be tested. Defaults to True. arg_defaults (bool): if True, the default values of the arguments will be tested, if False they won't be tested. Defaults to True. body: this arguments holds the part of the code that will be ran to check the body of the function definition. It should be passed as a lambda expression or a function. The functions that are ran should be other pythonwhat test functions, and they will be tested specifically on only the body of the for loop. Defaults to None. results (list(list)): a list of lists representing arguments that should be passed to the defined function. These arguments are passed to the function in the student environment and the solution environment, the results (what's returned) are compared. outputs (list(list)): a list of lists representing arguments that should be passed to the defined function. These arguments are passed to the function in the student environment and the solution environment, the outpus are compared. errors (list(list)): a list of lists representing arguments that should be passed to the defined function. These arguments are passed to the function in the student environment and the solution environment, the errors they generate are compared. not_called_msg (str): message if the function is not defined. nb_args_msg (str): message if the number of arguments do not matched. arg_names_msg (str): message if the argument names do not match. arg_defaults_msg (str): message if the argument default values do not match. wrong_result_msg (str): message if one of the tested function calls' result did not match. wrong_output_msg (str): message if one of the tested functions calls' output did not match. no_error_msg (str): message if one of the tested function calls' result did not generate an error. wrong_error_msg (str): message if the error that one of the tested function calls generated did not match. :Example: Student code:: def shout( word, times = 3): shout_word = not_word + '???' print( shout_word ) return word * times Solution code:: def shout( word = 'help', times = 3 ): shout_word = word + '!!!' print( shout_word ) return word * times SCT:: test_function_definition('shout') # fail test_function_definition('shout', arg_defaults = False) # pass test_function_definition('shout', arg_defaults = False, # fail outputs = [('help')]) test_function_definition('shout', arg_defaults = False, # pass results = [('help', 2)]) test_function_definition('shout', args_defaults = False # pass body = test_function('print', args = []])) """ # what the function will be referred to as child = check_node('function_defs', name, 'definition of `{{index}}()`', state=state) test_args(arg_names, arg_defaults, nb_args_msg, arg_names_msg, arg_defaults_msg, child) multi(body, state=check_part('body', "", state=child)) # Test function calls ----------------------------------------------------- for el in (results or []): el = fix_format(el) call(el, 'value', incorrect_msg = wrong_result_msg, error_msg = wrong_result_msg, argstr = '`{}{}`'.format(name, stringify(el)), state=child) for el in (outputs or []): el = fix_format(el) call(el, 'output', incorrect_msg = wrong_output_msg, error_msg = wrong_output_msg, argstr = '`{}{}`'.format(name, stringify(el)), state=child) for el in (errors or []): el = fix_format(el) call(el, 'error', incorrect_msg = wrong_error_msg, error_msg = no_error_msg, argstr = '`{}{}`'.format(name, stringify(el)), state=child)
def test_function_definition(name, arg_names=True, arg_defaults=True, body=None, results=None, outputs=None, errors=None, not_called_msg=None, nb_args_msg=None, other_args_msg=None, arg_names_msg=None, arg_defaults_msg=None, wrong_result_msg=None, wrong_output_msg=None, no_error_msg=None, wrong_error_msg=None, expand_message=True, state=None): """Test a function definition. This function helps you test a function definition. Generally four things can be tested: 1) The argument names of the function (including if the correct defaults are used) 2) The body of the functions (does it output correctly, are the correct functions used) 3) The return value with a certain input 4) The output value with a certain input 5) Whether certain inputs generate an error and what type of error Custom feedback messages can be set for all these parts, default messages are generated automatically if none are set. Args: name (str): the name of the function definition to be tested. arg_names (bool): if True, the argument names will be tested, if False they won't be tested. Defaults to True. arg_defaults (bool): if True, the default values of the arguments will be tested, if False they won't be tested. Defaults to True. body: this arguments holds the part of the code that will be ran to check the body of the function definition. It should be passed as a lambda expression or a function. The functions that are ran should be other pythonwhat test functions, and they will be tested specifically on only the body of the for loop. Defaults to None. results (list(list)): a list of lists representing arguments that should be passed to the defined function. These arguments are passed to the function in the student environment and the solution environment, the results (what's returned) are compared. outputs (list(list)): a list of lists representing arguments that should be passed to the defined function. These arguments are passed to the function in the student environment and the solution environment, the outpus are compared. errors (list(list)): a list of lists representing arguments that should be passed to the defined function. These arguments are passed to the function in the student environment and the solution environment, the errors they generate are compared. not_called_msg (str): message if the function is not defined. nb_args_msg (str): message if the number of arguments do not matched. arg_names_msg (str): message if the argument names do not match. arg_defaults_msg (str): message if the argument default values do not match. wrong_result_msg (str): message if one of the tested function calls' result did not match. wrong_output_msg (str): message if one of the tested functions calls' output did not match. no_error_msg (str): message if one of the tested function calls' result did not generate an error. wrong_error_msg (str): message if the error that one of the tested function calls generated did not match. expand_message (bool): only relevant if there is a body test. If True, feedback messages defined in the body test will be preceded by 'In your definition of ___, '. If False, `test_function_definition()` will generate no extra feedback if the body test fails. Defaults to True. :Example: Student code:: def shout( word, times = 3): shout_word = not_word + '???' print( shout_word ) return word * times Solution code:: def shout( word = 'help', times = 3 ): shout_word = word + '!!!' print( shout_word ) return word * times SCT:: test_function_definition('shout') # fail test_function_definition('shout', arg_defaults = False) # pass test_function_definition('shout', arg_defaults = False, # fail outputs = [('help')]) test_function_definition('shout', arg_defaults = False, # pass results = [('help', 2)]) test_function_definition('shout', args_defaults = False # pass body = test_function('print', args = []])) """ MSG_MISSING = "FMT:You didn't define the following function: {typestr}." MSG_PREPEND = "FMT:Check your definition of {typestr}. " # what the function will be referred to as typestr = "`{}()`".format(name) get_func_child = partial(check_node, 'function_defs', name, typestr, not_called_msg or MSG_MISSING, state=state) child = get_func_child(expand_msg=MSG_PREPEND if expand_message else "") # make a temporary child state, to reflect that there were two types of # messages prepended in the original function quiet_child = get_func_child(expand_msg="") prep_child2 = get_func_child(expand_msg=MSG_PREPEND) test_args(arg_names, arg_defaults, nb_args_msg, arg_names_msg, arg_defaults_msg, prep_child2, quiet_child) multi(body, state=check_part('body', "", expand_msg=None if expand_message else "", state=child)) # Test function calls ----------------------------------------------------- #fun_name = ("`%s()`" % name) for el in (results or []): el = fix_format(el) call(el, 'value', incorrect_msg=wrong_result_msg, error_msg=wrong_result_msg, argstr='`{}{}`'.format(name, stringify(el)), state=quiet_child) for el in (outputs or []): el = fix_format(el) call(el, 'output', incorrect_msg=wrong_output_msg, error_msg=wrong_output_msg, argstr='`{}{}`'.format(name, stringify(el)), state=quiet_child) for el in (errors or []): el = fix_format(el) call(el, 'error', incorrect_msg=wrong_error_msg, error_msg=no_error_msg, argstr='`{}{}`'.format(name, stringify(el)), state=quiet_child)
def test_function_definition(name, arg_names=True, arg_defaults=True, body=None, results=None, outputs=None, errors=None, not_called_msg=None, nb_args_msg=None, other_args_msg=None, arg_names_msg=None, arg_defaults_msg=None, wrong_result_msg=None, wrong_output_msg=None, no_error_msg=None, wrong_error_msg=None, expand_message=True, state=None): """Test a function definition. This function helps you test a function definition. Generally four things can be tested: 1) The argument names of the function (including if the correct defaults are used) 2) The body of the functions (does it output correctly, are the correct functions used) 3) The return value with a certain input 4) The output value with a certain input 5) Whether certain inputs generate an error and what type of error Custom feedback messages can be set for all these parts, default messages are generated automatically if none are set. Args: name (str): the name of the function definition to be tested. arg_names (bool): if True, the argument names will be tested, if False they won't be tested. Defaults to True. arg_defaults (bool): if True, the default values of the arguments will be tested, if False they won't be tested. Defaults to True. body: this arguments holds the part of the code that will be ran to check the body of the function definition. It should be passed as a lambda expression or a function. The functions that are ran should be other pythonwhat test functions, and they will be tested specifically on only the body of the for loop. Defaults to None. results (list(list)): a list of lists representing arguments that should be passed to the defined function. These arguments are passed to the function in the student environment and the solution environment, the results (what's returned) are compared. outputs (list(list)): a list of lists representing arguments that should be passed to the defined function. These arguments are passed to the function in the student environment and the solution environment, the outpus are compared. errors (list(list)): a list of lists representing arguments that should be passed to the defined function. These arguments are passed to the function in the student environment and the solution environment, the errors they generate are compared. not_called_msg (str): message if the function is not defined. nb_args_msg (str): message if the number of arguments do not matched. arg_names_msg (str): message if the argument names do not match. arg_defaults_msg (str): message if the argument default values do not match. wrong_result_msg (str): message if one of the tested function calls' result did not match. wrong_output_msg (str): message if one of the tested functions calls' output did not match. no_error_msg (str): message if one of the tested function calls' result did not generate an error. wrong_error_msg (str): message if the error that one of the tested function calls generated did not match. expand_message (bool): only relevant if there is a body test. If True, feedback messages defined in the body test will be preceded by 'In your definition of ___, '. If False, `test_function_definition()` will generate no extra feedback if the body test fails. Defaults to True. :Example: Student code:: def shout( word, times = 3): shout_word = not_word + '???' print( shout_word ) return word * times Solution code:: def shout( word = 'help', times = 3 ): shout_word = word + '!!!' print( shout_word ) return word * times SCT:: test_function_definition('shout') # fail test_function_definition('shout', arg_defaults = False) # pass test_function_definition('shout', arg_defaults = False, # fail outputs = [('help')]) test_function_definition('shout', arg_defaults = False, # pass results = [('help', 2)]) test_function_definition('shout', args_defaults = False # pass body = test_function('print', args = []])) """ rep = Reporter.active_reporter rep.set_tag("fun", "test_function_definition") # what the function will be referred to as typestr = "`{}()`".format(name) get_func_child = partial(check_node, 'function_defs', name, typestr, not_called_msg or MSG_MISSING, state=state) child = get_func_child(expand_msg = MSG_PREPEND if expand_message else "") # make a temporary child state, to reflect that there were two types of # messages prepended in the original function quiet_child = get_func_child(expand_msg = "") prep_child2 = get_func_child(expand_msg = MSG_PREPEND_ARG) test_args(arg_names, arg_defaults, nb_args_msg, arg_names_msg, arg_defaults_msg, prep_child2, quiet_child) multi(body, state=check_part('body', "", child)) # Test function calls ----------------------------------------------------- #fun_name = ("`%s()`" % name) for el in (results or []): el = fix_format(el) call(el, 'value', incorrect_msg = wrong_result_msg or MSG_RES_INCORRECT, error_msg = wrong_result_msg or MSG_RES_ERROR, argstr = name + stringify(el), state = quiet_child) for el in (outputs or []): el = fix_format(el) call(el, 'output', incorrect_msg = wrong_output_msg or MSG_OUT_INCORRECT, error_msg = wrong_output_msg or MSG_OUT_ERROR, argstr = name + stringify(el), state = quiet_child) for el in (errors or []): el = fix_format(el) call(el, 'error', incorrect_msg = wrong_error_msg or MSG_ERR_INCORRECT, error_msg = no_error_msg or MSG_ERR_NONE, argstr = name + stringify(el), state = quiet_child)