def test_with(index, context_vals=False, # whether to check number of context vals context_tests=None, # check on context expressions body=None, undefined_msg=None, context_vals_len_msg=None, context_vals_msg=None, expand_message=True, state=None): """Test a with statement. with open_file('...') as bla: [ open_file('...').__enter__() ] with open_file('...') as file: [ ] """ rep = Reporter.active_reporter rep.set_tag("fun", "test_with") check_with = partial(check_node, 'withs', index-1, "`with` statement", MSG_MISSING, state=state) child = check_with(MSG_PREPEND if expand_message else "") child2 = check_with(MSG_PREPEND2 if expand_message else "") quiet_child = quiet(1, child) if context_vals: # test num context vars ---- too_many = len(child.student_parts['context']) > len(child.solution_parts['context']) if too_many: _msg = child.build_message(MSG_NUM_CTXT) rep.do_test(Test(Feedback(_msg, child.student_tree))) # test context var names ---- for i in range(len(child.solution_parts['context'])): ctxt_state = check_part_index('context', i, "", state=child) has_equal_part('target_vars', MSG_CTXT_NAMES, state=ctxt_state) # Context sub tests ---- if context_tests and not isinstance(context_tests, list): context_tests = [context_tests] for i, context_test in enumerate(context_tests or []): # partial the substate check, because the function uses two prepended messages check_context = partial(check_part_index, 'context', i, "%s context"%utils.get_ord(i+1), MSG_NUM_CTXT2) check_context(state=child) # test exist ctxt_state = check_context(state=child2) # sub tests multi(context_test, state=ctxt_state) # Body sub tests ---- if body is not None: body_state = check_part('body', 'body', state=child2) with_context(body, state=body_state)
def test_try_except(index=1, not_called_msg=None, body=None, handlers={}, except_missing_msg = None, orelse=None, orelse_missing_msg=None, finalbody=None, finalbody_missing_msg=None, expand_message=True, state=None): """Test whether the student correctly coded a `try-except` block. This function allows you to test specific parts of a try-except block. A try-except block consists of 4 parts: a body, error handlers, plus (rarely) an else and final block. :: try: print(hello) except NameError: print('hello what?') except: print('unexplained error') else: print('else block') finally: print('final block') Args: index (int): index of the try-except block to check. not_called_msg: override the default message when too few try-except blocks found in student code. body: sub-sct to test the code of the `try` block. handlers: a dictionary, where the keys are the error classes you expect the student to capture (for the general `except:`, use `'all'`), and the values are sub-SCTs for each of these `except` blocks. except_missing_message: override the default message when a expect block in the handlers arg is missing. orelse: similar to body, but for the else block. finalbody: similar to body, but for the finally block. _missing_msg: custom messages if the orelse, or finalbody pieces are missing. """ rep = Reporter.active_reporter rep.set_tag("fun", "test_try_except") # TODO: alternatively, could have missing_msg not use prepended messages # then we wouldn't have to run check_part twice for everything child = check_node('try_excepts', index-1, "try-except block", MSG_MISSING, MSG_PREPEND, state) quiet_child = quiet(1, state=child) multi(body, state=check_part("body", "body", child)) # subtests # handler tests for key,value in handlers.items(): incorrect_part = "{} `except` block".format('general' if key == 'all' else "`%s`"%key) # run to see if index exists, since the message depends on using the quiet child :o check_handler = partial(check_part_index, 'handlers', key, incorrect_part, MSG_MISSING_PART) check_handler(state=quiet_child) # exists multi(value, state=check_handler(state=child)) # subtests # test orelse and finalbody check = partial(check_part, missing_msg = MSG_MISSING_PART) # test orelse if child.solution_parts['orelse']: check('orelse', "`else` part", quiet_child) # exists multi(orelse, state=check('orelse', "`else` part", child)) # subtests # test orelse if child.solution_parts['finalbody']: check('finalbody', "`finally` part", quiet_child) # exists multi(finalbody, state=check('finalbody', "`finally` part", child)) # subtests
def test_with( index, context_vals=False, # whether to check number of context vals context_tests=None, # check on context expressions body=None, undefined_msg=None, context_vals_len_msg=None, context_vals_msg=None, expand_message=True, state=None): """Test a with statement. with open_file('...') as bla: [ open_file('...').__enter__() ] with open_file('...') as file: [ ] """ rep = Reporter.active_reporter rep.set_tag("fun", "test_with") check_with = partial(check_node, 'withs', index - 1, "`with` statement", MSG_MISSING, state=state) child = check_with(MSG_PREPEND if expand_message else "") child2 = check_with(MSG_PREPEND2 if expand_message else "") quiet_child = quiet(1, child) if context_vals: # test num context vars ---- too_many = len(child.student_parts['context']) > len( child.solution_parts['context']) if too_many: _msg = child.build_message(MSG_NUM_CTXT) rep.do_test(Test(Feedback(_msg, child.student_tree))) # test context var names ---- for i in range(len(child.solution_parts['context'])): ctxt_state = check_part_index('context', i, "", state=child) has_equal_part('target_vars', MSG_CTXT_NAMES, state=ctxt_state) # Context sub tests ---- if context_tests and not isinstance(context_tests, list): context_tests = [context_tests] for i, context_test in enumerate(context_tests or []): # partial the substate check, because the function uses two prepended messages check_context = partial(check_part_index, 'context', i, "%s context" % utils.get_ord(i + 1), MSG_NUM_CTXT2) check_context(state=child) # test exist ctxt_state = check_context(state=child2) # sub tests multi(context_test, state=ctxt_state) # Body sub tests ---- if body is not None: body_state = check_part('body', 'body', state=child2) with_context(body, state=body_state)
def test_try_except(index=1, not_called_msg=None, body=None, handlers={}, except_missing_msg = None, orelse=None, orelse_missing_msg=None, finalbody=None, finalbody_missing_msg=None, expand_message=True, state=None): """Test whether the student correctly coded a `try-except` block. This function allows you to test specific parts of a try-except block. A try-except block consists of 4 parts: a body, error handlers, plus (rarely) an else and final block. :: try: print(hello) except NameError: print('hello what?') except: print('unexplained error') else: print('else block') finally: print('final block') Args: index (int): index of the try-except block to check. not_called_msg: override the default message when too few try-except blocks found in student code. body: sub-sct to test the code of the `try` block. handlers: a dictionary, where the keys are the error classes you expect the student to capture (for the general `except:`, use `'all'`), and the values are sub-SCTs for each of these `except` blocks. except_missing_message: override the default message when a expect block in the handlers arg is missing. orelse: similar to body, but for the else block. finalbody: similar to body, but for the finally block. _missing_msg: custom messages if the orelse, or finalbody pieces are missing. """ rep = Reporter.active_reporter # TODO: alternatively, could have missing_msg not use prepended messages # then we wouldn't have to run check_part twice for everything child = check_node('try_excepts', index-1, "try-except block", MSG_MISSING, MSG_PREPEND, state) quiet_child = quiet(1, state=child) multi(body, state=check_part("body", "body", child)) # subtests # handler tests for key,value in handlers.items(): incorrect_part = "{} `except` block".format('general' if key == 'all' else "`%s`"%key) # run to see if index exists, since the message depends on using the quiet child :o check_handler = partial(check_part_index, 'handlers', key, incorrect_part, MSG_MISSING_PART) check_handler(state=quiet_child) # exists multi(value, state=check_handler(state=child)) # subtests # test orelse and finalbody check = partial(check_part, missing_msg = MSG_MISSING_PART) # test orelse if child.solution_parts['orelse']: check('orelse', "`else` part", quiet_child) # exists multi(orelse, state=check('orelse', "`else` part", child)) # subtests # test orelse if child.solution_parts['finalbody']: check('finalbody', "`finally` part", quiet_child) # exists multi(finalbody, state=check('finalbody', "`finally` part", child)) # subtests
def test_with( index, context_vals=False, # whether to check number of context vals context_tests=None, # check on context expressions body=None, undefined_msg=None, context_vals_len_msg=None, context_vals_msg=None, expand_message=True, state=None): """Test a with statement. with open_file('...') as bla: [ open_file('...').__enter__() ] with open_file('...') as file: [ ] """ rep = Reporter.active_reporter check_with = partial(check_node, 'withs', index - 1, "`with` statement", MSG_MISSING, state=state) child = check_with(MSG_PREPEND if expand_message else "") child2 = check_with(MSG_PREPEND2 if expand_message else "") quiet_child = quiet(1, child) if context_vals: # test context var names ---- has_context(incorrect_msg=context_vals_msg or MSG_CTXT_NAMES, exact_names=True, state=child) # test num context vars ---- has_equal_part_len('context', MSG_NUM_CTXT, state=child) # Context sub tests ---- if context_tests and not isinstance(context_tests, list): context_tests = [context_tests] for i, context_test in enumerate(context_tests or []): # partial the substate check, because the function uses two prepended messages check_context = partial(check_part_index, 'context', i, "%s context" % utils.get_ord(i + 1), MSG_NUM_CTXT2) check_context(state=child) # test exist ctxt_state = check_context(state=child2) # sub tests multi(context_test, state=ctxt_state) # Body sub tests ---- if body is not None: body_state = check_part('body', 'body', state=child2) with_context(body, state=body_state)