Commit 1215f1f6 authored by eckhart's avatar eckhart

testing.py: runner() now profiles tests if parameter "--profile" is passed on the command line

parent d95141ee
......@@ -3324,7 +3324,7 @@ class Forward(UnaryParser):
if result[0] is not None:
# keep calling the (potentially left-)recursive parser and increase
# the recursion depth by 1 for each call as long as the length of
# the matches increase.
# the match increases.
depth = 1
while True:
self.recursion_counter[location] = depth
......@@ -3335,11 +3335,11 @@ class Forward(UnaryParser):
if len(next_result[1]) >= len(result[1]): # also true, if no match
# Since the result of the last parser call (`next_result`) is discarded,
# any variables captured by this call should be "rolled back", too.
if len(grammar.rollback__) > rb_stack_size:
while len(grammar.rollback__) > rb_stack_size:
_, rb_func = grammar.rollback__.pop()
rb_func()
grammar.last_rb__loc__ = grammar.rollback__[-1][0] \
if grammar.rollback__ else (grammar.document__.__len__() + 1)
if grammar.rollback__ else -2
# Plus, overwrite the discarded result in the last history record with
# the accepted result, i.e. the longest match.
# TODO: Move this to trace.py, somehow... and make it less confusing
......
......@@ -789,7 +789,7 @@ def run_test_function(func_name, namespace):
exec(func_name + '()', namespace)
def runner(tests, namespace):
def runner(tests, namespace, profile=False):
"""
Runs all or some selected Python unit tests found in the
namespace. To run all tests in a module, call
......@@ -807,17 +807,22 @@ def runner(tests, namespace):
(of a test-class) that shall be run. Test-Methods are specified in
the form: class_name.method.name e.g. "TestServer.test_connection".
Args:
tests: String or list of strings with the names of tests to
run. If empty, runner searches by itself all objects the
of which starts with 'test' and runs it (if its a function)
or all of its methods that start with "test" if its a class
plus the "setup" and "teardown" methods if they exist.
:param tests: String or list of strings with the names of tests
to run. If empty, runner searches by itself all objects the
of which starts with 'test' and runs it (if its a function)
or all of its methods that start with "test" if its a class
plus the "setup" and "teardown" methods if they exist.
:param namespace: The namespace for running the test, usually
``globals()`` should be used.
:param profile: If True, the tests will be run with the profiler on.
results will be displayed after the test-results. Profiling will
also be turned on, if the parameter `--profile` has been provided
on the command line.
namespace: The namespace for running the test, usually
``globals()`` should be used.
Example::
Example:
class TestSomething()
def setup(self):
pass
......@@ -854,12 +859,24 @@ def runner(tests, namespace):
elif inspect.isfunction(namespace[name]):
test_functions.append(name)
profile = profile or '--profile' in sys.argv
if profile:
import cProfile, pstats
pr = cProfile.Profile()
pr.enable()
for cls_name, methods in test_classes.items():
run_tests_in_class(cls_name, namespace, methods)
for test in test_functions:
run_test_function(test, namespace)
if profile:
pr.disable()
st = pstats.Stats(pr)
st.strip_dirs()
st.sort_stats('time').print_stats(50)
def run_file(fname):
if fname.lower().startswith('test_') and fname.endswith('.py'):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment