From 0a13b8f11468914f7c61d4d205529601c1aa1fa8 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sun, 10 Mar 2013 22:49:51 +0100 Subject: [PATCH 1/3] Separate test collection and run in refactoring.py --- test/refactor.py | 150 ++++++++++++++++++++++++++++++----------------- 1 file changed, 97 insertions(+), 53 deletions(-) diff --git a/test/refactor.py b/test/refactor.py index 4f01edd7..c9b1cbea 100755 --- a/test/refactor.py +++ b/test/refactor.py @@ -8,6 +8,8 @@ import sys import os import traceback import re +import itertools + import base from jedi._compatibility import reduce @@ -15,25 +17,54 @@ import jedi from jedi import refactoring -def run_test(source, f_name, lines_to_execute): - """ - This is the completion test for some cases. The tests are not unit test - like, they are rather integration tests. - It uses comments to specify a test in the next line. The comment also says, - which results are expected. The comment always begins with `#?`. The last - row symbolizes the cursor. +class RefactoringCase(object): - For example:: + def __init__(self, name, source, line_nr, index, path, f_name, + new_name, start_line_test, desired): + self.name = name + self.source = source + self.line_nr = line_nr + self.index = index + self.path = path + self.f_name = f_name + self.new_name = new_name + self.start_line_test = start_line_test + self.desired = desired - #? ['ab'] - ab = 3; a + def run(self): + (source, line_nr, index, path, f_name, new_name, start_line_test) \ + = (self.source, self.line_nr, self.index, self.path, self.f_name, + self.new_name, self.start_line_test) + script = jedi.Script(source, line_nr, index, path) + refactor_func = getattr(refactoring, f_name.replace('.py', '')) + args = (script, new_name) if new_name else (script,) + refactor_object = refactor_func(*args) - #? int() - ab = 3; ab - """ - fails = 0 - tests = 0 - # parse the refactor format + # try to get the right excerpt of the newfile + f = refactor_object.new_files()[path] + lines = f.splitlines()[start_line_test:] + + end = start_line_test + len(lines) + pop_start = None + for i, l in enumerate(lines): + if l.startswith('# +++'): + end = i + break + elif '#? ' in l: + pop_start = i + lines.pop(pop_start) + self.result = '\n'.join(lines[:end - 1]).strip() + return self.result + + def check(self): + return self.run() == self.desired + + def __repr__(self): + return '<%s: %s:%s>' % (self.__class__.__name__, + self.name, self.line_nr - 1) + + +def collect_file_tests(source, f_name, lines_to_execute): r = r'^# --- ?([^\n]*)\n((?:(?!\n# \+\+\+).)*)' \ r'\n# \+\+\+((?:(?!\n# ---).)*)' for match in re.finditer(r, source, re.DOTALL | re.MULTILINE): @@ -56,54 +87,67 @@ def run_test(source, f_name, lines_to_execute): continue path = os.path.abspath(refactoring_test_dir + os.path.sep + f_name) + yield RefactoringCase(name, source, line_nr, index, path, f_name, + new_name, start_line_test, second) + + +def collect_dir_tests(base_dir, test_files): + for f_name in os.listdir(base_dir): + files_to_execute = [a for a in test_files.items() if a[0] in f_name] + lines_to_execute = reduce(lambda x, y: x + y[1], files_to_execute, []) + if f_name.endswith(".py") and (not test_files or files_to_execute): + path = os.path.join(refactoring_test_dir, f_name) + with open(path) as f: + source = f.read() + for case in collect_file_tests(source, f_name, lines_to_execute): + yield case + + +def run_test(cases): + """ + This is the completion test for some cases. The tests are not unit test + like, they are rather integration tests. + It uses comments to specify a test in the next line. The comment also says, + which results are expected. The comment always begins with `#?`. The last + row symbolizes the cursor. + + For example:: + + #? ['ab'] + ab = 3; a + + #? int() + ab = 3; ab + """ + fails = 0 + tests = 0 + for case in cases: try: - script = jedi.Script(source, line_nr, index, path) - refactor_func = getattr(refactoring, f_name.replace('.py', '')) - args = (script, new_name) if new_name else (script,) - refactor_object = refactor_func(*args) - - # try to get the right excerpt of the newfile - f = refactor_object.new_files()[path] - lines = f.splitlines()[start_line_test:] - - end = start_line_test + len(lines) - pop_start = None - for i, l in enumerate(lines): - if l.startswith('# +++'): - end = i - break - elif '#? ' in l: - pop_start = i - lines.pop(pop_start) - result = '\n'.join(lines[:end - 1]).strip() - - if second != result: - print('test @%s: not the same result, %s' % (line_nr - 1, name)) - print(' ' + repr(str(result))) - print(' ' + repr(second)) + if not case.check(): + print(case) + print(' ' + repr(str(case.result))) + print(' ' + repr(case.desired)) fails += 1 except Exception: print(traceback.format_exc()) - print('test @%s: %s' % (line_nr - 1, name)) + print(case) fails += 1 tests += 1 return tests, fails def test_dir(refactoring_test_dir): - for f_name in os.listdir(refactoring_test_dir): - files_to_execute = [a for a in test_files.items() if a[0] in f_name] - lines_to_execute = reduce(lambda x, y: x + y[1], files_to_execute, []) - if f_name.endswith(".py") and (not test_files or files_to_execute): - path = os.path.join(refactoring_test_dir, f_name) - with open(path) as f: - num_tests, fails = run_test(f.read(), f_name, lines_to_execute) + for (path, cases) in itertools.groupby( + collect_dir_tests(refactoring_test_dir, test_files), + lambda case: case.path): + num_tests, fails = run_test(cases) - base.test_sum += num_tests - s = 'run %s tests with %s fails (%s)' % (num_tests, fails, f_name) - base.tests_fail += fails - print(s) - base.summary.append(s) + base.test_sum += num_tests + f_name = os.path.basename(path) + s = 'run %s tests with %s fails (%s)' % (num_tests, fails, f_name) + base.tests_fail += fails + print(s) + base.summary.append(s) if __name__ == '__main__': From 2362e290d8324886f8b781c4d4f57f648268fe85 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sun, 10 Mar 2013 22:55:28 +0100 Subject: [PATCH 2/3] Separate methods in RefactoringCase --- test/refactor.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/test/refactor.py b/test/refactor.py index c9b1cbea..709bb436 100755 --- a/test/refactor.py +++ b/test/refactor.py @@ -31,20 +31,21 @@ class RefactoringCase(object): self.start_line_test = start_line_test self.desired = desired - def run(self): - (source, line_nr, index, path, f_name, new_name, start_line_test) \ - = (self.source, self.line_nr, self.index, self.path, self.f_name, - self.new_name, self.start_line_test) - script = jedi.Script(source, line_nr, index, path) + def refactor(self): + script = jedi.Script(self.source, self.line_nr, self.index, self.path) + f_name = os.path.basename(self.path) refactor_func = getattr(refactoring, f_name.replace('.py', '')) - args = (script, new_name) if new_name else (script,) - refactor_object = refactor_func(*args) + args = (self.new_name,) if self.new_name else () + return refactor_func(script, *args) + + def run(self): + refactor_object = self.refactor() # try to get the right excerpt of the newfile - f = refactor_object.new_files()[path] - lines = f.splitlines()[start_line_test:] + f = refactor_object.new_files()[self.path] + lines = f.splitlines()[self.start_line_test:] - end = start_line_test + len(lines) + end = self.start_line_test + len(lines) pop_start = None for i, l in enumerate(lines): if l.startswith('# +++'): From 9791f045550698651f1f9c9ab6784340f62186f5 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sun, 10 Mar 2013 22:58:48 +0100 Subject: [PATCH 3/3] Reduce args for RefactoringCase --- test/refactor.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/refactor.py b/test/refactor.py index 709bb436..e4cc7c08 100755 --- a/test/refactor.py +++ b/test/refactor.py @@ -19,14 +19,13 @@ from jedi import refactoring class RefactoringCase(object): - def __init__(self, name, source, line_nr, index, path, f_name, + def __init__(self, name, source, line_nr, index, path, new_name, start_line_test, desired): self.name = name self.source = source self.line_nr = line_nr self.index = index self.path = path - self.f_name = f_name self.new_name = new_name self.start_line_test = start_line_test self.desired = desired @@ -87,8 +86,8 @@ def collect_file_tests(source, f_name, lines_to_execute): if lines_to_execute and line_nr - 1 not in lines_to_execute: continue - path = os.path.abspath(refactoring_test_dir + os.path.sep + f_name) - yield RefactoringCase(name, source, line_nr, index, path, f_name, + path = os.path.join(os.path.abspath(refactoring_test_dir), f_name) + yield RefactoringCase(name, source, line_nr, index, path, new_name, start_line_test, second)