summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2017-01-15 15:54:21 -0500
committerNed Batchelder <ned@nedbatchelder.com>2017-01-15 15:54:21 -0500
commit9708c8d60829d9dfb49c929cedcc86d9b65703b1 (patch)
treeb451c6d691c10a40ed096d84a7479ffd79daf03a
parent797e735c3c55e400e7f5d222c07e092789012c9b (diff)
downloadpython-coveragepy-9708c8d60829d9dfb49c929cedcc86d9b65703b1.tar.gz
Promote re_line and re_lines to real helpers, with tests.
-rw-r--r--tests/helpers.py24
-rw-r--r--tests/test_process.py14
-rw-r--r--tests/test_testing.py49
-rw-r--r--tests/test_xml.py16
4 files changed, 72 insertions, 31 deletions
diff --git a/tests/helpers.py b/tests/helpers.py
index a132872..344ed71 100644
--- a/tests/helpers.py
+++ b/tests/helpers.py
@@ -4,6 +4,7 @@
"""Helpers for coverage.py tests."""
import os
+import re
import subprocess
import sys
@@ -77,3 +78,26 @@ class CheckUniqueFilenames(object):
self.filenames.add(filename)
ret = self.wrapped(filename, *args, **kwargs)
return ret
+
+
+def re_lines(text, pat, match=True):
+ """Return the text of lines that match `pat` in the string `text`.
+
+ If `match` is false, the selection is inverted: only the non-matching
+ lines are included.
+
+ Returns a string, the text of only the selected lines.
+
+ """
+ return "".join(l for l in text.splitlines(True) if bool(re.search(pat, l)) == match)
+
+
+def re_line(text, pat):
+ """Return the one line in `text` that matches regex `pat`.
+
+ Raises an AssertionError if more than one, or less than one, line matches.
+
+ """
+ lines = re_lines(text, pat).splitlines()
+ assert len(lines) == 1
+ return lines[0]
diff --git a/tests/test_process.py b/tests/test_process.py
index d77dfda..6ed566e 100644
--- a/tests/test_process.py
+++ b/tests/test_process.py
@@ -18,6 +18,7 @@ from coverage import env, CoverageData
from coverage.misc import output_encoding
from tests.coveragetest import CoverageTest
+from tests.helpers import re_lines
class ProcessTest(CoverageTest):
@@ -388,8 +389,7 @@ class ProcessTest(CoverageTest):
out2 = self.run_command("python throw.py")
if env.PYPY:
# Pypy has an extra frame in the traceback for some reason
- lines2 = out2.splitlines()
- out2 = "".join(l+"\n" for l in lines2 if "toplevel" not in l)
+ out2 = re_lines(out2, "toplevel", match=False)
self.assertMultiLineEqual(out, out2)
# But also make sure that the output is what we expect.
@@ -722,8 +722,8 @@ class EnvironmentTest(CoverageTest):
# the comparison also...
if env.PYPY:
ignored += "|"+re.escape(os.getcwd())
- out_cov = remove_matching_lines(out_cov, ignored)
- out_py = remove_matching_lines(out_py, ignored)
+ out_cov = re_lines(out_cov, ignored, match=False)
+ out_py = re_lines(out_py, ignored, match=False)
self.assertMultiLineEqual(out_cov, out_py)
self.assert_execfile_output(out_cov)
@@ -1405,9 +1405,3 @@ class ProcessStartupWithSourceTest(ProcessCoverageMixin, CoverageTest):
def test_script_pkg_sub(self):
self.assert_pth_and_source_work_together('', 'pkg', 'sub')
-
-
-def remove_matching_lines(text, pat):
- """Return `text` with all lines matching `pat` removed."""
- lines = [l for l in text.splitlines(True) if not re.search(pat, l)]
- return "".join(lines)
diff --git a/tests/test_testing.py b/tests/test_testing.py
index b74d08f..a7f60b3 100644
--- a/tests/test_testing.py
+++ b/tests/test_testing.py
@@ -8,12 +8,14 @@ import datetime
import os
import sys
+import pytest
+
import coverage
from coverage.backunittest import TestCase
from coverage.files import actual_path
from tests.coveragetest import CoverageTest
-from tests.helpers import CheckUniqueFilenames
+from tests.helpers import CheckUniqueFilenames, re_lines, re_line
class TestingTest(TestCase):
@@ -131,12 +133,14 @@ class CoverageTestTest(CoverageTest):
self.assertEqual(out[2], 'XYZZY')
# Try it with a "coverage debug sys" command.
- out = self.run_command("coverage debug sys").splitlines()
- # "environment: COV_FOOBAR = XYZZY" or "COV_FOOBAR = XYZZY"
- executable = next(l for l in out if "executable:" in l) # pragma: part covered
+ out = self.run_command("coverage debug sys")
+
+ executable = re_line(out, "executable:")
executable = executable.split(":", 1)[1].strip()
- self.assertTrue(same_python_executable(executable, sys.executable))
- environ = next(l for l in out if "COV_FOOBAR" in l) # pragma: part covered
+ self.assertTrue(_same_python_executable(executable, sys.executable))
+
+ # "environment: COV_FOOBAR = XYZZY" or "COV_FOOBAR = XYZZY"
+ environ = re_line(out, "COV_FOOBAR")
_, _, environ = environ.rpartition(":")
self.assertEqual(environ.strip(), "COV_FOOBAR = XYZZY")
@@ -168,7 +172,38 @@ class CheckUniqueFilenamesTest(CoverageTest):
stub.method("file1")
-def same_python_executable(e1, e2):
+@pytest.mark.parametrize("text, pat, result", [
+ ("line1\nline2\nline3\n", "line", "line1\nline2\nline3\n"),
+ ("line1\nline2\nline3\n", "[13]", "line1\nline3\n"),
+ ("line1\nline2\nline3\n", "X", ""),
+])
+def test_re_lines(text, pat, result):
+ assert re_lines(text, pat) == result
+
+@pytest.mark.parametrize("text, pat, result", [
+ ("line1\nline2\nline3\n", "line", ""),
+ ("line1\nline2\nline3\n", "[13]", "line2\n"),
+ ("line1\nline2\nline3\n", "X", "line1\nline2\nline3\n"),
+])
+def test_re_lines_inverted(text, pat, result):
+ assert re_lines(text, pat, match=False) == result
+
+@pytest.mark.parametrize("text, pat, result", [
+ ("line1\nline2\nline3\n", "2", "line2"),
+])
+def test_re_line(text, pat, result):
+ assert re_line(text, pat) == result
+
+@pytest.mark.parametrize("text, pat", [
+ ("line1\nline2\nline3\n", "line"), # too many matches
+ ("line1\nline2\nline3\n", "X"), # no matches
+])
+def test_re_line_bad(text, pat):
+ with pytest.raises(AssertionError):
+ re_line(text, pat)
+
+
+def _same_python_executable(e1, e2):
"""Determine if `e1` and `e2` refer to the same Python executable.
Either path could include symbolic links. The two paths might not refer
diff --git a/tests/test_xml.py b/tests/test_xml.py
index dd14b92..9f1781a 100644
--- a/tests/test_xml.py
+++ b/tests/test_xml.py
@@ -13,6 +13,7 @@ from coverage.files import abs_file
from tests.coveragetest import CoverageTest
from tests.goldtest import CoverageGoldTest
from tests.goldtest import change_dir, compare
+from tests.helpers import re_line, re_lines
class XmlTestHelpers(CoverageTest):
@@ -194,7 +195,7 @@ class XmlPackageStructureTest(XmlTestHelpers, CoverageTest):
cov.xml_report(outfile="-")
packages_and_classes = re_lines(self.stdout(), r"<package |<class ")
scrubs = r' branch-rate="0"| complexity="0"| line-rate="[\d.]+"'
- return clean("".join(packages_and_classes), scrubs)
+ return clean(packages_and_classes, scrubs)
def assert_package_and_class_tags(self, cov, result):
"""Check the XML package and class tags from `cov` match `result`."""
@@ -282,19 +283,6 @@ class XmlPackageStructureTest(XmlTestHelpers, CoverageTest):
""")
-def re_lines(text, pat):
- """Return a list of lines that match `pat` in the string `text`."""
- lines = [l for l in text.splitlines(True) if re.search(pat, l)]
- return lines
-
-
-def re_line(text, pat):
- """Return the one line in `text` that matches regex `pat`."""
- lines = re_lines(text, pat)
- assert len(lines) == 1
- return lines[0]
-
-
def clean(text, scrub=None):
"""Clean text to prepare it for comparison.