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 test_generates_imports_for_user_defined_exceptions(self): klass = Class("UserDefinedException") function = Function("throw") function.calls = [FunctionCall(function, {}, exception=UserObject(None, klass))] result = generate_single_test_module(objects=[function, klass]) assert_contains(result, "from module import UserDefinedException")
def GeneratorWithSingleException(genname, input, exception): execution = EmptyProjectExecution() generator = Function(genname, input.keys(), is_generator=True) gobject = GeneratorObject(None, generator, stable_serialize_call_arguments(execution, input), generator) gobject.add_call(GeneratorObjectInvocation(generator, {}, exception=execution.serialize(exception))) generator.add_call(gobject) return generator
def GeneratorWithYields(genname, input, yields): execution = EmptyProjectExecution() generator = Function(genname, input.keys(), is_generator=True) gobject = GeneratorObject(None, generator, stable_serialize_call_arguments(execution, input), generator) for syield in map(execution.serialize, yields): gobject.add_call(GeneratorObjectInvocation(generator, {}, syield)) generator.add_call(gobject) return generator
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 pythoscope_t3st(): project = Project.from_directory(".") #inspect_project(project) #add_tests_to_project(project, modules, template, force) #modname = "foo" #module = project.create_test_module_from_name(modname) #pprint.pprint(module) foo = Function("testfoo") #module = project.find_module_by_full_path(modname) #pprint.pprint(module) #pprint.pprint(module.__dict__) #pprint.pprint(dir(module)) #module.objects.append(foo) #template = "unittest" #generator = pythoscope.generator.TestGenerator.from_template(template) #generator._add_tests_for_module(module, project, True) code = test_unparse_ast ast2 = ast.parse(inspect.getsource(code)) code2 = astunparse.unparse(ast2) m = project.create_module("tests/foo123.py", code=code2) #pprint.pprint(m.__dict__) pprint.pprint(project.__dict__) for module in project.get_modules(): module.changed = True # print("Calling save() on module %r" % module.subpath) # module.save() project.save()
def test_handles_generators_called_not_from_top_level(self): def function_calling_function_that_uses_generator(): def generator(x): yield x yield x + 1 yield x * 2 yield x ** 3 def function(y): return [x for x in generator(y)] function(2) execution = TestingProject()\ .with_all_catch_module()\ .with_object(Function("generator", is_generator=True))\ .with_object(Function("function"))\ .make_new_execution() inspect_code_in_context(function_calling_function_that_uses_generator, execution) assert_function_with_single_generator_object("generator", {'x': 2}, [2, 3, 4, 8], execution)
def test_clear_previous_run_removes_function_calls_from_functions(self): function = Function('some_function') self._create_project_with_two_points_of_entry(function) call1 = inject_function_call(self.first, function) call2 = inject_function_call(self.first, function) call3 = inject_function_call(self.second, function) self.first.clear_previous_run() # Only the FunctionCall from the second POE remains. assert_equal_sets([call3], function.calls)
def test_generator_can_be_invoked_in_multiple_places(self): def function(): def generator(): i = 1 while True: yield i i += 1 def first(g): return g.next() def second(g): return g.next() + g.next() g = generator() g.next() first(g) second(g) execution = TestingProject()\ .with_all_catch_module()\ .with_object(Function("generator", is_generator=True))\ .with_object(Function("first"))\ .with_object(Function("second"))\ .make_new_execution() inspect_code_in_context(function, execution) expected_call_graph = noindent(""" generator() first() next() generator() second() next() generator() next() generator() """) assert_equal_strings(expected_call_graph, call_graph_as_string(execution.call_graph))
def test_serializes_generator_objects_passed_as_values(self): def function(): def invoke(g): return [x for x in g] def generator(): yield 1 yield 2 invoke(generator()) execution = TestingProject()\ .with_all_catch_module()\ .with_object(Function("invoke"))\ .with_object(Function("generator", is_generator=True))\ .make_new_execution() inspect_code_in_context(function, execution) function = execution.project.find_object(Function, "invoke") fcall = assert_one_element_and_return(function.calls) gobject = fcall.input['g'] assert_instance(gobject, GeneratorObject) assert_generator_object({}, [1, 2], gobject)
def test_generator_can_be_invoked_multiple_times_at_the_same_place(self): def function(): def sth_else(): return False def generator(): yield 1 yield 2 g = generator() g.next() sth_else() g.next() execution = TestingProject()\ .with_all_catch_module()\ .with_object(Function("generator", is_generator=True))\ .with_object(Function("sth_else"))\ .make_new_execution() inspect_code_in_context(function, execution) assert_instance(execution.call_graph[0], GeneratorObjectInvocation) assert_instance(execution.call_graph[1], FunctionCall) assert_instance(execution.call_graph[2], GeneratorObjectInvocation)
def test_clear_previous_run_ignores_not_referenced_objects(self): function = Function('some_function') self._create_project_with_two_points_of_entry(function) args = { 'i': ImmutableObject(123), 'u': UnknownObject(None), 's': SequenceObject([], None), 'm': MapObject({}, None) } inject_function_call(self.first, function, args) self.first.clear_previous_run()
def test_clear_previous_run_removes_generator_objects_from_functions(self): function = Function('generator', is_generator=True) method = Method('generator_method', is_generator=True) klass = Class('ClassWithGenerators', methods=[method]) self._create_project_with_two_points_of_entry(function, klass) user_object = inject_user_object(self.first, 1, klass) inject_generator_object(self.first, 2, function, {}, function) inject_generator_object(self.first, 3, method, {}, user_object) self.first.clear_previous_run() assert_equal([], klass.user_objects) assert_equal([], function.calls)
def test_can_be_saved_and_restored_from_file(self): project = ProjectInDirectory(self.tmpdir).with_modules( ["good_module.py", "bad_module.py"]) project['good_module'].add_objects( [Class("AClass", [Method("amethod")]), Function("afunction")]) project['bad_module'].errors = ["Syntax error"] project.save() project = Project.from_directory(project.path) assert_equal(2, len(project.get_modules())) assert_equal(2, len(project['good_module'].objects)) assert_equal(["AClass"], get_names(project['good_module'].classes)) assert_equal(["amethod"], get_names(project['good_module'].classes[0].methods)) assert_equal(["afunction"], get_names(project['good_module'].functions)) assert_equal(["Syntax error"], project['bad_module'].errors)
def test_generates_complete_assertion_for_functions_which_take_defined_generator_objects_as_arguments(self): execution = EmptyProjectExecution() def ssca(args): return stable_serialize_call_arguments(execution, args) s = execution.serialize mygen = Function('mygen', ['a', 'b'], is_generator=True) gobject = GeneratorObject(None, mygen, ssca({'a': 42, 'b': False}), mygen) gobject.add_call(GeneratorObjectInvocation(mygen, {}, s(42))) mygen.add_call(gobject) function = Function('invoke', ['g']) function.add_call(FunctionCall(function, {'g': gobject}, output=s(True))) result = generate_single_test_module(objects=[function, mygen]) assert_contains(result, "from module import mygen") assert_contains(result, "def test_invoke_returns_true_for_mygen_instance(self):") assert_contains(result, "self.assertEqual(True, invoke(mygen(42, False)))")
class ListReverse(BuiltinMethodWithPositionArgsSideEffect): trigger = (list, 'reverse') definition = Function('reverse', [])
def TestableProject(path, more_modules=[]): project = ProjectWithModules(["module.py"] + more_modules, lambda: ProjectInDirectory(path)) project["module"].add_object(Function("function")) return project
def test_code_of_function(self): function = Function('fun', module=self.module) function_code = object() self.code_tree.add_object(function, function_code) assert_equal(function_code, code_of(function))
class ListExtend(BuiltinMethodWithPositionArgsSideEffect): trigger = (list, 'extend') definition = Function('extend', ['iterable'])
def visit_lambda_assign(self, name, args): self.objects.append(Function(name, args=args)) self.past_imports = True
class ListSort(BuiltinMethodWithPositionArgsSideEffect): trigger = (list, 'sort') definition = Function('sort', [])
class ListAppend(BuiltinMethodWithPositionArgsSideEffect): trigger = (list, 'append') definition = Function('append', ['object'])
def test_module_of_for_function(self): fun = Function('fun', module=self.module) assert_equal(self.module, module_of(fun))
class ListRemove(BuiltinMethodWithPositionArgsSideEffect): trigger = (list, 'remove') definition = Function('remove', ['value'])
class ListPop(BuiltinMethodWithPositionArgsSideEffect): trigger = (list, 'pop') definition = Function('pop', ['index'])
class ListInsert(BuiltinMethodWithPositionArgsSideEffect): trigger = (list, 'insert') definition = Function('insert', ['index', 'object'])
def make_execution_with_single_generator_function(name): return TestingProject()\ .with_all_catch_module()\ .with_object(Function(name, is_generator=True))\ .make_new_execution()