Esempio n. 1
0
 def update_decorator_metrics(self,
                              decorator,
                              start_time,
                              exception=None,
                              trace=None):
     from test_junkie.objects import Limiter
     self.__stats[decorator]["performance"].append(time.time() - start_time)
     self.__stats[decorator]["exceptions"].append(
         Limiter.parse_exception_object(exception))
     self.__stats[decorator]["tracebacks"].append(
         Limiter.parse_traceback(trace))
Esempio n. 2
0
    def update_metrics(self,
                       status,
                       start_time,
                       param=None,
                       class_param=None,
                       exception=None,
                       formatted_traceback=None,
                       runtime=None,
                       decorator=None):
        def __get_template():

            return {
                "status": None,
                "retry": 0,
                "performance": [],
                "exceptions": [],
                "tracebacks": [],
                DecoratorType.BEFORE_TEST: {
                    "performance": [],
                    "exceptions": [],
                    "tracebacks": []
                },
                DecoratorType.AFTER_TEST: {
                    "performance": [],
                    "exceptions": [],
                    "tracebacks": []
                }
            }

        runtime = runtime if runtime is not None else time.time() - start_time
        string_param = str(param)
        string_class_param = str(class_param)
        if string_class_param not in self.__stats:
            self.__stats.update(
                {string_class_param: {
                    string_param: __get_template()
                }})
        elif string_param not in self.__stats[string_class_param]:
            self.__stats[string_class_param].update(
                {string_param: __get_template()})

        from test_junkie.objects import Limiter
        if decorator is not None:
            self.__stats[string_class_param][string_param][decorator][
                "performance"].append(time.time() - start_time)
            self.__stats[string_class_param][string_param][decorator]["exceptions"]\
                .append(Limiter.parse_exception_object(exception))
            self.__stats[string_class_param][string_param][decorator]["tracebacks"]\
                .append(Limiter.parse_traceback(formatted_traceback))

            if self.__stats[string_class_param][string_param]["status"] is None:
                # while status is not set, will use one that is currently passed in
                # Once its explicitly updated for the test decorator, then we wont change it
                self.__stats[string_class_param][string_param][
                    "status"] = status
        else:
            self.__stats[string_class_param][string_param][
                "performance"].append(runtime)
            self.__stats[string_class_param][string_param]["exceptions"]\
                .append(Limiter.parse_exception_object(exception))
            self.__stats[string_class_param][string_param]["tracebacks"]\
                .append(Limiter.parse_traceback(formatted_traceback))
            self.__stats[string_class_param][string_param]["retry"] += 1
            self.__stats[string_class_param][string_param]["status"] = status
            self.__stats[string_class_param][string_param]["param"] = param
            self.__stats[string_class_param][string_param][
                "class_param"] = class_param
