Example #1
0
    def multiline_indentation(self):
        if self._multiline_indentation is None:
            offset = 0
            if self.show_aligned_keywords:
                offset = 2
            indentation = make_indentation(3 * self.indent_size + offset)
            self._multiline_indentation = indentation

        if self.current_rule:
            indent_extra = make_indentation(self.indent_size)
            return self._multiline_indentation + indent_extra
        return self._multiline_indentation
Example #2
0
    def multiline_indentation(self):
        if self._multiline_indentation is None:
            offset = 0
            if self.show_aligned_keywords:
                offset = 2
            indentation = make_indentation(3 * self.indent_size + offset)
            self._multiline_indentation = indentation

        if self.current_rule:
            indent_extra = make_indentation(self.indent_size)
            return self._multiline_indentation + indent_extra
        return self._multiline_indentation
Example #3
0
    def result(self, result):
        """
        Process the result of a step (after step execution).

        :param result:
        """
        step = self.steps.pop(0)
        indent = make_indentation(2 * self.indent_size)
        if self.show_aligned_keywords:
            # -- RIGHT-ALIGN KEYWORDS (max. keyword width: 6):
            text = '%s%6s %s ... ' % (indent, step.keyword, step.name)
        else:
            text = '%s%s %s ... ' % (indent, step.keyword, step.name)
        self.stream.write(text)

        status = result.status
        if self.show_timings:
            status += " in %0.3fs" % step.duration

        if result.error_message:
            self.stream.write('%s\n%s\n' % (status, result.error_message))
        else:
            self.stream.write('%s\n' % status)

        if self.show_multiline:
            if step.text:
                self.doc_string(step.text)
            if step.table:
                self.table(step.table)
Example #4
0
    def result(self, result):
        """
        Process the result of a step (after step execution).

        :param result:
        """
        step = self.steps.pop(0)
        indent = make_indentation(2 * self.indent_size)
        if self.show_aligned_keywords:
            # -- RIGHT-ALIGN KEYWORDS (max. keyword width: 6):
            text = u"%s%6s %s ... " % (indent, step.keyword, step.name)
        else:
            text = u"%s%s %s ... " % (indent, step.keyword, step.name)
        self.stream.write(text)

        status_text = result.status.name
        if self.show_timings:
            status_text = "started at %s, %s in %0.3fs," % (
                datetime.fromtimestamp(step.start).strftime("%H:%M:%S.%f"),
                status_text, step.duration)
        if result.error_message:
            self.stream.write(u"%s\n%s\n" %
                              (status_text, result.error_message))
        else:
            self.stream.write(u"%s\n" % status_text)

        if self.show_multiline:
            if step.text:
                self.doc_string(step.text)
            if step.table:
                self.table(step.table)
Example #5
0
    def result(self, result):
        """
        Process the result of a step (after step execution).

        :param result:
        """
        step = self.steps.pop(0)
        indent = make_indentation(2 * self.indent_size)
        if self.show_aligned_keywords:
            # -- RIGHT-ALIGN KEYWORDS (max. keyword width: 6):
            text = u'%s%6s %s ... ' % (indent, step.keyword, step.name)
        else:
            text = u'%s%s %s ... ' % (indent, step.keyword, step.name)
        self.stream.write(text)

        status = result.status
        if self.show_timings:
            status += " in %0.3fs" % step.duration

        if result.error_message:
            self.stream.write(u'%s\n%s\n' % (status, result.error_message))
        else:
            self.stream.write(u'%s\n' % status)

        if self.show_multiline:
            if step.text:
                self.doc_string(step.text)
            if step.table:
                self.table(step.table)
Example #6
0
 def scenario(self, scenario):
     self.reset_steps()
     self.stream.write(u"\n")
     indent = make_indentation(self.indent_size)
     text = u"%s%s: %s\n" % (indent, scenario.keyword, scenario.name)
     self.write_tags(scenario.tags, indent)
     self.stream.write(text)
Example #7
0
 def multiline_indentation(self):
     if self._multiline_indentation is None:
         offset = 0
         if self.show_aligned_keywords:
             offset = 2
         indentation = make_indentation(3 * self.indent_size + offset)
         self._multiline_indentation = indentation
     return self._multiline_indentation
Example #8
0
 def multiline_indentation(self):
     if self._multiline_indentation is None:
         offset = 0
         if self.show_aligned_keywords:
             offset = 2
         indentation = make_indentation(3 * self.indent_size + offset)
         self._multiline_indentation = indentation
     return self._multiline_indentation
