def FunctionWithExceptions(funcname, calls): execution = EmptyProjectExecution() function = Function(funcname, sorted(calls[0][0].keys())) function.calls = [FunctionCall(function, stable_serialize_call_arguments(execution, i), exception=execution.serialize(e)) for (i,e) in calls] return function
def counted(objects): """Count how many times each object appears in a list and return list of (object, count) tuples. >>> counted(['a', 'b', 'c', 'a', 'b', 'a']) [('a', 3), ('b', 2), ('c', 1)] >>> counted([]) [] """ return [(obj, len(list(group))) for obj, group in groupby(sorted(objects))]
def FunctionWithCalls(funcname, calls): def fc(function, args, output, execution): call = FunctionCall(function, stable_serialize_call_arguments(execution, args)) # Output needs to be created after the Call object is created. call.set_output(execution.serialize(output)) return call execution = EmptyProjectExecution() function = Function(funcname, sorted(calls[0][0].keys())) function.calls = [fc(function, i, o, execution) for (i,o) in calls] return function
def stable_serialize_call_arguments(execution, args): """Work just like execution.serialize_call_arguments, but serialize arguments in lexicographical order, so test outputs are stable. This doesn't change semantics of the serialization process (as objects identity will be preserved), yet it makes testing it much easier. """ serialized_args = {} for key, value in sorted(args.iteritems()): serialized_args[key] = execution.serialize(value) return serialized_args
def call_as_string(object_name, args, assigned_names={}): """Generate code for calling an arbitrary object with given arguments. Use `call_as_string_for` when you have a definition to base the call on. >>> from test.helper import make_fresh_serialize >>> serialize = make_fresh_serialize() Since we don't have a definition to base the generated call on, we use keywords to name all arguments: >>> call_as_string('fun', {'a': serialize(1), 'b': serialize(2)}) 'fun(a=1, b=2)' >>> call_as_string('capitalize', {'str': serialize('string')}) "capitalize(str='string')" Uses references to existing objects where possible... >>> result = call_as_string('call', {'f': serialize(call_as_string)}) >>> result 'call(f=call_as_string)' >>> result.uncomplete False ...but marks the resulting call as uncomplete if at least one of objects appearing in a call cannot be constructed. >>> result = call_as_string('map', {'f': serialize(lambda x: 42), 'L': serialize([1,2,3])}) >>> result 'map(L=[1, 2, 3], f=<TODO: function>)' >>> result.uncomplete True Uses names already assigned to objects instead of inlining their construction code. >>> mutable = serialize([]) >>> call_as_string('merge', {'seq1': mutable, 'seq2': serialize([1,2,3])}, ... {mutable: 'alist'}) 'merge(seq1=alist, seq2=[1, 2, 3])' """ arguments = [] for arg, value in sorted(args.iteritems()): constructor = constructor_as_string(value, assigned_names) arguments.append(combine(arg, constructor, template="%s=%s")) return combine(object_name, join(", ", arguments), template="%s(%s)")
def map_as_kwargs(mapobject): # Keys of kwargs argument must be strings - assertion is checked by # the interpreter on runtime. return sorted([(eval(k.reconstructor), v) for k,v in mapobject.mapping])
def map_as_kwargs(mapobject): # Keys of kwargs argument must be strings - assertion is checked by # the interpreter on runtime. return sorted([(eval(k.reconstructor), v) for k, v in mapobject.mapping])
def sorted_test_method_descriptions(descriptions): return sorted(descriptions, key=lambda md: md.name)