Example #1
0
    def restore(self):

        parser = argparse.ArgumentParser(
            description='Restore config settings to it\'s original values',
            usage="tj config restore [OPTIONS]")
        parser.add_argument(
            "-a",
            "--all",
            action="store_true",
            default=False,
            help="Will restore all config settings to its default values")
        CliUtils.add_standard_boolean_tj_args(parser)
        args = parser.parse_args(self.args[3:])
        if args.all:
            self.config.restore()
            print("[{status}] Config restored to default settings!".format(
                status=CliUtils.format_color_string(value="OK",
                                                    color="green")))
            return
        if not self.args[3:]:
            print("[{status}]\tWhat do you want to restore?\n".format(
                status=CliUtils.format_color_string(value="ERROR",
                                                    color="red")))
            parser.print_help()
            return
        for option, value in args.__dict__.items():
            if value is True:
                self.__restore_value(option, None)
Example #2
0
        def raise_import_error(error):

            print("[{status}] There is an import error: {error}".format(
                status=CliUtils.format_color_string(value="ERROR",
                                                    color="red"),
                error=error))
            print(
                "[{status}] 1. Make sure you have installed all of the packages required for your project "
                "to work".format(status=CliUtils.format_color_string(
                    value="ERROR", color="red")))
            print(
                "[{status}] 2. Make sure the root of your project is in the PYTHONPATH"
                .format(status=CliUtils.format_color_string(value="ERROR",
                                                            color="red")))
            raise
Example #3
0
    def __restore_value(self, option, value):

        try:
            self.config.set_value(option, value)
            print("[{status}]\t{option}={value}".format(
                status=CliUtils.format_color_string(value="OK", color="green"),
                option=option,
                value=value))
        except:
            print(
                "[{status}]\tUnexpected error occurred during update of {setting}={value}"
                .format(status=CliUtils.format_color_string(value="ERROR",
                                                            color="red"),
                        setting=option,
                        value=value))
            CliUtils.print_color_traceback()
            exit(120)
Example #4
0
 def get_value(self, option, default=Undefined):
     section = "runtime"
     try:
         if sys.version_info[0] < 3:
             # Python 2
             value = self.config.get(section, option, default)
         else:
             # Python 3, module is not backwards compatible and fallback has to be explicitly assigned
             value = self.config.get(section, option, fallback=default)
         return value
     except Exception:
         print(
             "[{status}]\tPlease check config: {path} it appears that its miss-configured."
             .format(status=CliUtils.format_color_string(value="ERROR",
                                                         color="red"),
                     path=CliUtils.format_color_string(value=self.path,
                                                       color="red")))
         raise
Example #5
0
    def __init__(self, config_name):

        if config_name not in [CliConstants.TJ_CONFIG_NAME]:
            if not os.path.exists(config_name):
                print(
                    "[{status}]\tWasn't able to find config @ {path}. Please check that the file exists."
                    .format(status=CliUtils.format_color_string(value="ERROR",
                                                                color="red"),
                            path=CliUtils.format_color_string(
                                value=config_name, color="red")))
                exit(120)
            self.path = config_name
        else:
            self.path = "{root}{sep}{file}".format(root=Config.get_root_dir(),
                                                   file=config_name,
                                                   sep=os.sep)
        if not os.path.exists(Config.get_root_dir()):
            os.makedirs(Config.get_root_dir())
        if not os.path.exists(self.path):
            self.restore()
        self.config = self.__get_parser()
Example #6
0
    def update(self):

        parser = argparse.ArgumentParser(
            description=
            "Update configuration settings for individual properties",
            usage="tj config update [OPTIONS]")
        CliUtils.add_standard_tj_args(parser)
        args = parser.parse_args(self.args[3:])
        if not self.args[3:]:
            print("[{status}]\tWhat do you want to update?\n".format(
                status=CliUtils.format_color_string(value="ERROR",
                                                    color="red")))
            parser.print_help()
            return
        for option, value in args.__dict__.items():
            if value is not Undefined:
                self.__restore_value(option, value)
        print(
            "[{status}]\tRestore original value with tj config restore [OPTION]. tj config restore -h for more info."
            .format(status=CliUtils.format_color_string(value="TIP",
                                                        color="blue")))