Esempio n. 3
0
    def __run_suite(self, suite):
        def before_group_rule_failed():
            for group, _result in self.__before_group_failure_records.items():
                if suite.get_class_object() in _result["definition"]["suites"]:
                    return _result["trace"]

        suite_start_time = time.time()
        unsuccessful_tests = None
        exception = Runner.__validate_suite_parameters(suite)

        if not exception:
            exception = before_group_rule_failed()
            if not exception:
                result = self.__group_rules.run_before_group(
                    suite, DecoratorType.BEFORE_GROUP)
                if result is not None:
                    self.__before_group_failure_records.update(result)
                    exception = result[list(result.keys())[0]]["trace"]

        if not suite.can_skip(
                self.__settings) and not self.__cancel and not exception:
            Runner.__process_event(event=Event.ON_CLASS_IN_PROGRESS,
                                   suite=suite)
            for suite_retry_attempt in range(1, suite.get_retry_limit() + 1):
                if suite_retry_attempt == 1 or suite.get_status(
                ) in SuiteCategory.ALL_UN_SUCCESSFUL:

                    for class_param in suite.get_parameters(
                            process_functions=True):
                        LogJunkie.debug("Running suite: {}".format(
                            suite.get_class_object()))
                        LogJunkie.debug(
                            "Suite Retry {}/{} with Param: {}".format(
                                suite_retry_attempt, suite.get_retry_limit(),
                                class_param))

                        before_class_error = Runner.__run_before_class(
                            suite, class_param)

                        if suite_retry_attempt > 1:
                            unsuccessful_tests = suite.get_unsuccessful_tests()
                            LogJunkie.debug(
                                "There are {} unsuccessful tests that need to be retried"
                                .format(len(unsuccessful_tests)))
                            if not unsuccessful_tests:
                                break
                            tests = unsuccessful_tests
                        else:
                            tests = list(suite.get_test_objects())

                        while tests:
                            for test in list(tests):

                                test_start_time = time.time(
                                )  # will use in case of a failure in context of this loop

                                if not self.__positive_skip_condition(test=test) and \
                                        Runner.__runnable_tags(test=test, tag_config=self.__settings.tags):

                                    if not test.is_parallelized():
                                        LogJunkie.debug(
                                            "Cant run test: {} in parallel with any other tests"
                                            .format(
                                                test.get_function_object()))
                                        ParallelProcessor.wait_currently_active_tests_to_finish(
                                        )

                                    bad_params = Runner.__validate_test_parameters(
                                        test)
                                    if bad_params is not None:
                                        tests.remove(test)
                                        test.metrics.update_metrics(
                                            status=TestCategory.IGNORE,
                                            start_time=test_start_time,
                                            exception=bad_params["exception"],
                                            formatted_traceback=bad_params[
                                                "trace"])
                                        Runner.__process_event(
                                            event=Event.ON_IGNORE,
                                            suite=suite,
                                            test=test,
                                            class_param=class_param,
                                            error=bad_params)
                                        continue

                                    while not self.__processor.test_qualifies(
                                            test):
                                        time.sleep(0.2)
                                        if test.get_priority() is None:
                                            continue

                                    for param in test.get_parameters(
                                            process_functions=True):
                                        if unsuccessful_tests is not None and \
                                                not test.is_qualified_for_retry(param, class_param=class_param):
                                            # If does not qualify with current parameter, will move to the next
                                            continue
                                        if ((self.__processor.
                                             test_multithreading()
                                             and param is None) or
                                            (self.__processor.
                                             test_multithreading() and
                                             test.parallelized_parameters()
                                             and param is not None)):

                                            while self.__processor.test_limit_reached(
                                            ):
                                                time.sleep(0.2)
                                            time.sleep(
                                                Limiter.get_test_throttling())
                                            self.__processor.run_test_in_a_thread(
                                                Runner.__run_test, suite, test,
                                                param, class_param,
                                                before_class_error,
                                                self.__cancel)
                                        else:
                                            Runner.__run_test(
                                                suite=suite,
                                                test=test,
                                                parameter=param,
                                                class_parameter=class_param,
                                                before_class_error=
                                                before_class_error,
                                                cancel=self.__cancel)
                                    tests.remove(test)

                                else:
                                    tests.remove(test)
                                    test.metrics.update_metrics(
                                        status=TestCategory.SKIP,
                                        start_time=test_start_time)
                                    Runner.__process_event(
                                        event=Event.ON_SKIP,
                                        suite=suite,
                                        test=test,
                                        class_param=class_param)
                        ParallelProcessor.wait_currently_active_tests_to_finish(
                        )
                        Runner.__run_after_class(suite, class_param)
                    suite.metrics.update_suite_metrics(
                        status=SuiteCategory.FAIL
                        if suite.has_unsuccessful_tests() else
                        SuiteCategory.SUCCESS,
                        start_time=suite_start_time)
            Runner.__process_event(event=Event.ON_CLASS_COMPLETE, suite=suite)
            after_group_failed = self.__group_rules.run_after_group(suite)
            if after_group_failed:
                event = Event.ON_AFTER_GROUP_FAIL if isinstance(
                    after_group_failed["exception"],
                    AssertionError) else Event.ON_AFTER_GROUP_ERROR
                Runner.__process_event(
                    event=event,
                    suite=suite,
                    error=after_group_failed["exception"],
                    formatted_traceback=after_group_failed["trace"])
        elif self.__cancel:
            suite.metrics.update_suite_metrics(status=SuiteCategory.CANCEL,
                                               start_time=suite_start_time)
            Runner.__process_event(event=Event.ON_CLASS_CANCEL, suite=suite)
        elif exception or before_group_rule_failed():
            suite.metrics.update_suite_metrics(status=SuiteCategory.IGNORE,
                                               start_time=suite_start_time,
                                               initiation_error=exception)
            Runner.__process_event(event=Event.ON_CLASS_IGNORE, suite=suite)
        else:
            suite.metrics.update_suite_metrics(status=SuiteCategory.SKIP,
                                               start_time=suite_start_time)
            Runner.__process_event(event=Event.ON_CLASS_SKIP, suite=suite)
