summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--coverage/debug.py7
-rw-r--r--tests/test_debug.py37
2 files changed, 41 insertions, 3 deletions
diff --git a/coverage/debug.py b/coverage/debug.py
index 4cf0f3e5..3d67c611 100644
--- a/coverage/debug.py
+++ b/coverage/debug.py
@@ -87,7 +87,7 @@ def info_formatter(info):
yield "%*s: %s" % (label_len, label, data)
-def short_stack(limit=None): # pragma: debugging
+def short_stack(limit=None, skip=0):
"""Return a string summarizing the call stack.
The string is multi-line, with one line per stack frame. Each line shows
@@ -101,8 +101,11 @@ def short_stack(limit=None): # pragma: debugging
`limit` is the number of frames to include, defaulting to all of them.
+ `skip` is the number of frames to skip, so that debugging functions can
+ call this and not be included in the result.
+
"""
- stack = inspect.stack()[limit:0:-1]
+ stack = inspect.stack()[limit:skip:-1]
return "\n".join("%30s : %s @%d" % (t[3], t[1], t[2]) for t in stack)
diff --git a/tests/test_debug.py b/tests/test_debug.py
index 4d9e9271..8309395b 100644
--- a/tests/test_debug.py
+++ b/tests/test_debug.py
@@ -8,7 +8,8 @@ import re
import coverage
from coverage.backward import StringIO
-from coverage.debug import info_formatter, info_header
+from coverage.debug import info_formatter, info_header, short_stack
+
from tests.coveragetest import CoverageTest
@@ -132,6 +133,40 @@ class DebugTraceTest(CoverageTest):
)
+def f_one(*args, **kwargs):
+ """First of the chain of functions for testing `short_stack`."""
+ return f_two(*args, **kwargs)
+
+def f_two(*args, **kwargs):
+ """Second of the chain of functions for testing `short_stack`."""
+ return f_three(*args, **kwargs)
+
+def f_three(*args, **kwargs):
+ """Third of the chain of functions for testing `short_stack`."""
+ return short_stack(*args, **kwargs)
+
+
+class ShortStackTest(CoverageTest):
+ """Tests of coverage.debug.short_stack."""
+
+ run_in_temp_dir = False
+
+ def test_short_stack(self):
+ stack = f_one().splitlines()
+ self.assertGreater(len(stack), 10)
+ self.assertIn("f_three", stack[-1])
+ self.assertIn("f_two", stack[-2])
+ self.assertIn("f_one", stack[-3])
+
+ def test_short_stack_limit(self):
+ stack = f_one(limit=5).splitlines()
+ self.assertEqual(len(stack), 5)
+
+ def test_short_stack_skip(self):
+ stack = f_one(skip=1).splitlines()
+ self.assertIn("f_two", stack[-1])
+
+
def lines_matching(lines, pat):
"""Gives the list of lines from `lines` that match `pat`."""
return [l for l in lines if re.search(pat, l)]