def handles_stoptest_exceptions(self): ''' if stop test exception is thrown stop executing instructions ''' mock_fn = lancelot.MockSpec(name='mock_fn') mock_call = lancelot.MockSpec(name='mock_call') results = lancelot.MockSpec(name='results') a_list = [['id_', 'call', 'instance', 'fn', 'arg'], ['id_', 'call', 'instance2', 'fn2', 'arg2']] instructions = Instructions(a_list, lambda item: mock_fn.instruction_for(item)) spec = lancelot.Spec(instructions) ctx = ExecutionContext() msg = "I couldn't eat another thing. I'm absolutely stuffed." # Suppress warning log message that we know will be generated logger = logging.getLogger('Instructions') log_level = logger.getEffectiveLevel() logger.setLevel(logging.ERROR) try: spec.execute(ctx, results).should_collaborate_with( mock_fn.instruction_for(a_list[0]).will_return(mock_call), mock_call.execute(ctx, results).will_raise(StopTestException(msg)), results.failed(mock_call, msg, True)) finally: # Put logger back to how it was logger.setLevel(log_level) ctx.cleanup_imports()
def call_invokes_system_under_test(): ''' Will try to access sut when Call target has no such method''' params = ['instance', 'is_dead'] instances = [ ClassWithSystemUnderTestMethod(), ClassWithSystemUnderTestField() ] for instance in instances: execution_context = lancelot.MockSpec(name='execution_context') results = lancelot.MockSpec(name='results') call_instruction = Call('id_blah', params) spec = lancelot.Spec(call_instruction) spec.execute(execution_context, results).should_collaborate_with( execution_context.get_instance(params[0]).will_return(instance), execution_context.target_for(instance, params[1]).will_return(None), execution_context.target_for(instance, 'sut').will_return(instance.sut), execution_context.target_for(Anything(), params[1]).will_return(lambda: False), execution_context.to_args(params, 2).will_return(()), results.completed(call_instruction, False))
def execute_fails(self): ''' The base class execute() method fails with INVALID_STATEMENT ''' instruction = Instruction('id', ['nonsense']) spec = lancelot.Spec(instruction) execution_context = lancelot.MockSpec('execution_context') results = lancelot.MockSpec('results') spec.execute(execution_context, results).should_collaborate_with( results.failed(instruction, 'INVALID_STATEMENT nonsense'))
def import_adds_to_type_context(): ''' Import should add a module / package to the type context when one is supplied ''' execution_context = lancelot.MockSpec('execution_context') results = lancelot.MockSpec('results') import_instruction = Import('id', ['some.module']) spec = lancelot.Spec(import_instruction) spec.execute(execution_context, results).should_collaborate_with( execution_context.add_type_prefix('some.module'), results.completed(import_instruction))
def call_and_assign_sets_variable(): ''' CallAndAssign should assign a value to an execution context symbol ''' execution_context = lancelot.MockSpec('execution_context') results = lancelot.MockSpec('results') call_and_assign = CallAndAssign('id', ['symbol', 'list', '__len__']) spec = lancelot.Spec(call_and_assign) spec.execute(execution_context, results).should_collaborate_with( execution_context.get_instance('list').will_return([]), execution_context.target_for([], '__len__').will_return(lambda: 0), execution_context.to_args(['list', '__len__'], 2).will_return(()), execution_context.store_symbol('symbol', 0), results.completed(call_and_assign, 0))
def handles_bad_instance(self): ''' NO_INSTANCE indicates bad instance name in Call ''' execution_context = lancelot.MockSpec(name='execution_context') results = lancelot.MockSpec(name='results') params = ['bad_instance', 'method', 'args'] cause = 'NO_INSTANCE bad_instance' call_instruction = Call('id_9A', params) spec = lancelot.Spec(call_instruction) spec.execute(execution_context, results).should_collaborate_with( execution_context.get_instance(params[0]).will_return(None), execution_context.get_library_method(params[1]).will_return(None), results.failed(call_instruction, cause))
def params_converter_behaviour(): ''' ParamsConverter should create (possibly nested) tuple of string args from a (possibly nested) list of strings (possibly symbols) ''' execution_context = lancelot.MockSpec('execution_context') spec = lancelot.Spec(ParamsConverter(execution_context)) spec.to_args([], 0).should_be(()) execution_context = lancelot.MockSpec('execution_context') spec = lancelot.Spec(ParamsConverter(execution_context)) spec.to_args(['mint'], 0).should_be(('mint', )) execution_context = lancelot.MockSpec('execution_context') spec = lancelot.Spec(ParamsConverter(execution_context)) spec.to_args(['wafer', 'thin'], 0).should_be(('wafer', 'thin')) execution_context = lancelot.MockSpec('execution_context') spec = lancelot.Spec(ParamsConverter(execution_context)) spec.to_args(['wafer', 'thin'], 1).should_be(('thin', )) execution_context = lancelot.MockSpec('execution_context') spec = lancelot.Spec(ParamsConverter(execution_context)) spec.to_args(['$A', '$b_', 'C$'], 0).should_collaborate_with( execution_context.get_symbol('A').will_return('X'), execution_context.get_symbol('b_').will_return('Y'), and_result=(('X', 'Y', 'C$'))) execution_context = lancelot.MockSpec('execution_context') spec = lancelot.Spec(ParamsConverter(execution_context)) spec.to_args(['$id'], 0).should_collaborate_with( execution_context.get_symbol('id').will_return('20'), and_result=(('20', ))) execution_context = lancelot.MockSpec('execution_context') spec = lancelot.Spec(ParamsConverter(execution_context)) spec.to_args([['bring', 'me'], ['another', 'bucket']], 0).should_be( (('bring', 'me'), ('another', 'bucket'))) execution_context = lancelot.MockSpec('execution_context') spec = lancelot.Spec(ParamsConverter(execution_context)) spec.to_args(['$s11$s$s1$s11'], 0).should_collaborate_with( execution_context.get_symbol('s11').will_return('I'), execution_context.get_symbol('s').will_return('R'), execution_context.get_symbol('s1').will_return('O'), execution_context.get_symbol('s11').will_return('N'), and_result=(('IRON', ))) execution_context = lancelot.MockSpec('execution_context') long_multiline_expression = '''$a(long{ \ multi-line expression}) $and(another{ \ multi-line expression})''' spec = lancelot.Spec(ParamsConverter(execution_context)) spec.to_args([long_multiline_expression], 0).should_collaborate_with( execution_context.get_symbol('a').will_return('$a'), execution_context.get_symbol('and').will_return('$and'), and_result=(('%s' % long_multiline_expression, )))
def handles_bad_import(self): ''' import problem => NO_CLASS''' wrong_params = [ 'creosote', 'FakeClass', ['some unwanted', 'constructor args'] ] import_error = ImportError('y') cause = 'NO_CLASS FakeClass y' execution_context = lancelot.MockSpec(name='execution_context') results = lancelot.MockSpec(name='results') make_instruction = Make('wrong params', wrong_params) spec = lancelot.Spec(make_instruction) spec.execute(execution_context, results).should_collaborate_with( execution_context.get_type('FakeClass').will_raise(import_error), results.failed(make_instruction, cause))
def import_adds_to_pythonpath(): ''' Import should add a path to the pythonpath when a path is supplied ''' execution_context = lancelot.MockSpec('execution_context') results = lancelot.MockSpec('results') import_instruction = Import('id', ['/some_path']) spec = lancelot.Spec(import_instruction) spec.execute(execution_context, results).should_collaborate_with( execution_context.add_import_path('/some_path'), results.completed(import_instruction)) execution_context = lancelot.MockSpec('execution_context') results = lancelot.MockSpec('results') import_instruction = Import('id', ['c:\some_path']) spec = lancelot.Spec(import_instruction) spec.execute(execution_context, results).should_collaborate_with( execution_context.add_import_path('c:\some_path'), results.completed(import_instruction))
def completed_without_return_value(self): ''' completed() should add to results list. Results list should be accessible through collection() ''' instruction = lancelot.MockSpec(name='instruction') spec = lancelot.Spec(Results()) spec.completed(instruction, result=None).should_collaborate_with( instruction.instruction_id().will_return('c')) spec.collection().should_be([['c', '/__VOID__/']])
def handles_wrong_args(self): ''' incorrect num constructor args => COULD_NOT_INVOKE_CONSTRUCTOR''' wrong_params = [ 'creosote', 'FakeClass', ['some unwanted', 'constructor args'] ] wrong_args = ('some unwanted', 'constructor args') cause = 'COULD_NOT_INVOKE_CONSTRUCTOR FakeClass ' \ + 'object.__new__() takes no parameters' execution_context = lancelot.MockSpec(name='execution_context') results = lancelot.MockSpec(name='results') a_class = ClassWithNoArgs make_instruction = Make('wrong params', wrong_params) spec = lancelot.Spec(make_instruction) spec.execute(execution_context, results).should_collaborate_with( execution_context.get_type('FakeClass').will_return(a_class), execution_context.to_args(wrong_params, 2).will_return(wrong_args), results.failed(make_instruction, cause))
def completed_ok(self): ''' completed() for Make should add ok to results list. Results list should be accessible through collection() ''' instruction = lancelot.MockSpec(name='instruction') spec = lancelot.Spec(Results()) spec.completed(instruction).should_collaborate_with( instruction.instruction_id().will_return('a')) spec.collection().should_be([['a', 'OK']])
def handles_bad_method(self): ''' NO_METHOD_IN_CLASS indicates bad method name for Call target ''' execution_context = lancelot.MockSpec(name='execution_context') results = lancelot.MockSpec(name='results') params = ['instance', 'bad_method', 'args'] instance = ClassWithNoArgs() cause = 'NO_METHOD_IN_CLASS bad_method ClassWithNoArgs' call_instruction = Call('id_9B', params) spec = lancelot.Spec(call_instruction) spec.execute(execution_context, results).should_collaborate_with( execution_context.get_instance(params[0]).will_return(instance), execution_context.target_for(instance, params[1]).will_return(None), execution_context.target_for(instance, 'sut').will_return(None), execution_context.get_library_method(params[1]).will_return(None), results.failed(call_instruction, cause))
def failed_with_stoptest(self): ''' failed(stop_test=True) should change formatted cause to include the stop message ''' formatted_cause = '__EXCEPTION__:ABORT_SLIM_TEST: message:<<bucket>>' instruction = lancelot.MockSpec(name='instruction') spec = lancelot.Spec(Results()) spec.failed(instruction, 'bucket', True) spec.should_collaborate_with( instruction.instruction_id().will_return('b')) spec.collection().should_be([['b', formatted_cause]])
def failed(self): ''' failed() should add a translated error message to results list. Results list should be accessible through collection() ''' formatted_cause = '__EXCEPTION__: message:<<bucket>>' instruction = lancelot.MockSpec(name='instruction') spec = lancelot.Spec(Results()) spec.failed(instruction, 'bucket') spec.should_collaborate_with( instruction.instruction_id().will_return('b')) spec.collection().should_be([['b', formatted_cause]])
def loops_through_list(self): ''' Instructions should collaborate with instruction_for to instantiate a list of instructions, which execute() loops through ''' mock_fn = lancelot.MockSpec(name='mock_fn') mock_make = lancelot.MockSpec(name='mock_make') mock_call = lancelot.MockSpec(name='mock_call') a_list = [['id_0', 'make', 'instance', 'fixture', 'argument'], ['id_1', 'call', 'instance', 'f', '3']] instructions = Instructions(a_list, lambda item: mock_fn.instruction_for(item)) spec = lancelot.Spec(instructions) ctx = ExecutionContext() results = Results() spec.execute(ctx, results).should_collaborate_with( mock_fn.instruction_for(a_list[0]).will_return(mock_make), mock_make.execute(ctx, results), mock_fn.instruction_for(a_list[1]).will_return(mock_call), mock_call.execute(ctx, results)) ctx.cleanup_imports()
def completed_with_result(self): ''' completed() for Call should add to results list. Results list should be accessible through collection() ''' class Fake: def __str__(self): return 'Bon appetit' instruction = lancelot.MockSpec(name='instruction') spec = lancelot.Spec(Results()) spec.completed(instruction, result=Fake()).should_collaborate_with( instruction.instruction_id().will_return('b'), ) spec.collection().should_be([['b', 'Bon appetit']])
def observable_observer_behaviour(): ''' Illustrate how Spec.should_collaborate_with() and MockSpec interact. Note how a new MockSpec is required for each should...() specification ''' observer = lancelot.MockSpec() observable = Observable() spec = lancelot.Spec(observable) spec.send_notification().should_collaborate_with() observer = lancelot.MockSpec() observable = Observable() spec = lancelot.Spec(observable) spec.when(spec.add_observer(observer)) spec.then(spec.send_notification()) spec.should_collaborate_with(observer.notify(observable)) observer = lancelot.MockSpec() observable = Observable() spec = lancelot.Spec(observable) spec.when(spec.add_observer(observer), spec.add_observer(observer)) spec.then(spec.send_notification()) spec.should_collaborate_with(observer.notify(observable).twice())
def make_creates_instance(): ''' Make.execute() should instantiate the class & add it to context ''' package = 'waferslim.specs.spec_classes' classes = [ClassWithNoArgs, ClassWithOneArg, ClassWithTwoArgs] arg_params = [[], ['bucket'], ['mr', 'creosote']] for i in range(0, 3): target = classes[i] name = target.__name__ execution_context = lancelot.MockSpec(name='execution_context') results = lancelot.MockSpec(name='results') params = [name, '%s.%s' % (package, name)] params.extend(arg_params[i]) args = ParamsConverter(execution_context).to_args(params, 2) make_instruction = Make(name, params) spec = lancelot.Spec(make_instruction) spec.execute(execution_context, results).should_collaborate_with( execution_context.get_type(params[1]).will_return(target), execution_context.to_args(params, 2).will_return(args), execution_context.store_instance(name, Type(target)), results.completed(make_instruction))
def responder_handles_errors(): ''' RequestResponder should handle UnpackingError-s gracefully''' request = lancelot.MockSpec(name='request') instructions = lancelot.MockSpec(name='instructions') request_responder = RequestResponder() request_responder.request = request spec = lancelot.Spec(request_responder) spec.respond_to_request(instructions=lambda data: instructions) unpacking_error = '000109:[000001:000092:' \ + '[000002:000014:UnpackingError:000053:' \ + '__EXCEPTION__: message:<<MALFORMED_INSTRUCTION mint>>:]:]' spec.should_collaborate_with( request.send('Slim -- V0.1\n'.encode('utf-8')).will_return(2), request.recv(7).will_return('000009:'.encode('utf-8')), request.recv(1024).will_return('[000000:]'.encode('utf-8')), instructions.execute(Anything(), Anything()).will_raise(UnpackingError('mint')), request.send(unpacking_error.encode('utf-8')).will_return(6), request.recv(7).will_return('000003:'.encode('utf-8')), request.recv(1024).will_return('bye'.encode('utf-8')), and_result=(7 + 9 + 7 + 3, 2 + 6))
def warns_if_library_methods_may_pollute_tests(self): ''' libraries with method names "execute" and "reset" may pollute test results, since those methods are called for each row in a decision table ''' polluting_names = ['execute', 'reset', 'table'] for name in polluting_names: logger = lancelot.MockSpec(name='logger') context = ExecutionContext(logger=logger) library = ClassWithNoArgs() setattr(library, name, lambda: None) spec = lancelot.Spec(context) spec.store_instance('library', library).should_collaborate_with( logger.debug(Anything()), logger.warning(Contain('%s()' % name)))
def request_responder_behaviour(): ''' RequestResponder should send an ACK then recv a message header and message contents: then EITHER send a response and loop back to recv; OR if the message content is a "bye" then terminate ''' request = lancelot.MockSpec(name='request') instructions = lancelot.MockSpec(name='instructions') request_responder = RequestResponder() request_responder.request = request spec = lancelot.Spec(request_responder) spec.respond_to_request(instructions=lambda data: instructions) spec.should_collaborate_with( request.send('Slim -- V0.1\n'.encode('utf-8')).will_return(2), request.recv(7).will_return('000009:'.encode('utf-8')), request.recv(1024).will_return('[000000:]'.encode('utf-8')), instructions.execute(Type(ExecutionContext), Type(Results)), request.send('000009:[000000:]'.encode('utf-8')).will_return(4), request.recv(7).will_return('000003:'.encode('utf-8')), request.recv(1024).will_return('bye'.encode('utf-8')), and_result=(7 + 9 + 7 + 3, 2 + 4)) request = lancelot.MockSpec(name='request') instructions = lancelot.MockSpec(name='instructions') request_responder = RequestResponder() request_responder.request = request spec = lancelot.Spec(request_responder) spec.respond_to_request(instructions=lambda data: instructions) spec.should_collaborate_with( request.send('Slim -- V0.1\n'.encode('utf-8')).will_return(2), request.recv(7).will_return('000009:'.encode('utf-8')), request.recv(1024).will_return('[000000:]'.encode('utf-8')), instructions.execute(Type(ExecutionContext), Type(Results)), request.send('000009:[000000:]'.encode('utf-8')).will_return(4), request.recv(7).will_return('000009:'.encode('utf-8')), request.recv(1024).will_return('[000000:]'.encode('utf-8')), instructions.execute(Type(ExecutionContext), Type(Results)), request.send('000009:[000000:]'.encode('utf-8')).will_return(8), request.recv(7).will_return('000003:'.encode('utf-8')), request.recv(1024).will_return('bye'.encode('utf-8')), and_result=(7 + 9 + 7 + 9 + 7 + 3, 2 + 4 + 8))
def call_invokes_method(): ''' Call instruction should get an instance from context and execute a callable method on it, returning the results ''' methods = { 'method_0': [], 'method_1': ['bucket'], 'method_2': ['mr', 'creosote'], 'method_3': [[['bring', 'me'], ['another', 'bucket']]] } for target in methods.keys(): instance = lancelot.MockSpec(name='instance') execution_context = lancelot.MockSpec(name='execution_context') results = lancelot.MockSpec(name='results') params = ['instance', 'aMethod'] params.extend(methods[target]) call_instruction = Call('id', params) spec = lancelot.Spec(call_instruction) spec.execute(execution_context, results).should_collaborate_with( execution_context.get_instance(params[0]).will_return(instance), execution_context.target_for( instance, params[1]).will_return(lambda life: 'meaning'), execution_context.to_args(params, 2).will_return(('life', )), results.completed(call_instruction, 'meaning'))
def collaboration_with_comparators(): ''' Illustrate use of Anything() in should_collaborate_with() ''' class Hungarian: ''' A gentleman who needs a phrasebook to speak english ''' def __init__(self, phrasebook): ''' supply the phrasebook ''' self._phrasebook = phrasebook def say(self, phrase): ''' use the phraseboook to translate something into english ''' return '<<%s>>' % self._phrasebook.translate(phrase) phrasebook = lancelot.MockSpec() spec = lancelot.Spec(Hungarian(phrasebook)) eels = 'My hovercraft is full of eels' mistranslation = phrasebook.translate(Anything()).will_return(eels) spec.say('Do you have any matches') spec.should_collaborate_with(mistranslation, and_result='<<%s>>' % eels)