Exemple #1
0
    def test_empty_decorated_function(self):
        parser = self.parse_source("""\
            def decorator(func):
                return func

            @decorator
            def foo(self):
                '''Docstring'''

            @decorator
            def bar(self):
                pass
            """)

        if env.PYBEHAVIOR.trace_decorated_def:
            expected_statements = {1, 2, 4, 5, 8, 9, 10}
            expected_arcs = set(
                arcz_to_arcs(".1 14 45 58 89 9.  .2 2.  -8A A-8"))
            expected_exits = {1: 1, 2: 1, 4: 1, 5: 1, 8: 1, 9: 1, 10: 1}
        else:
            expected_statements = {1, 2, 4, 8, 10}
            expected_arcs = set(arcz_to_arcs(".1 14 48 8.  .2 2.  -8A A-8"))
            expected_exits = {1: 1, 2: 1, 4: 1, 8: 1, 10: 1}

        if env.PYBEHAVIOR.docstring_only_function:
            # 3.7 changed how functions with only docstrings are numbered.
            expected_arcs.update(set(arcz_to_arcs("-46 6-4")))
            expected_exits.update({6: 1})

        self.assertEqual(expected_statements, parser.statements)
        self.assertEqual(expected_arcs, parser.arcs())
        self.assertEqual(expected_exits, parser.exit_counts())
Exemple #2
0
    def check_coverage(
        self,
        text,
        lines=None,
        missing="",
        report="",
        excludes=None,
        partials="",
        arcz=None,
        arcz_missing=None,
        arcz_unpredicted=None,
        arcs=None,
        arcs_missing=None,
        arcs_unpredicted=None,
    ):
        """Check the coverage measurement of `text`.

        The source `text` is run and measured.  `lines` are the line numbers
        that are executable, or a list of possible line numbers, any of which
        could match. `missing` are the lines not executed, `excludes` are
        regexes to match against for excluding lines, and `report` is the text
        of the measurement report.

        For arc measurement, `arcz` is a string that can be decoded into arcs
        in the code (see `arcz_to_arcs` for the encoding scheme).
        `arcz_missing` are the arcs that are not executed, and
        `arcz_unpredicted` are the arcs executed in the code, but not deducible
        from the code.  These last two default to "", meaning we explicitly
        check that there are no missing or unpredicted arcs.

        Returns the Coverage object, in case you want to poke at it some more.

        """
        # We write the code into a file so that we can import it.
        # Coverage.py wants to deal with things as modules with file names.
        modname = self.get_module_name()

        self.make_file(modname + ".py", text)

        if arcs is None and arcz is not None:
            arcs = arcz_to_arcs(arcz)
        if arcs_missing is None and arcz_missing is not None:
            arcs_missing = arcz_to_arcs(arcz_missing)
        if arcs_unpredicted is None and arcz_unpredicted is not None:
            arcs_unpredicted = arcz_to_arcs(arcz_unpredicted)

        # Start up coverage.py.
        cov = coverage.Coverage(branch=True)
        cov.erase()
        for exc in excludes or []:
            cov.exclude(exc)
        for par in partials or []:
            cov.exclude(par, which='partial')

        mod = self.start_import_stop(cov, modname)

        # Clean up our side effects
        del sys.modules[modname]

        # Get the analysis results, and check that they are right.
        analysis = cov._analyze(mod)
        statements = sorted(analysis.statements)
        if lines is not None:
            if isinstance(lines[0], int):
                # lines is just a list of numbers, it must match the statements
                # found in the code.
                assert statements == lines, "{!r} != {!r}".format(
                    statements, lines)
            else:
                # lines is a list of possible line number lists, one of them
                # must match.
                for line_list in lines:
                    if statements == line_list:
                        break
                else:
                    self.fail("None of the lines choices matched %r" %
                              statements)

            missing_formatted = analysis.missing_formatted()
            if isinstance(missing, string_class):
                msg = "{!r} != {!r}".format(missing_formatted, missing)
                assert missing_formatted == missing, msg
            else:
                for missing_list in missing:
                    if missing_formatted == missing_list:
                        break
                else:
                    self.fail("None of the missing choices matched %r" %
                              missing_formatted)

        if arcs is not None:
            # print("Possible arcs:")
            # print(" expected:", arcs)
            # print(" actual:", analysis.arc_possibilities())
            # print("Executed:")
            # print(" actual:", sorted(set(analysis.arcs_executed())))
            # TODO: this would be nicer with pytest-check, once we can run that.
            msg = (
                self._check_arcs(arcs, analysis.arc_possibilities(),
                                 "Possible") +
                self._check_arcs(arcs_missing, analysis.arcs_missing(),
                                 "Missing") +
                self._check_arcs(arcs_unpredicted, analysis.arcs_unpredicted(),
                                 "Unpredicted"))
            if msg:
                assert False, msg

        if report:
            frep = StringIO()
            cov.report(mod, file=frep, show_missing=True)
            rep = " ".join(frep.getvalue().split("\n")[2].split()[1:])
            assert report == rep, "{!r} != {!r}".format(report, rep)

        return cov
Exemple #3
0
def test_arcz_to_arcs(arcz, arcs):
    assert arcz_to_arcs(arcz) == arcs