class StepsCatalogFormatter(StepsDocFormatter):
    """
    Provides formatter class that shows the documentation of all registered
    step definitions. The primary purpose is to provide help for a test writer.

    In order to ease work for non-programmer testers, the technical details of
    the steps (i.e. function name, source location) are ommited and the
    steps are shown as they would apprear in a feature file (no noisy '@',
    or '(', etc.).

    Also, the output is sorted by step type (Given, When, Then)

    Generic step definitions are listed with all three step types.

    EXAMPLE:
        $ behave --dry-run -f steps.catalog features/
        Given a file named "{filename}" with
            Creates a textual file with the content provided as docstring.

        When I run "{command}"
            Run a command as subprocess, collect its output and returncode.

        Given a file named "{filename}" exists
         When a file named "{filename}" exists
         Then a file named "{filename}" exists
            Verifies that a file with this filename exists.

            .. code-block:: gherkin

                Given a file named "abc.txt" exists
                 When a file named "abc.txt" exists
        ...

    .. note::
        Supports behave dry-run mode.
    """
    name = "steps.catalog"
    description = "Shows non-technical documentation for step definitions."
    shows_location = False
    shows_function_name = False
    ordered_by_location = False
    doc_prefix = make_indentation(4)

    def describe_step_definition(self, step_definition, step_type=None):
        if not step_type:
            step_type = step_definition.step_type
        assert step_type
        desc = []
        if step_type == "step":
            for step_type1 in self.step_types[:-1]:
                text = u"%5s %s" % (step_type1.title(),
                                    step_definition.pattern)
                desc.append(text)
        else:
            desc.append(u"%s %s" %
                        (step_type.title(), step_definition.pattern))

        return '\n'.join(desc)
Example #10
0
    def scenario(self, scenario):
        indent_extra = 0
        if self.current_rule:
            indent_extra = self.indent_size

        self.reset_steps()
        self.stream.write("\n")
        indent = make_indentation(self.indent_size + indent_extra)
        self.write_entity(scenario, indent)
Example #11
0
    def scenario(self, scenario):
        indent_extra = 0
        if self.current_rule:
            indent_extra = self.indent_size

        self.reset_steps()
        self.stream.write(u"\n")
        indent = make_indentation(self.indent_size + indent_extra)
        self.write_entity(scenario, indent)
Example #12
0
    def background(self, background):
        self.reset_steps()
        if not self.SHOW_BACKGROUNDS:
            return

        indent_extra = 0
        if self.current_rule:
            indent_extra = self.indent_size

        indent = make_indentation(self.indent_size + indent_extra)
        self.write_entity(background, indent, has_tags=False)
Example #13
0
    def background(self, background):
        self.reset_steps()
        if not self.SHOW_BACKGROUNDS:
            return

        indent_extra = 0
        if self.current_rule:
            indent_extra = self.indent_size

        indent = make_indentation(self.indent_size + indent_extra)
        self.write_entity(background, indent, has_tags=False)
Example #14
0
    def result(self, step):
        """
        Process the result of a step (after step execution).

        :param step:   Step object with result to process.
        """
        step = self.steps.pop(0)
        indent = make_indentation(2 * self.indent_size)
        if self.show_aligned_keywords:
            # -- RIGHT-ALIGN KEYWORDS (max. keyword width: 6):
            text = u"%s%6s %s" % (indent, step.keyword, step.name)
        else:
            text = u"%s%s %s" % (indent, step.keyword, step.name)
        text = escapes[step.status.name] + textwrap.shorten(
            text, width=self.LINE_WIDTH - 30) + escapes['reset'] + ' '
        self.stream.write(text)

        status_text = ': '
        status_text += {
            'passed': u'\u2713',
            'failed': u'\u26A0'
        }[step.status.name]

        if self.show_timings:
            status_text += " in %0.3fs" % step.duration

        unicode_errors = 0
        if step.error_message:
            try:
                self.stream.write(u"%s\n%s\n" %
                                  (status_text, step.error_message))
            except UnicodeError as e:
                unicode_errors += 1
                self.stream.write(u"%s\n" % status_text)
                self.stream.write(u"%s while writing error message: %s\n" % \
                                  (e.__class__.__name__, e))
                if self.RAISE_OUTPUT_ERRORS:
                    raise
        else:
            self.stream.write(u"%s\n" % status_text)

        if self.show_multiline:
            if step.text:
                try:
                    self.doc_string(step.text)
                except UnicodeError as e:
                    unicode_errors += 1
                    self.stream.write(u"%s while writing docstring: %s\n" % \
                                      (e.__class__.__name__, e))
                    if self.RAISE_OUTPUT_ERRORS:
                        raise
            if step.table:
                self.table(step.table)
    def feature(self, feature):
        super(PlainColorFormatter, self).feature(feature)

        if feature.description:
            self.stream.write('\n')

            for line in feature.description:
                self.stream.write(make_indentation(self.indent_size))
                self.stream.write(line)
                self.stream.write('\n')

            self.stream.write('\n')