Example #7
0
        def guess_project_root(path, _module_name, error):

            print("[{status}] Import error: {error}".format(
                status=CliUtils.format_color_string(value="WARNING",
                                                    color="yellow"),
                error=error))
            possibility = "{}".format(os.sep).join(path.split(os.sep)[:-1])
            print(
                "[{status}] Trying again with assumption that this is your project root: {assumed_root}"
                .format(status=CliUtils.format_color_string(value="WARNING",
                                                            color="yellow"),
                        assumed_root=CliUtils.format_color_string(
                            value=possibility, color="yellow")))
            try:
                sys.path.insert(0, possibility)
                return imp.load_source(_module_name, _file_path)
            except KeyboardInterrupt:
                print("(Ctrl+C) Exiting!")
                exit(12)
            except ImportError as error:
                if len(possibility.split(os.sep)) > 2:
                    return guess_project_root(possibility, _module_name, error)
                raise_import_error(error)
Example #8
0
    def show(self):

        parser = argparse.ArgumentParser(
            description='Display current configuration for Test-Junkie',
            usage="tj config show [OPTIONS]")
        parser.add_argument(
            "-a",
            "--all",
            action="store_true",
            default=False,
            help="Will restore all config settings to its default values")
        CliUtils.add_standard_boolean_tj_args(parser)
        args = parser.parse_args(self.args[3:])
        if args.all or not self.args[3:]:
            print("Config is located at: {path}\n".format(
                path=CliUtils.format_color_string(value=self.config.path,
                                                  color="green")))
            with open(self.config.path, "r") as cfg:
                print(cfg.read())
            return
        for option, value in args.__dict__.items():
            if value is True:
                self.__print_value(option)
Example #9
0
    def run_suites(self, args):
        def tags():
            config = {
                "run_on_match_all": args.run_on_match_all,
                "run_on_match_any": args.run_on_match_any,
                "skip_on_match_all": args.skip_on_match_all,
                "skip_on_match_any": args.skip_on_match_any
            }
            for prop, value in config.items():
                if value is not None:
                    return config
            return None

        if self.suites:
            print("[{status}] Running tests ...\n".format(
                status=CliUtils.format_color_string(value="INFO",
                                                    color="blue")))
            try:
                runner = Runner(suites=self.suites,
                                html_report=args.html_report,
                                xml_report=args.xml_report,
                                config=self.execution_config)
                runner.run(
                    test_multithreading_limit=args.test_multithreading_limit,
                    suite_multithreading_limit=args.suite_multithreading_limit,
                    tests=args.tests,
                    owners=args.owners,
                    components=args.components,
                    features=args.features,
                    tag_config=tags(),
                    quiet=args.quiet)
            except KeyboardInterrupt:
                print("(Ctrl+C) Exiting!")
                exit(12)
            except:
                print("[{status}] Unexpected error during test execution.".
                      format(status=CliUtils.format_color_string(value="ERROR",
                                                                 color="red")))
                CliUtils.print_color_traceback()
                exit(120)
            finally:
                if self.coverage is not None:
                    self.coverage.stop()
                    self.coverage.save()
                    import coverage
                    try:
                        print("[{status}] Code coverage report:".format(
                            status=CliUtils.format_color_string(value="INFO",
                                                                color="blue")))
                        self.coverage.report(show_missing=True,
                                             skip_covered=True)
                        print(
                            "[{status}] TJ uses Coverage.py. Control it with --cov-rcfile, "
                            "see {link}".format(
                                status=CliUtils.format_color_string(
                                    value="TIP", color="blue"),
                                link=DocumentationLinks.COVERAGE_CONFIG_FILE))
                    except coverage.misc.CoverageException:
                        CliUtils.print_color_traceback()
                        exit(120)
            return
