Example #1
0
 def __str__(self):
     arg0 = _text(self.args[0])
     if self.filename:
         filename = _text(self.filename, sys.getfilesystemencoding())
         return u'Failed to parse "%s": %s' % (filename, arg0)
     else:
         return u"Failed to parse <string>: %s" % arg0
Example #2
0
    def captured(self):
        """Provides access of the captured output data.

        :return: Object that stores the captured output parts (as Captured).
        """
        stdout = None
        stderr = None
        log_out = None
        if self.config.stdout_capture and self.stdout_capture:
            stdout = _text(self.stdout_capture.getvalue())
        if self.config.stderr_capture and self.stderr_capture:
            stderr = _text(self.stderr_capture.getvalue())
        if self.config.log_capture and self.log_capture:
            log_out = _text(self.log_capture.getvalue())
        return Captured(stdout, stderr, log_out)
Example #3
0
    def make_report(self):
        """Makes a detailled report of the captured output data.

        :returns: Report as string.
        """
        report_parts = []
        if self.stdout:
            parts = ["Captured stdout:", _text(self.stdout).rstrip(), ""]
            report_parts.extend(parts)
        if self.stderr:
            parts = ["Captured stderr:", _text(self.stderr).rstrip(), ""]
            report_parts.extend(parts)
        if self.log_output:
            parts = ["Captured logging:", _text(self.log_output)]
            report_parts.extend(parts)
        return self.linesep.join(report_parts).strip()
Example #4
0
 def __str__(self):
     filename = self.filename
     if isinstance(filename, six.binary_type):
         filename = _text(filename, "utf-8")
     if self.line is None:
         return filename
     return u"%s:%d" % (filename, self.line)
Example #5
0
 def doc_string(self, doc_string):
     #self.stream.write('      """' + doc_string.content_type + '\n')
     doc_string = _text(doc_string)
     prefix = u"      "
     self.stream.write(u'%s"""\n' % prefix)
     doc_string = escape_triple_quotes(indent(doc_string, prefix))
     self.stream.write(doc_string)
     self.stream.write(u'\n%s"""\n' % prefix)
     self.stream.flush()
Example #6
0
 def make_feature_filename(self, feature):
     filename = None
     for path in self.config.paths:
         if feature.filename.startswith(path):
             filename = feature.filename[len(path) + 1:]
             break
     if not filename:
         # -- NOTE: Directory path (subdirs) are taken into account.
         filename = feature.location.relpath(self.config.base_dir)
     filename = filename.rsplit('.', 1)[0]
     filename = filename.replace('\\', '/').replace('/', '.')
     return _text(filename)
Example #7
0
 def describe_step(self, step):
     status_text = _text(step.status.name)
     if self.show_timings:
         status_text += u" in %0.3fs" % step.duration
     text = u'%s %s ... ' % (step.keyword, step.name)
     text += u'%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 #8