Example #16
0
File: junit.py Project: xbx/behave
 def describe_step(cls, step):
     status = str(step.status)
     if cls.show_timings:
         status += u" in %0.3fs" % step.duration
     text  = u'%s %s ... ' % (step.keyword, step.name)
     text += u'%s\n' % status
     if cls.show_multiline:
         prefix = make_indentation(2)
         if step.text:
             text += ModelDescriptor.describe_docstring(step.text, prefix)
         elif step.table:
             text += ModelDescriptor.describe_table(step.table, prefix)
     return text
Example #17
0
 def describe_step(self, step):
     status_text = _text(step.status.name)
     if self.show_timings:
         status_text += " in %0.3fs" % step.duration
     text = '%s %s ... ' % (step.keyword, step.name)
     text += '%s\n' % status_text
     if self.show_multiline:
         prefix = make_indentation(2)
         if step.text:
             text += ModelDescriptor.describe_docstring(step.text, prefix)
         elif step.table:
             text += ModelDescriptor.describe_table(step.table, prefix)
     return text
Example #18
0
 def describe_step(cls, step):
     status = str(step.status)
     if cls.show_timings:
         status += u" in %0.3fs" % step.duration
     text  = u'%s %s ... ' % (step.keyword, step.name)
     text += u'%s\n' % status
     if cls.show_multiline:
         prefix = make_indentation(2)
         if step.text:
             text += ModelDescriptor.describe_docstring(step.text, prefix)
         elif step.table:
             text += ModelDescriptor.describe_table(step.table, prefix)
     return text
    def print_step(self, step, executed=True):
        indent = make_indentation(2 * self.indent_size)
        plain_text = self.step_format % (indent, step.keyword, step.name)

        # pretty formater prints not executed steps as skipped
        status = step.status if executed else Status.skipped
        status_text = status.name

        self.stream.write(escapes[status_text] + plain_text + escapes['reset'])

        if self.show_timings:
            if executed:
                status_text += " in %0.3fs" % step.duration
            else:
                status_text += " in -.---s"

        # creates nice indentation between end of step description and status
        whitespace_width = 80
        whitespace_width -= len(plain_text)
        whitespace_width -= len(status_text)
        whitespace_width -= len('... ')

        self.stream.write(u" " * max(1, whitespace_width))
        self.stream.write(u"... ")
        self.stream.write(status_text)
        self.stream.write('\n')

        if step.error_message:
            for line in step.error_message.split('\n'):
                self.stream.write(make_indentation(self.indent_size * 4))
                self.stream.write(line)
                self.stream.write('\n')

        if self.show_multiline:
            if step.text:
                self.doc_string(step.text)
            if step.table:
                self.table(step.table)
Example #20
0
    def result(self, step):
        """Process the result of a step (after step execution).

        :param step:   Step object with result to process.
        """
        indent_extra = 0
        if self.current_rule:
            indent_extra = self.indent_size

        step = self.steps.pop(0)
        indent = make_indentation(2 * self.indent_size + indent_extra)
        if self.show_aligned_keywords:
            # -- RIGHT-ALIGN KEYWORDS (max. keyword width: 6):
            text = "%s%6s %s ... " % (indent, step.keyword, step.name)
        else:
            text = "%s%s %s ... " % (indent, step.keyword, step.name)
        self.stream.write(text)

        status_text = step.status.name
        if self.show_timings:
            status_text += " in %0.3fs" % step.duration

        unicode_errors = 0
        if step.error_message:
            try:
                self.stream.write("%s\n%s\n" %
                                  (status_text, step.error_message))
            except UnicodeError as e:
                unicode_errors += 1
                self.stream.write("%s\n" % status_text)
                self.stream.write("%s while writing error message: %s\n" % \
                                  (e.__class__.__name__, e))
                if self.RAISE_OUTPUT_ERRORS:
                    raise
        else:
            self.stream.write("%s\n" % status_text)

        if self.show_multiline:
            if step.text:
                try:
                    self.doc_string(step.text)
                except UnicodeError as e:
                    unicode_errors += 1
                    self.stream.write("%s while writing docstring: %s\n" % \
                                      (e.__class__.__name__, e))
                    if self.RAISE_OUTPUT_ERRORS:
                        raise
            if step.table:
                self.table(step.table)