Example #10
0
    def scan(self):
        @contextmanager
        def open_file(_file):
            if sys.version_info[0] < 3:
                with open(_file) as _doc:
                    _source = _doc.read()
                    yield (_source, _doc)
            else:
                with open(_file, encoding="utf-8") as _doc:
                    _source = _doc.read()
                    yield (_source, _doc)

        def parse_file(_file):

            with open_file(_file) as __source:

                suite_imported_as_alias = re.findall(
                    CliRunner.__REGEX_ALIAS_IMPORT, __source[0])
                if suite_imported_as_alias:
                    suite_alias = suite_imported_as_alias[-1].split(
                        "Suite")[-1].split("as")[-1].split(",")[0].strip()
                    CliRunner.start_in_a_thread(
                        target=self.__find_and_register_suite,
                        args=(suite_alias, __source[0], __source[1].name))
                    return True

                suite_imported = re.findall(CliRunner.__REGEX_NO_ALIAS_IMPORT,
                                            __source[0])
                if suite_imported:
                    CliRunner.start_in_a_thread(
                        target=self.__find_and_register_suite,
                        args=("Suite", __source[0], __source[1].name))
                    return True

        try:
            print("\n[{status}] Scanning: {location} ...".format(
                location=CliUtils.format_color_string(value=",".join(
                    self.sources),
                                                      color="green"),
                status=CliUtils.format_color_string(value="INFO",
                                                    color="blue")))
            start = time.time()
            for source in self.sources:
                if source.endswith(".py"):
                    parse_file(source)
                else:
                    for dirName, subdirList, fileList in os.walk(source,
                                                                 topdown=True):

                        if self.__skip(source, dirName):
                            continue

                        for file_path in glob(
                                os.path.join(os.path.dirname(dirName + "\\"),
                                             "*.py")):
                            if parse_file(file_path) is True:
                                continue
            for thread in CliRunner.__SCANNER_THREADS:
                thread.join()
            print(
                "[{status}] Scan finished in: {time} seconds. Found: {suites} suite(s)."
                .format(status=CliUtils.format_color_string(value="INFO",
                                                            color="blue"),
                        time="{0:.2f}".format(time.time() - start),
                        suites=CliUtils.format_bold_string(len(self.suites))))
        except KeyboardInterrupt:
            print("(Ctrl+C) Exiting!")
            exit(12)
        except BadCliParameters as err:
            print("[{status}] {error}.".format(
                status=CliUtils.format_color_string(value="ERROR",
                                                    color="red"),
                error=err))
            exit(120)
        except:
            print("[{status}] Unexpected error during scan for test suites.".
                  format(status=CliUtils.format_color_string(value="ERROR",
                                                             color="red")))
            CliUtils.print_color_traceback()
            exit(120)
Example #11
0
    def present_console_output(aggregator):
        def parse_exception(value):
            if value is not None:
                error = ""
                for line in value.split("\n"):
                    error += "\n\t\t  {}".format(line)
                return error

        report = aggregator.get_basic_report()
        test_report = report["tests"]
        suite_report = report["suites"]
        for status in TestCategory.ALL:
            value = "[{part}/{total} {percent}%] {status}".format(
                part=test_report[status],
                total=test_report["total"],
                status=status.upper(),
                percent=Aggregator.percentage(test_report["total"],
                                              test_report[status]))
            if test_report[status]:
                value = CliUtils.format_bold_string(value)
            print(value)
        print("")
        for suite, stats in suite_report.items():
            status = suite.metrics.get_metrics()["status"]
            if status is None:  # this means that something went wrong with custom event processing
                status = "*" + SuiteCategory.ERROR
            print(
                ">> [{status}] [{passed}/{total} {rate}%] [{runtime:0.2f}s] {module}.{name}"
                .format(
                    module=CliUtils.format_bold_string(
                        suite.get_class_module()),
                    name=CliUtils.format_bold_string(suite.get_class_name()),
                    status=CliUtils.format_bold_string(status.upper()),
                    runtime=suite.get_runtime(),
                    rate=Aggregator.percentage(stats["total"],
                                               stats[TestCategory.SUCCESS]),
                    passed=stats[TestCategory.SUCCESS],
                    total=stats["total"]))
            if status == SuiteCategory.IGNORE:
                print("\t|__ reason: {error}".format(
                    error=suite.metrics.get_metrics().get(
                        "initiation_error", None)))
            if status != SuiteCategory.SUCCESS:
                tests = suite.get_unsuccessful_tests()
                for test in tests:
                    test_metrics = test.metrics.get_metrics()
                    print("\t|__ test: {name}()".format(
                        name=CliUtils.format_bold_string(
                            test.get_function_name())))
                    for class_param, class_param_data in test_metrics.items():
                        if class_param != "None":
                            print("\t  |__ class parameter: {class_parameter}".
                                  format(class_parameter=class_param))
                        for param, param_data in class_param_data.items():
                            if param != "None":
                                print(
                                    "\t    |__ parameter: {parameter}".format(
                                        parameter=param))
                            for index in range(param_data["retry"]):
                                trace = param_data["tracebacks"][index]
                                if trace is not None:
                                    trace = ":: Traceback: {}".format(
                                        CliUtils.format_color_string(
                                            parse_exception(
                                                trace.encode(
                                                    'utf8',
                                                    errors="replace").decode(
                                                        "utf8")), "red"))
                                else:
                                    trace = ""
                                print(
                                    "\t      |__ run #{num} [{status}] [{runtime:0.2f}s] {trace}"
                                    .format(num=index + 1,
                                            trace=trace,
                                            runtime=param_data["performance"]
                                            [index],
                                            status=param_data["statuses"]
                                            [index].upper()))
        print("\n===========================================================")
        print(". Test Junkie {} (Python{}) {} .".format(
            pkg_resources.require("test-junkie")[0].version,
            sys.version_info[0], DocumentationLinks.DOMAIN))
        print("===========================================================")