Esempio n. 4
0
    def run(self, **kwargs):
        """
        Initiates the execution process that runs tests
        :return: None
        """
        self.__settings = Settings(runner_kwargs=self.__kwargs,
                                   run_kwargs=kwargs)
        initial_start_time = time.time()
        resource_monitor = None
        try:
            if self.__settings.monitor_resources:
                resource_monitor = ResourceMonitor()
                resource_monitor.start()
            self.__processor = ParallelProcessor(self.__settings)

            with suppressed_stdout(self.__settings.quiet):
                while self.__suites:
                    for suite in list(self.__suites):
                        suite_object = Builder.get_execution_roster().get(
                            suite, None)
                        if suite_object is not None:
                            if self.__processor.suite_multithreading(
                            ) and suite_object.is_parallelized():
                                while True:
                                    if self.__processor.suite_qualifies(
                                            suite_object):
                                        time.sleep(
                                            Limiter.get_suite_throttling())
                                        self.__executed_suites.append(
                                            suite_object)
                                        ParallelProcessor.run_suite_in_a_thread(
                                            self.__run_suite, suite_object)
                                        self.__suites.remove(suite)
                                        break
                                    elif suite_object.get_priority() is None:
                                        break
                                    else:
                                        time.sleep(1)
                            else:
                                if not suite_object.is_parallelized():
                                    LogJunkie.debug(
                                        "Cant run suite: {} in parallel with any other suites. Waiting for "
                                        "parallel suites to finish so I can run it by itself."
                                        .format(
                                            suite_object.get_class_object()))
                                    ParallelProcessor.wait_currently_active_suites_to_finish(
                                    )
                                self.__executed_suites.append(suite_object)
                                self.__run_suite(suite_object)
                                self.__suites.remove(suite)
                        else:
                            LogJunkie.warn(
                                "Suite: {} not found! Make sure that your input is correct. "
                                "If it is, make sure the use of Test Junkie's decorators "
                                "is correct.".format(suite))
                            self.__suites.remove(suite)
                    LogJunkie.debug("{} Suite(s) left in queue.".format(
                        len(self.__suites)))
                    time.sleep(0.2)

                ParallelProcessor.wait_currently_active_suites_to_finish()
        finally:
            if self.__settings.monitor_resources:
                resource_monitor.shutdown()

        runtime = time.time() - initial_start_time
        print("========== Test Junkie finished in {:0.2f} seconds ==========".
              format(runtime))
        aggregator = Aggregator(self.get_executed_suites())
        Aggregator.present_console_output(aggregator)
        if self.__settings.html_report:
            reporter = Reporter(
                monitoring_file=resource_monitor.get_file_path()
                if resource_monitor is not None else None,
                runtime=runtime,
                aggregator=aggregator,
                multi_threading_enabled=self.__processor.test_multithreading()
                or self.__processor.suite_multithreading())
            reporter.generate_html_report(self.__settings.html_report)
        XmlReporter.create_xml_report(write_file=self.__settings.xml_report,
                                      suites=self.get_executed_suites())
        if self.__settings.monitor_resources:
            resource_monitor.cleanup()
        return aggregator