Example #21
0
    def result(self, step):
        """Process the result of a step (after step execution).

        :param step:   Step object with result to process.
        """
        indent_extra = 0
        if self.current_rule:
            indent_extra = self.indent_size

        step = self.steps.pop(0)
        indent = make_indentation(2 * self.indent_size + indent_extra)
        if self.show_aligned_keywords:
            # -- RIGHT-ALIGN KEYWORDS (max. keyword width: 6):
            text = u"%s%6s %s ... " % (indent, step.keyword, step.name)
        else:
            text = u"%s%s %s ... " % (indent, step.keyword, step.name)
        self.stream.write(text)

        status_text = step.status.name
        if self.show_timings:
            status_text += " in %0.3fs" % step.duration

        unicode_errors = 0
        if step.error_message:
            try:
                self.stream.write(u"%s\n%s\n" % (status_text, step.error_message))
            except UnicodeError as e:
                unicode_errors += 1
                self.stream.write(u"%s\n" % status_text)
                self.stream.write(u"%s while writing error message: %s\n" % \
                                  (e.__class__.__name__, e))
                if self.RAISE_OUTPUT_ERRORS:
                    raise
        else:
            self.stream.write(u"%s\n" % status_text)

        if self.show_multiline:
            if step.text:
                try:
                    self.doc_string(step.text)
                except UnicodeError as e:
                    unicode_errors += 1
                    self.stream.write(u"%s while writing docstring: %s\n" % \
                                      (e.__class__.__name__, e))
                    if self.RAISE_OUTPUT_ERRORS:
                        raise
            if step.table:
                self.table(step.table)
Example #22
0
    def describe_scenario(cls, scenario):
        """
        Describe the scenario and the test status.
        NOTE: table, multiline text is missing in description.

        :param scenario:  Scenario that was tested.
        :return: Textual description of the scenario.
        """
        header_line  = u'\[email protected]\n'
        header_line += '  %s: %s\n' % (scenario.keyword, scenario.name)
        footer_line  = u'\[email protected]\n' + u'-' * 80 + '\n'
        text = u''
        for step in scenario:
            text += cls.describe_step(step)
        step_indentation = make_indentation(4)
        return header_line + indent(text, step_indentation) + footer_line
Example #23
0
File: junit.py Project: xbx/behave
    def describe_scenario(cls, scenario):
        """
        Describe the scenario and the test status.
        NOTE: table, multiline text is missing in description.

        :param scenario:  Scenario that was tested.
        :return: Textual description of the scenario.
        """
        header_line  = u'\[email protected]\n'
        header_line += '  %s: %s\n' % (scenario.keyword, scenario.name)
        footer_line  = u'\[email protected]\n' + u'-' * 80 + '\n'
        text = u''
        for step in scenario:
            text += cls.describe_step(step)
        step_indentation = make_indentation(4)
        return header_line + indent(text, step_indentation) + footer_line
Example #24
0
    def describe_scenario(self, scenario):
        """Describe the scenario and the test status.
        NOTE: table, multiline text is missing in description.

        :param scenario:  Scenario that was tested.
        :return: Textual description of the scenario.
        """
        header_line = '\[email protected]\n'
        if self.show_tags and scenario.tags:
            header_line += '\n  %s\n' % self.describe_tags(scenario.tags)
        header_line += '  %s: %s\n' % (scenario.keyword, scenario.name)
        footer_line = '\[email protected]\n' + '-' * 80 + '\n'
        text = ''
        for step in scenario:
            text += self.describe_step(step)
        step_indentation = make_indentation(4)
        return header_line + indent(text, step_indentation) + footer_line