Example #12
0
    def print_results(self):

        from test_junkie.cli.cli import CliUtils
        match_found = False
        output = []
        for data_context in CliAudit.__SECTIONS:
            if data_context == self.args.command:
                data = self.aggregated_data["context_by_{context}".format(
                    context=data_context)]
                if data:
                    section = []
                    _sorted_data = sorted(data.items(),
                                          key=lambda x: x[1]["total_tests"])
                    _sorted_data.reverse()
                    _sorted_data = collections.OrderedDict(_sorted_data)
                    for primary_key, context in _sorted_data.items():
                        details = []
                        if data_context == "suites":
                            details.append(
                                "\nSuite: {value} Feature: {feature}".format(
                                    value=CliUtils.format_bold_string(
                                        primary_key),
                                    feature=CliUtils.format_bold_string(
                                        context["feature"])))
                        else:
                            parent = "".join(
                                list(data_context)
                                [:-1]).capitalize()  # exp: features > Feature
                            if primary_key is None:
                                primary_key = CliUtils.format_color_string(
                                    primary_key, "red")
                            else:
                                primary_key = CliUtils.format_bold_string(
                                    primary_key)
                            details.append("\n{parent}: {value}".format(
                                parent=parent, value=primary_key))

                        from test_junkie.metrics import Aggregator
                        details.append(
                            "\t- Tests:\t{total} of {absolute} total tests ({percentage}%)"
                            .format(total=context["total_tests"],
                                    absolute=self.
                                    aggregated_data["absolute_test_count"],
                                    percentage=Aggregator.percentage(
                                        self.
                                        aggregated_data["absolute_test_count"],
                                        context["total_tests"])))

                        for i in CliAudit.__SECTIONS:
                            if i in context:
                                msg = "\t"
                                counter = 0
                                _sorted_context = sorted(context[i].items(),
                                                         key=lambda x: x[1])
                                _sorted_context.reverse()
                                _sorted_context = collections.OrderedDict(
                                    _sorted_context)
                                for key, count in _sorted_context.items():
                                    if counter > 0:
                                        msg += "\n\t\t\t"
                                    if key is None:
                                        key = CliUtils.format_color_string(
                                            key, "red")
                                    msg += "{} ({})".format(key, count)
                                    counter += 1
                                if len(msg) > 0:
                                    details.append("\t- {i}: {msg}".format(
                                        i=i.capitalize(), msg=msg))
                        if len(details) >= 5:
                            section += details
                    if len(section) > 1:
                        output.append(section)
                    break

        for section in output:
            if len(section) >= 5:
                match_found = True
                for msg in section:
                    print(msg)

        if not match_found:
            print("[{status}] Nothing matches your search criteria!".format(
                status=CliUtils.format_color_string("INFO", "blue")))