def cumulative(): scorer = CumulativeScoreKeeper() with let(__scorer, scorer): yield value(__scorer).suite_finished(scorer.score)
def weight(maximum): scorer = CumulativeScoreKeeper() with let(__scorer, scorer): yield score = scorer.score value(__scorer).suite_finished(score.rescale(maximum))
def function_reftest(identifier): if not identifier in dir(value(reference_module)): raise Exception(f'Bug in tests: reference module does not contain member called "{identifier}"') with when(defined(identifier, value(tested_module))), let(tested_function_name, identifier): reference_function = getattr(value(reference_module), identifier) tested_function = getattr(value(tested_module), identifier) with check_function_against_reference_implementation(tested=tested_function, reference=reference_function) as check: yield check
def all_or_nothing(): scorer = CumulativeScoreKeeper() with let(__scorer, scorer): yield score = scorer.score if not score.is_perfect: score = score.zero value(__scorer).suite_finished(score)
def when(condition): ''' Adds an extra condition ''' old_condition = value(__condition) with let(__condition, lambda: old_condition() and condition()): yield
def __load_module(filename, module_name, directory): # If no directory is specified, fetch the test file's directory if not directory: directory = value(test_directory) full_path = os.path.join(directory, filename) return load_code(full_path, module_name)
def failure_message_generator(*, failure, **kwargs): failure_message = value(__failure_message) if failure_message: return format.vbox(f'Verifying {call_string}', \ format.indent(2, failure_message), \ format.indent(2, str(failure))) else: raise Exception('Bug in reference tests: no failure message set')
def __add_callback(event, callback): ''' Helper function. Adds a callback to and event, the event being __passed, __failed or __skipped. ''' old_callback = value(event) chained = __chain(old_callback, callback) with let(event, chained): yield
def failure_callback(*, failure): nonlocal failure_index if failure_index != 1: print('-' * 40) generator = value(__failure_message_generator) message = generator(failure=failure) message_lines = format.hbox(f'[{failure_index}] ', message).format() print("\n".join(message_lines)) failure_index += 1
def check(*args, **kwargs): positional_parameter_names = __get_positional_parameter_names(reference) function_name = value(tested_function_name) positional_argument_strings = [ f'{name} = {str(arg)}' for name, arg in zip(positional_parameter_names, args) ] keyword_argument_strings = [ f'{k}={v}' for k, vi in kwargs.items() ] arguments_string = ', '.join(positional_argument_strings + keyword_argument_strings) call_string = f'{function_name}({arguments_string})' def failure_message_generator(*, failure, **kwargs): failure_message = value(__failure_message) if failure_message: return format.vbox(f'Verifying {call_string}', \ format.indent(2, failure_message), \ format.indent(2, str(failure))) else: raise Exception('Bug in reference tests: no failure message set') def test_function(): def check_return_values(expected, actual): __failure_message.value = f'Comparing return values' assert expected == actual, f'Expected {expected}, got {actual}' def check_positional_argument(index, name, expected, actual): __failure_message.value = f'Comparing {name} (positional argument #{index + 1})' assert expected == actual, f'Expected {expected}, got {actual}' def check_positional_arguments(names, expecteds, actuals): for (index, name, expected, actual) in zip(range(len(names)), names, expecteds, actuals): check_positional_argument(index, name, expected, actual) actual_args = deepcopy(args) actual_kwargs = deepcopy(kwargs) expected_args = deepcopy(args) expected_kwargs = deepcopy(kwargs) __failure_message.value = f'Exception occurred during function call' actual_result = tested(*actual_args, **actual_kwargs) expected_result = reference(*expected_args, **expected_kwargs) check_return_values(expected=expected_result, actual=actual_result) check_positional_arguments(positional_parameter_names, expected_args, actual_args) with reporting.default_failure_message_generator(failure_message_generator), \ let(__failure_message, None): test(test_function)
def current_test_function(): # Inside a @test annotated function, returns the function return value(__test_function)
def signal_passed(): value(__passed)()
def __should_test_run(): return value(__condition)()
def skipped(): value(__scorer).test_skipped()
def passed(): value(__scorer).test_passed()
def default_failure_message_generator(message_generator): if value(__failure_message_generator) != __dummy_failure_message_generator: yield else: with failure_message_generator(message_generator): yield
def signal_skipped(): value(__skipped)()
def failed(*args, **kwargs): value(__scorer).test_failed()
def signal_failed(exception): value(__failed)(failure=exception)