Example #25
0
    def describe_scenario(cls, scenario):
        """
        Describe the scenario and the test status.
        NOTE: table, multiline text is missing in description.

        :param scenario:  Scenario that was tested.
        :return: Textual description of the scenario.
        """
        header_line = u"\[email protected]\n"
        if cls.show_tags and scenario.tags:
            header_line += u"\n  %s\n" % cls.describe_tags(scenario.tags)
        header_line += u"  %s: %s\n" % (scenario.keyword, scenario.name)
        footer_line = u"\[email protected]\n" + u"-" * 80 + "\n"
        text = u""
        for step in scenario:
            text += cls.describe_step(step)
        step_indentation = make_indentation(4)
        return header_line + indent(text, step_indentation) + footer_line
Example #26
0
    def print_statement_head(self, statement, steps=None):
        self.writer.write(u"\n")
        #self.print_comments(self.statement.comments, '  ')
        indentation = self.indentations[self.INDENT_SCENARIO]
        if hasattr(statement, 'tags'):
            self.print_tags(statement.tags, indentation)
        text = u"%s%s: %s " % (indentation, statement.keyword, statement.name)
        self.writer.write(text, style="scenario")

        if self.show_location:
            steps = steps or []
            self.calculate_location_indentations(statement, steps)
        if self.show_source:
            assert self.show_location
            indent_size = self.location_indentations.pop(0)
            location = six.text_type(statement.location)
            text = self.location_text(location, indent_size)
            self.writer.write(text, style="comments")
        self.writer.write("\n")
        description = getattr(statement, "description", None)
        if self.show_scenario_description and description:
            indentation = make_indentation(self.indent_size * 2)
            self.print_description(description, indentation)
Example #27
0
    def print_statement_head(self, statement, steps=None):
        self.writer.write(u"\n")
        #self.print_comments(self.statement.comments, '  ')
        indentation = self.indentations[self.INDENT_SCENARIO]
        if hasattr(statement, 'tags'):
            self.print_tags(statement.tags, indentation)
        text = u"%s%s: %s " % (indentation, statement.keyword,
                               statement.name)
        self.writer.write(text, style="scenario")

        if self.show_location:
            steps = steps or []
            self.calculate_location_indentations(statement, steps)
        if self.show_source:
            assert self.show_location
            indent_size = self.location_indentations.pop(0)
            location = six.text_type(statement.location)
            text = self.location_text(location, indent_size)
            self.writer.write(text, style="comments")
        self.writer.write("\n")
        description = getattr(statement, "description", None)
        if self.show_scenario_description and description:
            indentation = make_indentation(self.indent_size*2)
            self.print_description(description, indentation)
Example #28
0
 def location_text(self, text, indent_size=0):
     if not text:
         return u''
     indentation = make_indentation(indent_size)
     return u'%s # %s' % (indentation, text)
Example #29
0
 def build_indentations(self, levels):
     return [ make_indentation(level * self.indent_size)
              for level in levels]
Example #30
0
 def scenario_outline(self, outline):
     self.reset_steps()
     indent = make_indentation(self.indent_size)
     text = u'%s%s: %s\n' % (indent, outline.keyword, outline.name)
     self.stream.write(text)
Example #31
0
 def rule(self, rule):
     self.current_rule = rule
     self.reset_steps()
     indent = make_indentation(self.indent_size)
     self.stream.write(u"\n")
     self.write_entity(rule, indent)