0
    def report_used_step_definitions(self):
        # -- STEP: Used step definitions.
        # ORDERING: Sort step definitions by file location.
        get_location = lambda x: x[0].location
        step_definition_items = self.step_usage_database.items()
        step_definition_items = sorted(step_definition_items, key=get_location)

        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"%-" + _text(max_size) + "s  # %s\n"
            self.stream.write(schema % (stepdef_text, step_definition.location))
            schema = u"%-" + _text(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")
Example #9
0
    def report_tag_counts(self):
        # -- PREPARE REPORT:
        ordered_tags = sorted(list(self.tag_counts.keys()))
        tag_maxsize = compute_words_maxsize(ordered_tags)
        schema = "  @%-" + _text(tag_maxsize) + "s %4d    (used for %s)\n"

        # -- EMIT REPORT:
        self.stream.write("TAG COUNTS (alphabetically sorted):\n")
        for tag in ordered_tags:
            tag_data = self.tag_counts[tag]
            counts = len(tag_data)
            details = self.get_tag_count_details(tag_data)
            self.stream.write(schema % (tag, counts, details))
        self.stream.write("\n")
Example #10
0
    def report_steps_by_type(self):
        """Show an overview of the existing step implementations per step type.
        """
        # pylint: disable=too-many-branches
        assert set(self.step_types) == set(self.step_registry.steps.keys())
        language = self.config.lang or "en"
        language_keywords = i18n.languages[language]

        for step_type in self.step_types:
            steps = list(self.step_registry.steps[step_type])
            if step_type != "step":
                steps.extend(self.step_registry.steps["step"])
            if not steps:
                continue

            # -- PREPARE REPORT: For a step-type.
            step_type_name = step_type.upper()
            if step_type == "step":
                step_keyword = "*"
                step_type_name = "GENERIC"
            else:
                # step_keyword = step_type.capitalize()
                keywords = language_keywords[step_type]
                if keywords[0] == u"*":
                    assert len(keywords) > 1
                    step_keyword = keywords[1]
                else:
                    step_keyword = keywords[0]

            steps_text = [u"%s %s" % (step_keyword, step.pattern)
                          for step in steps]
            if self.shows_location:
                max_size = compute_words_maxsize(steps_text)
                if max_size < self.min_location_column:
                    max_size = self.min_location_column
                schema = u"  %-" + _text(max_size) + "s  # %s\n"
            else:
                schema = u"  %s\n"

            # -- REPORT:
            message = "%s STEP DEFINITIONS[%s]:\n"
            self.stream.write(message % (step_type_name, len(steps)))
            for step, step_text in zip(steps, steps_text):
                if self.shows_location:
                    self.stream.write(schema % (step_text, step.location))
                else:
                    self.stream.write(schema % step_text)
            self.stream.write("\n")
Example #11
0
    def report_tag_counts_by_usage(self):
        # -- PREPARE REPORT:
        compare_tag_counts_size = lambda x: len(self.tag_counts[x])
        ordered_tags = sorted(list(self.tag_counts.keys()),
                              key=compare_tag_counts_size)
        tag_maxsize = compute_words_maxsize(ordered_tags)
        schema = "  @%-" + _text(tag_maxsize) + "s %4d    (used for %s)\n"

        # -- EMIT REPORT:
        self.stream.write("TAG COUNTS (most often used first):\n")
        for tag in ordered_tags:
            tag_data = self.tag_counts[tag]
            counts = len(tag_data)
            details = self.get_tag_count_details(tag_data)
            self.stream.write(schema % (tag, counts, details))
        self.stream.write("\n")
Example #12
0
    def report_tags_by_locations(self):
        # -- PREPARE REPORT:
        locations = set()
        for tag_elements in self.tag_counts.values():
            locations.update([six.text_type(x.location) for x in tag_elements])
        location_column_size = compute_words_maxsize(locations)
        schema = u"    %-" + _text(location_column_size) + "s   %s\n"

        # -- EMIT REPORT:
        self.stream.write("TAG LOCATIONS (alphabetically ordered):\n")
        for tag in sorted(self.tag_counts):
            self.stream.write("  @%s:\n" % tag)
            for element in self.tag_counts[tag]:
                info = u"%s: %s" % (element.keyword, element.name)
                self.stream.write(schema % (element.location, info))
            self.stream.write("\n")
        self.stream.write("\n")
Example #13
0
 def add_step_definition(self, keyword, step_text, func):
     step_location = Match.make_location(func)
     step_type = keyword.lower()
     step_text = _text(step_text)
     step_definitions = self.steps[step_type]
     for existing in step_definitions:
         if self.same_step_definition(existing, step_text, step_location):
             # -- EXACT-STEP: Same step function is already registered.
             # This may occur when a step module imports another one.
             return
         elif existing.match(step_text):  # -- SIMPLISTIC
             message = u"%s has already been defined in\n  existing step %s"
             new_step = u"@%s('%s')" % (step_type, step_text)
             existing.step_type = step_type
             existing_step = existing.describe()
             existing_step += u" at %s" % existing.location
             raise AmbiguousStep(message % (new_step, existing_step))
     step_definitions.append(get_matcher(func, step_text))
Example #14
0
    def report_undefined_steps(self):
        if not self.undefined_steps:
            return

        # -- STEP: Undefined steps.
        undefined_steps = sorted(self.undefined_steps,
                                 key=attrgetter("location"))

        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"%-" + _text(max_size) + "s  # %s\n"
        for step, step_text in zip(undefined_steps, steps_text):
            self.stream.write(schema % (step_text, step.location))
Example #15
0
    def feature(self, feature):
        if feature.status == Status.skipped and not self.show_skipped:
            # -- SKIP-OUTPUT: If skipped features should not be shown.
            return

        feature_filename = self.make_feature_filename(feature)
        classname = feature_filename
        report = FeatureReportData(feature, feature_filename)
        now = datetime.now()

        suite = ElementTree.Element(u'testsuite')
        feature_name = feature.name or feature_filename
        suite.set(u'name', u'%s.%s' % (classname, feature_name))

        # -- BUILD-TESTCASES: From scenarios
        for scenario in feature:
            if isinstance(scenario, ScenarioOutline):
                scenario_outline = scenario
                self._process_scenario_outline(scenario_outline, report)
            else:
                self._process_scenario(scenario, report)

        # -- ADD TESTCASES to testsuite:
        for testcase in report.testcases:
            suite.append(testcase)

        suite.set(u'tests', _text(report.counts_tests))
        suite.set(u'errors', _text(report.counts_errors))
        suite.set(u'failures', _text(report.counts_failed))
        suite.set(u'skipped', _text(report.counts_skipped))  # WAS: skips
        suite.set(u'time', _text(round(feature.duration, 6)))
        # -- SINCE: Pyautomators-1.2.6.dev0
        if self.show_timestamp:
            suite.set(u'timestamp', _text(now.isoformat()))
        if self.show_hostname:
            suite.set(u'hostname', _text(gethostname()))

        if not os.path.exists(self.config.junit_directory):
            # -- ENSURE: Create multiple directory levels at once.
            os.makedirs(self.config.junit_directory)

        tree = ElementTreeWithCDATA(suite)
        report_dirname = self.config.junit_directory
        report_basename = u'TEST-%s.xml' % feature_filename
        report_filename = os.path.join(report_dirname, report_basename)
        tree.write(codecs.open(report_filename, "wb"), "UTF-8")
Example #16
0
    def write_table(self, table):
        """
        Write a ReST simple table.

        EXAMPLE:
        ========================================= ===== ===== ===== =====
        Step Definition                           Given When  Then  Step
        ========================================= ===== ===== ===== =====
        Given a file named "{filename}" contains
        Then the file "{filename}" should ...
        ========================================= ===== ===== ===== =====

        :param table:   Table to render (as `Pyautomators.model.Table`)

        .. todo::
            Column alignments
        """
        assert self.stream

        # -- STEP: Determine table layout dimensions
        cols_size = []
        separator_parts = []
        row_schema_parts = []
        for col_index, heading in enumerate(table.headings):
            column = [six.text_type(row[col_index]) for row in table.rows]
            column.append(heading)
            column_size = compute_words_maxsize(column)
            cols_size.append(column_size)
            separator_parts.append("=" * column_size)
            row_schema_parts.append("%-" + _text(column_size) + "s")

        separator = " ".join(separator_parts) + "\n"
        row_schema = " ".join(row_schema_parts) + "\n"
        self.stream.write("\n")  # -- ENSURE: Empty line before table start.
        self.stream.write(separator)
        self.stream.write(row_schema % tuple(table.headings))
        self.stream.write(separator)
        for row in table.rows:
            self.stream.write(row_schema % tuple(row))
        self.stream.write(separator)
        self.stream.write("\n")  # -- ENSURE: Empty line after table end.
Example #17
0
def print_formatters(title=None, stream=None):
    """Prints the list of available formatters and their description.

    :param title:   Optional title (as string).
    :param stream:  Optional, output stream to use (default: sys.stdout).
    """
    from Pyautomators.formatter._registry import format_items
    from operator import itemgetter

    if stream is None:
        stream = sys.stdout
    if title:
        stream.write(u"%s\n" % title)

    format_items = sorted(format_items(resolved=True), key=itemgetter(0))
    format_names = [item[0] for item in format_items]
    column_size = compute_words_maxsize(format_names)
    schema = u"  %-" + _text(column_size) + "s  %s\n"
    for name, formatter_class in format_items:
        formatter_description = getattr(formatter_class, "description", "")
        stream.write(schema % (name, formatter_description))
Example #18
0
    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.
        get_location = lambda x: x.location
        step_definitions = sorted(unused_step_definitions, key=get_location)
        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"  %-" + _text(max_size) + "s  # %s\n"
        self.stream.write("UNUSED STEP DEFINITIONS[%d]:\n" % len(step_texts))
        for step_definition, step_text in zip(step_definitions, step_texts):
            self.stream.write(schema % (step_text, step_definition.location))
Example #19
0
    def report_failures(self):
        if self.failures:
            separator = "-" * 80
            self.stream.write(u"%s\n" % separator)
            unicode_errors = 0
            for step in self.failures:
                try:
                    self.stream.write(u"FAILURE in step '%s' (%s):\n" % \
                                      (step.name, step.location))
                    self.stream.write(u"%s\n" % step.error_message)
                    self.stream.write(u"%s\n" % separator)
                except UnicodeError as e:
                    self.stream.write(u"%s while reporting failure in %s\n" % \
                                      (e.__class__.__name__, step.location))
                    self.stream.write(u"ERROR: %s\n" % \
                                      _text(e, encoding=self.stream.encoding))
                    unicode_errors += 1

            if unicode_errors:
                msg = u"HINT: %d unicode errors occured during failure reporting.\n"
                self.stream.write(msg % unicode_errors)
            self.stream.flush()
Example #20
0
def run_Pyautomators(config, runner_class=None):
    """Run Pyautomators with configuration.

    :param config:          Configuration object for Pyautomators.
    :param runner_class:    Runner class to use or none (use Runner class).
    :return:    0, if successful. Non-zero on failure.

    .. note:: BEST EFFORT, not intended for multi-threaded usage.
    """
    # pylint: disable=too-many-branches, too-many-statements, too-many-return-statements
    if runner_class is None:
        runner_class = Runner

    if config.version:
        print("Pyautomators " + __version__)
        return 0

    if config.tags_help:
        print(TAG_HELP)
        return 0

    if config.lang_list:
        from Pyautomators.i18n import languages
        stdout = sys.stdout
        if six.PY2:
            # -- PYTHON2: Overcome implicit encode problems (encoding=ASCII).
            stdout = codecs.getwriter("UTF-8")(sys.stdout)
        iso_codes = languages.keys()
        print("Languages available:")
        for iso_code in sorted(iso_codes):
            native = languages[iso_code]["native"][0]
            name = languages[iso_code]["name"][0]
            print(u"%s: %s / %s" % (iso_code, native, name), file=stdout)
        return 0

    if config.lang_help:
        from Pyautomators.i18n import languages
        if config.lang_help not in languages:
            print("%s is not a recognised language: try --lang-list" % \
                    config.lang_help)
            return 1
        trans = languages[config.lang_help]
        print(u"Translations for %s / %s" %
              (trans["name"][0], trans["native"][0]))
        for kw in trans:
            if kw in "name native".split():
                continue
            print(u"%16s: %s" % (kw.title().replace("_", " "), u", ".join(
                w for w in trans[kw] if w != "*")))
        return 0

    if not config.format:
        config.format = [config.default_format]
    elif config.format and "format" in config.defaults:
        # -- CASE: Formatter are specified in Pyautomators configuration file.
        #    Check if formatter are provided on command-line, too.
        if len(config.format) == len(config.defaults["format"]):
            # -- NO FORMATTER on command-line: Add default formatter.
            config.format.append(config.default_format)
    if "help" in config.format:
        print_formatters("Available formatters:")
        return 0

    if len(config.outputs) > len(config.format):
        print("CONFIG-ERROR: More outfiles (%d) than formatters (%d)." % \
              (len(config.outputs), len(config.format)))
        return 1

    # -- MAIN PART:
    failed = True
    try:
        reset_runtime()
        runner = runner_class(config)
        failed = runner.run()
    except ParserError as e:
        print(u"ParserError: %s" % e)
    except ConfigError as e:
        print(u"ConfigError: %s" % e)
    except FileNotFoundError as e:
        print(u"FileNotFoundError: %s" % e)
    except InvalidFileLocationError as e:
        print(u"InvalidFileLocationError: %s" % e)
    except InvalidFilenameError as e:
        print(u"InvalidFilenameError: %s" % e)
    except Exception as e:
        # -- DIAGNOSTICS:
        text = _text(e)
        print(u"Exception %s: %s" % (e.__class__.__name__, text))
        raise

    if config.show_snippets and runner.undefined_steps:
        print_undefined_step_snippets(runner.undefined_steps,
                                      colored=config.color)

    return_code = 0
    if failed:
        return_code = 1
    return return_code
Example #21
0
    def _process_scenario(self, scenario, report):
        """Process a scenario and append information to JUnit report object.
        This corresponds to a JUnit testcase:

          * testcase.@classname = f(filename) +'.'+ feature.name
          * testcase.@name   = scenario.name
          * testcase.@status = scenario.status
          * testcase.@time   = scenario.duration

        Distinguishes now between failures and errors.
        Failures are AssertationErrors: expectation is violated/not met.
        Errors are unexpected RuntimeErrors (all other exceptions).

        If a failure/error occurs, the step, that caused the failure,
        and its location are provided now.

        :param scenario:  Scenario to process.
        :param report:    Context object to store/add info to (outgoing param).
        """
        # pylint: disable=too-many-locals, too-many-branches, too-many-statements
        assert isinstance(scenario, Scenario)
        assert not isinstance(scenario, ScenarioOutline)
        if scenario.status != Status.skipped or self.show_skipped:
            # -- NOTE: Count only if not-skipped or skipped should be shown.
            report.counts_tests += 1
        classname = report.classname
        feature = report.feature
        feature_name = feature.name
        if not feature_name:
            feature_name = self.make_feature_filename(feature)

        case = ElementTree.Element('testcase')
        case.set(u"classname", u"%s.%s" % (classname, feature_name))
        case.set(u"name", scenario.name or "")
        case.set(u"status", scenario.status.name)
        case.set(u"time", _text(round(scenario.duration, 6)))

        step = None
        failing_step = None
        if scenario.status == Status.failed:
            for status in (Status.failed, Status.undefined):
                step = self.select_step_with_status(status, scenario)
                if step:
                    break
            # -- NOTE: Scenario may fail now due to hook-errors.
            element_name = "failure"
            if step and isinstance(step.exception, (AssertionError, type(None))):
                # -- FAILURE: AssertionError
                assert step.status in (Status.failed, Status.undefined)
                report.counts_failed += 1
            else:
                # -- UNEXPECTED RUNTIME-ERROR:
                report.counts_errors += 1
                element_name = "error"
            # -- COMMON-PART:
            failure = ElementTree.Element(element_name)
            if step:
                step_text = self.describe_step(step).rstrip()
                text = u"\nFailing step: %s\nLocation: %s\n" % \
                       (step_text, step.location)
                message = _text(step.exception)
                failure.set(u'type', step.exception.__class__.__name__)
                failure.set(u'message', message)
                text += _text(step.error_message)
            else:
                # -- MAYBE: Hook failure before any step is executed.
                failure_type = "UnknownError"
                if scenario.exception:
                    failure_type = scenario.exception.__class__.__name__
                failure.set(u'type', failure_type)
                failure.set(u'message', scenario.error_message or "")
                traceback_lines = traceback.format_tb(scenario.exc_traceback)
                traceback_lines.insert(0, u"Traceback:\n")
                text = _text(u"".join(traceback_lines))
            failure.append(CDATA(text))
            case.append(failure)
        elif (scenario.status in (Status.skipped, Status.untested)
              and self.show_skipped):
            report.counts_skipped += 1
            step = self.select_step_with_status(Status.undefined, scenario)
            if step:
                # -- UNDEFINED-STEP:
                report.counts_failed += 1
                failure = ElementTree.Element(u"failure")
                failure.set(u"type", u"undefined")
                failure.set(u"message", (u"Undefined Step: %s" % step.name))
                case.append(failure)
            else:
                skip = ElementTree.Element(u'skipped')
                case.append(skip)

        # Create stdout section for each test case
        stdout = ElementTree.Element(u"system-out")
        text = u""
        if self.show_scenarios:
            text = self.describe_scenario(scenario)

        # Append the captured standard output
        if scenario.captured.stdout:
            output = _text(scenario.captured.stdout)
            ##retirado para analise da necessidade de verificar as saidas
            #text += u"\nCaptured stdout:\n%s\n" % output
        stdout.append(CDATA(text))
        case.append(stdout)

        # Create stderr section for each test case
        if scenario.captured.stderr:
            stderr = ElementTree.Element(u"system-err")
            output = _text(scenario.captured.stderr)
            text = u"\nCaptured stderr:\n%s\n" % output
            stderr.append(CDATA(text))
            case.append(stderr)

        if scenario.status != Status.skipped or self.show_skipped:
            report.testcases.append(case)