Example #32
0
class StepsDocFormatter(AbstractStepsFormatter):
    """
    Provides formatter class that shows the documentation of all registered
    step definitions. The primary purpose is to provide help for a test writer.

    EXAMPLE:
        $ behave --dry-run -f steps.doc features/
        @given('a file named "{filename}" with')
          Function: step_a_file_named_filename_with()
          Location: behave4cmd0/command_steps.py:50
            Creates a textual file with the content provided as docstring.

        @when('I run "{command}"')
          Function: step_i_run_command()
          Location: behave4cmd0/command_steps.py:80
            Run a command as subprocess, collect its output and returncode.

        @step('a file named "{filename}" exists')
          Function: step_file_named_filename_exists()
          Location: behave4cmd0/command_steps.py:305
            Verifies that a file with this filename exists.

            .. code-block:: gherkin

                Given a file named "abc.txt" exists
                 When a file named "abc.txt" exists
        ...

    .. note::
        Supports behave dry-run mode.
    """
    name = "steps.doc"
    description = "Shows documentation for step definitions."
    shows_location = True
    shows_function_name = True
    ordered_by_location = True
    doc_prefix = make_indentation(4)

    # -- REPORT SPECIFIC-API:
    def report(self):
        self.report_step_definition_docs()
        self.stream.write("\n")

    def report_step_definition_docs(self):
        step_definitions = []
        for step_type in self.step_types:
            for step_definition in self.step_registry.steps[step_type]:
                # step_definition.step_type = step_type
                assert step_definition.step_type is not None
                step_definitions.append(step_definition)

        if self.ordered_by_location:
            compare = lambda x, y: cmp(x.location, y.location)
            step_definitions = sorted(step_definitions, compare)

        for step_definition in step_definitions:
            self.write_step_definition(step_definition)

    def write_step_definition(self, step_definition):
        step_definition_text = self.describe_step_definition(step_definition)
        self.stream.write(u"%s\n" % step_definition_text)
        doc = inspect.getdoc(step_definition.func)
        func_name = step_definition.func.__name__
        if self.shows_function_name and func_name not in ("step", "impl"):
            self.stream.write(u"  Function: %s()\n" % func_name)
        if self.shows_location:
            self.stream.write(u"  Location: %s\n" % step_definition.location)
        if doc:
            doc = doc.strip()
            self.stream.write(indent(doc, self.doc_prefix))
            self.stream.write("\n")
        self.stream.write("\n")
Example #33
0
 def scenario_outline(self, outline):
     self.reset_steps()
     indent = make_indentation(self.indent_size)
     text = '%s%s: %s\n' % (indent, outline.keyword, outline.name)
     self.stream.write(text)
Example #34
0
 def scenario(self, scenario):
     self.reset_steps()
     self.stream.write('\n')
     indent = make_indentation(self.indent_size)
     text = '%s%s: %s\n' % (indent, scenario.keyword, scenario.name)
     self.stream.write(text)
Example #35
0
 def background(self, background):
     self.reset_steps()
     indent = make_indentation(self.indent_size)
     text = '%s%s: %s\n' % (indent, background.keyword, background.name)
     self.stream.write(text)
Example #36
0
class StepsUsageFormatter(AbstractStepsFormatter):
    """
    Provides formatter class that shows how step definitions are used by steps.

    EXAMPLE:
        $ behave --dry-run -f steps.usage features/
        ...

    .. note::
        Supports behave dry-run mode.
    """
    name = "steps.usage"
    description = "Shows how step definitions are used by steps."
    doc_prefix = make_indentation(4)
    min_location_column = 40

    def __init__(self, stream_opener, config):
        super(StepsUsageFormatter, self).__init__(stream_opener, config)
        self.step_usage_database = {}
        self.undefined_steps = []

    def reset(self):
        super(StepsUsageFormatter, self).reset()
        self.step_usage_database = {}
        self.undefined_steps = []

    def get_step_type_for_step_definition(self, step_definition):
        step_type = step_definition.step_type
        if not step_type:
            # -- DETERMINE STEP-TYPE FROM STEP-REGISTRY:
            assert self.step_registry
            for step_type, values in self.step_registry.steps.items():
                if step_definition in values:
                    return step_type
            # -- OTHERWISE:
            step_type = "step"
        return step_type

    def select_unused_step_definitions(self):
        step_definitions = set()
        for step_type, values in self.step_registry.steps.items():
            step_definitions.update(values)
        used_step_definitions = set(self.step_usage_database.keys())
        unused_step_definitions = step_definitions - used_step_definitions
        return unused_step_definitions

    def update_usage_database(self, step_definition, step):
        matching_steps = self.step_usage_database.get(step_definition, None)
        if matching_steps is None:
            assert step_definition.step_type is not None
            matching_steps = self.step_usage_database[step_definition] = []
        # -- AVOID DUPLICATES: From Scenario Outlines
        if not steps_contain(matching_steps, step):
            matching_steps.append(step)

    def update_usage_database_for_step(self, step):
        step_definition = self.step_registry.find_step_definition(step)
        if step_definition:
            self.update_usage_database(step_definition, step)
        # elif step not in self.undefined_steps:
        elif not steps_contain(self.undefined_steps, step):
            # -- AVOID DUPLICATES: From Scenario Outlines
            self.undefined_steps.append(step)

    def update_usage_database_for_feature(self, feature):
        # -- PROCESS BACKGROUND (if exists): Use Background steps only once.
        if feature.background:
            for step in feature.background.steps:
                self.update_usage_database_for_step(step)

        # -- PROCESS SCENARIOS: Without background steps.
        for scenario in feature.walk_scenarios():
            for step in scenario.steps:
                self.update_usage_database_for_step(step)

    # -- FORMATTER API:
    def feature(self, feature):
        super(StepsUsageFormatter, self).feature(feature)
        self.update_usage_database_for_feature(feature)

    # -- REPORT API:
    def report(self):
        self.report_used_step_definitions()
        self.report_unused_step_definitions()
        self.report_undefined_steps()
        self.stream.write("\n")

    # -- REPORT SPECIFIC-API:
    def report_used_step_definitions(self):
        # -- STEP: Used step definitions.
        # ORDERING: Sort step definitions by file location.
        compare = lambda x, y: cmp(x[0].location, y[0].location)
        step_definition_items = self.step_usage_database.items()
        step_definition_items = sorted(step_definition_items, compare)

        for step_definition, steps in step_definition_items:
            stepdef_text = self.describe_step_definition(step_definition)
            steps_text = [
                u"  %s %s" % (step.keyword, step.name) for step in steps
            ]
            steps_text.append(stepdef_text)
            max_size = compute_words_maxsize(steps_text)
            if max_size < self.min_location_column:
                max_size = self.min_location_column

            schema = u"%-" + str(max_size) + "s  # %s\n"
            self.stream.write(schema %
                              (stepdef_text, step_definition.location))
            schema = u"%-" + str(max_size) + "s  # %s\n"
            for step, step_text in zip(steps, steps_text):
                self.stream.write(schema % (step_text, step.location))
            self.stream.write("\n")

    def report_unused_step_definitions(self):
        unused_step_definitions = self.select_unused_step_definitions()
        if not unused_step_definitions:
            return

        # -- STEP: Prepare report for unused step definitions.
        # ORDERING: Sort step definitions by file location.
        compare = lambda x, y: cmp(x.location, y.location)
        step_definitions = sorted(unused_step_definitions, compare)
        step_texts = [
            self.describe_step_definition(step_definition)
            for step_definition in step_definitions
        ]

        max_size = compute_words_maxsize(step_texts)
        if max_size < self.min_location_column - 2:
            max_size = self.min_location_column - 2

        # -- STEP: Write report.
        schema = u"  %-" + str(max_size) + "s  # %s\n"
        self.stream.write("UNUSED STEP DEFINITIONS[%d]:\n" % len(step_texts))
        for step_definition, text in zip(step_definitions, step_texts):
            self.stream.write(schema % (text, step_definition.location))

    def report_undefined_steps(self):
        if not self.undefined_steps:
            return

        # -- STEP: Undefined steps.
        compare = lambda x, y: cmp(x.location, y.location)
        undefined_steps = sorted(self.undefined_steps, compare)

        steps_text = [
            u"  %s %s" % (step.keyword, step.name) for step in undefined_steps
        ]
        max_size = compute_words_maxsize(steps_text)
        if max_size < self.min_location_column:
            max_size = self.min_location_column

        self.stream.write("\nUNDEFINED STEPS[%d]:\n" % len(steps_text))
        schema = u"%-" + str(max_size) + "s  # %s\n"
        for step, step_text in zip(undefined_steps, steps_text):
            self.stream.write(schema % (step_text, step.location))
Example #37
0
 def location_text(self, text, indent_size=0):
     if not text:
         return u''
     indentation = make_indentation(indent_size)
     return u'%s # %s' % (indentation, text)
Example #38
0
 def build_indentations(self, levels):
     return [make_indentation(level * self.indent_size) for level in levels]
Example #39
0
 def scenario(self, scenario):
     self.reset_steps()
     self.stream.write(u'\n')
     indent = make_indentation(self.indent_size)
     text = u'%s%s: %s\n' % (indent, scenario.keyword, scenario.name)
     self.stream.write(text)
Example #40
0
 def rule(self, rule):
     self.current_rule = rule
     self.reset_steps()
     indent = make_indentation(self.indent_size)
     self.stream.write("\n")
     self.write_entity(rule, indent)
Example #41
0
 def background(self, background):
     self.reset_steps()
     indent = make_indentation(self.indent_size)
     text = u"%s%s: %s\n" % (indent, background.keyword, background.name)
     self.stream.write(text)