Пример #1
0
class AllureListener(object):

    def __init__(self, config):
        self.config = config
        self.allure_logger = AllureReporter()
        self._cache = ItemCache()
        self._host = host_tag()
        self._thread = thread_tag()

    @allure_commons.hookimpl
    def start_step(self, uuid, title, params):
        parameters = [Parameter(name=name, value=value) for name, value in params.items()]
        step = TestStepResult(name=title, start=now(), parameters=parameters)
        self.allure_logger.start_step(None, uuid, step)

    @allure_commons.hookimpl
    def stop_step(self, uuid, exc_type, exc_val, exc_tb):
        self.allure_logger.stop_step(uuid,
                                     stop=now(),
                                     status=get_status(exc_val),
                                     statusDetails=get_status_details(exc_type, exc_val, exc_tb))

    @allure_commons.hookimpl
    def start_fixture(self, parent_uuid, uuid, name):
        after_fixture = TestAfterResult(name=name, start=now())
        self.allure_logger.start_after_fixture(parent_uuid, uuid, after_fixture)

    @allure_commons.hookimpl
    def stop_fixture(self, parent_uuid, uuid, name, exc_type, exc_val, exc_tb):
        self.allure_logger.stop_after_fixture(uuid,
                                              stop=now(),
                                              status=get_status(exc_val),
                                              statusDetails=get_status_details(exc_type, exc_val, exc_tb))

    @pytest.hookimpl(hookwrapper=True, tryfirst=True)
    def pytest_runtest_protocol(self, item, nextitem):
        uuid = self._cache.push(item.nodeid)
        test_result = TestResult(name=item.name, uuid=uuid, start=now(), stop=now())
        self.allure_logger.schedule_test(uuid, test_result)
        yield

    @pytest.hookimpl(hookwrapper=True)
    def pytest_runtest_setup(self, item):
        if not self._cache.get(item.nodeid):
            uuid = self._cache.push(item.nodeid)
            test_result = TestResult(name=item.name, uuid=uuid, start=now(), stop=now())
            self.allure_logger.schedule_test(uuid, test_result)

        yield

        uuid = self._cache.get(item.nodeid)
        test_result = self.allure_logger.get_test(uuid)
        for fixturedef in _test_fixtures(item):
            group_uuid = self._cache.get(fixturedef)
            if not group_uuid:
                group_uuid = self._cache.push(fixturedef)
                group = TestResultContainer(uuid=group_uuid)
                self.allure_logger.start_group(group_uuid, group)
            self.allure_logger.update_group(group_uuid, children=uuid)
        params = item.callspec.params if hasattr(item, 'callspec') else {}

        test_result.name = allure_name(item, params)
        full_name = allure_full_name(item)
        test_result.fullName = full_name
        test_result.historyId = md5(item.nodeid)
        test_result.testCaseId = md5(full_name)
        test_result.description = allure_description(item)
        test_result.descriptionHtml = allure_description_html(item)
        test_result.parameters.extend(
            [Parameter(name=name, value=represent(value)) for name, value in params.items()])

    @pytest.hookimpl(hookwrapper=True)
    def pytest_runtest_call(self, item):
        uuid = self._cache.get(item.nodeid)
        test_result = self.allure_logger.get_test(uuid)
        if test_result:
            self.allure_logger.drop_test(uuid)
            self.allure_logger.schedule_test(uuid, test_result)
            test_result.start = now()
        yield
        if test_result:
            test_result.stop = now()

    @pytest.hookimpl(hookwrapper=True)
    def pytest_runtest_teardown(self, item):
        yield
        uuid = self._cache.get(item.nodeid)
        test_result = self.allure_logger.get_test(uuid)
        test_result.labels.extend([Label(name=name, value=value) for name, value in allure_labels(item)])
        test_result.labels.extend([Label(name=LabelType.TAG, value=value) for value in pytest_markers(item)])
        test_result.labels.extend([Label(name=name, value=value) for name, value in allure_suite_labels(item)])
        test_result.labels.append(Label(name=LabelType.HOST, value=self._host))
        test_result.labels.append(Label(name=LabelType.THREAD, value=self._thread))
        test_result.labels.append(Label(name=LabelType.FRAMEWORK, value='pytest'))
        test_result.labels.append(Label(name=LabelType.LANGUAGE, value=platform_label()))
        test_result.labels.append(Label(name='package', value=allure_package(item)))
        test_result.links.extend([Link(link_type, url, name) for link_type, url, name in allure_links(item)])

    @pytest.hookimpl(hookwrapper=True)
    def pytest_fixture_setup(self, fixturedef, request):
        fixture_name = getattr(fixturedef.func, '__allure_display_name__', fixturedef.argname)

        container_uuid = self._cache.get(fixturedef)

        if not container_uuid:
            container_uuid = self._cache.push(fixturedef)
            container = TestResultContainer(uuid=container_uuid)
            self.allure_logger.start_group(container_uuid, container)

        self.allure_logger.update_group(container_uuid, start=now())

        before_fixture_uuid = uuid4()
        before_fixture = TestBeforeResult(name=fixture_name, start=now())
        self.allure_logger.start_before_fixture(container_uuid, before_fixture_uuid, before_fixture)

        outcome = yield

        self.allure_logger.stop_before_fixture(before_fixture_uuid,
                                               stop=now(),
                                               status=get_outcome_status(outcome),
                                               statusDetails=get_outcome_status_details(outcome))

        finalizers = getattr(fixturedef, '_finalizers', [])
        for index, finalizer in enumerate(finalizers):
            name = '{fixture}::{finalizer}'.format(fixture=fixture_name,
                                                   finalizer=getattr(finalizer, "__name__", index))
            finalizers[index] = allure_commons.fixture(finalizer, parent_uuid=container_uuid, name=name)

    @pytest.hookimpl(hookwrapper=True)
    def pytest_fixture_post_finalizer(self, fixturedef):
        yield
        if hasattr(fixturedef, 'cached_result') and self._cache.get(fixturedef):
            container_uuid = self._cache.pop(fixturedef)
            self.allure_logger.stop_group(container_uuid, stop=now())

    @pytest.hookimpl(hookwrapper=True)
    def pytest_runtest_makereport(self, item, call):
        uuid = self._cache.get(item.nodeid)

        report = (yield).get_result()

        test_result = self.allure_logger.get_test(uuid)
        status = get_pytest_report_status(report)
        status_details = None

        if call.excinfo:
            message = escape_non_unicode_symbols(call.excinfo.exconly())
            if hasattr(report, 'wasxfail'):
                reason = report.wasxfail
                message = ('XFAIL {}'.format(reason) if reason else 'XFAIL') + '\n\n' + message
            trace = escape_non_unicode_symbols(report.longreprtext)
            status_details = StatusDetails(
                message=message,
                trace=trace)
            if (status != Status.SKIPPED
                    and not (call.excinfo.errisinstance(AssertionError)
                             or call.excinfo.errisinstance(pytest.fail.Exception))):
                status = Status.BROKEN

        if status == Status.PASSED and hasattr(report, 'wasxfail'):
            reason = report.wasxfail
            message = 'XPASS {reason}'.format(reason=reason) if reason else 'XPASS'
            status_details = StatusDetails(message=message)

        if report.when == 'setup':
            test_result.status = status
            test_result.statusDetails = status_details

        if report.when == 'call':
            if test_result.status == Status.PASSED:
                test_result.status = status
                test_result.statusDetails = status_details

        if report.when == 'teardown':
            if status in (Status.FAILED, Status.BROKEN) and test_result.status == Status.PASSED:
                test_result.status = status
                test_result.statusDetails = status_details

            if self.config.option.attach_capture:
                if report.caplog:
                    self.attach_data(report.caplog, "log", AttachmentType.TEXT, None)
                if report.capstdout:
                    self.attach_data(report.capstdout, "stdout", AttachmentType.TEXT, None)
                if report.capstderr:
                    self.attach_data(report.capstderr, "stderr", AttachmentType.TEXT, None)

    @pytest.hookimpl(hookwrapper=True)
    def pytest_runtest_logfinish(self, nodeid, location):
        yield
        uuid = self._cache.pop(nodeid)
        if uuid:
            self.allure_logger.close_test(uuid)

    @allure_commons.hookimpl
    def attach_data(self, body, name, attachment_type, extension):
        self.allure_logger.attach_data(uuid4(), body, name=name, attachment_type=attachment_type, extension=extension)

    @allure_commons.hookimpl
    def attach_file(self, source, name, attachment_type, extension):
        self.allure_logger.attach_file(uuid4(), source, name=name, attachment_type=attachment_type, extension=extension)

    @allure_commons.hookimpl
    def add_title(self, test_title):
        test_result = self.allure_logger.get_test(None)
        if test_result:
            test_result.name = test_title

    @allure_commons.hookimpl
    def add_description(self, test_description):
        test_result = self.allure_logger.get_test(None)
        if test_result:
            test_result.description = test_description

    @allure_commons.hookimpl
    def add_description_html(self, test_description_html):
        test_result = self.allure_logger.get_test(None)
        if test_result:
            test_result.descriptionHtml = test_description_html

    @allure_commons.hookimpl
    def add_link(self, url, link_type, name):
        test_result = self.allure_logger.get_test(None)
        if test_result:
            pattern = dict(self.config.option.allure_link_pattern).get(link_type, u'{}')
            link_url = pattern.format(url)
            new_link = Link(link_type, link_url, link_url if name is None else name)
            for link in test_result.links:
                if link.url == new_link.url:
                    return
            test_result.links.append(new_link)

    @allure_commons.hookimpl
    def add_label(self, label_type, labels):
        test_result = self.allure_logger.get_test(None)
        for label in labels if test_result else ():
            test_result.labels.append(Label(label_type, label))
Пример #2
0
class AllureListener(object):
    def __init__(self, behave_config):
        self.behave_config = behave_config
        self.logger = AllureReporter()
        self.current_step_uuid = None
        self.current_scenario_uuid = None
        self.execution_context = Context()
        self.fixture_context = Context()
        self.steps = deque()

    def __del__(self):
        for group in self.fixture_context.exit():
            group.children.extend(self.execution_context)
            self.logger.stop_group(group.uuid)

    @allure_commons.hookimpl
    def start_fixture(self, parent_uuid, uuid, name, parameters):
        parameters = [Parameter(name=param_name, value=param_value) for param_name, param_value in parameters.items()]

        if name in FIXTURES and not self.fixture_context:
            group = TestResultContainer(uuid=uuid4())
            self.logger.start_group(group.uuid, group)
            self.fixture_context.append(group)

        if name in BEFORE_FIXTURES:
            fixture = TestBeforeResult(name=name, start=now(), parameters=parameters)
            for group in self.fixture_context:
                self.logger.start_before_fixture(group.uuid, uuid, fixture)

        elif name in AFTER_FIXTURES:
            fixture = TestAfterResult(name=name, start=now(), parameters=parameters)
            for group in self.fixture_context:
                self.logger.start_after_fixture(group.uuid, uuid, fixture)

    @allure_commons.hookimpl
    def stop_fixture(self, parent_uuid, uuid, name, exc_type, exc_val, exc_tb):
        if name in FIXTURES:
            self.logger.stop_before_fixture(uuid=uuid,
                                            stop=now(),
                                            status=get_status(exc_val),
                                            statusDetails=get_status_details(exc_type, exc_val, exc_tb))

    def start_feature(self):
        self.execution_context.enter()
        self.fixture_context.enter()

    def stop_feature(self):
        uuids = self.execution_context.exit()
        for group in self.fixture_context.exit():
            group.children.extend(uuids)
            self.logger.stop_group(group.uuid)
        self.execution_context.extend(uuids)

    @allure_commons.hookimpl
    def start_test(self, parent_uuid, uuid, name, parameters, context):
        self.start_scenario(context['scenario'])

    def start_scenario(self, scenario):
        self.current_scenario_uuid = uuid4()
        self.fixture_context.enter()
        self.execution_context.enter()
        self.execution_context.append(self.current_scenario_uuid)

        test_case = TestResult(uuid=self.current_scenario_uuid, start=now())
        test_case.name = scenario_name(scenario)
        test_case.historyId = scenario_history_id(scenario)
        test_case.description = '\n'.join(scenario.description)
        test_case.parameters = scenario_parameters(scenario)
        test_case.labels.extend([Label(name=LabelType.TAG, value=tag) for tag in scenario_tags(scenario)])
        test_case.labels.append(Label(name=LabelType.SEVERITY, value=scenario_severity(scenario).value))
        test_case.labels.append(Label(name=LabelType.FEATURE, value=scenario.feature.name))
        test_case.labels.append(Label(name=LabelType.FRAMEWORK, value='behave'))
        test_case.labels.append(Label(name=LabelType.LANGUAGE, value=platform_label()))

        self.logger.schedule_test(self.current_scenario_uuid, test_case)

    @allure_commons.hookimpl
    def stop_test(self, parent_uuid, uuid, name, context, exc_type, exc_val, exc_tb):
        self.stop_scenario(context['scenario'])

    def stop_scenario(self, scenario):
        if scenario.status == 'skipped' and not self.behave_config.show_skipped:
            self.logger.drop_test(self.current_scenario_uuid)
        else:
            status = scenario_status(scenario)
            status_details = scenario_status_details(scenario)

            self.flush_steps()
            test_result = self.logger.get_test(self.current_scenario_uuid)
            test_result.stop = now()
            test_result.status = status
            test_result.statusDetails = status_details
            self.logger.close_test(self.current_scenario_uuid)
            self.current_step_uuid = None

            for group in self.fixture_context.exit():
                group.children.append(self.current_scenario_uuid)
                self.logger.stop_group(group.uuid)

        self.execution_context.exit()
        self.execution_context.append(self.current_scenario_uuid)
        self.current_scenario_uuid = None

    def schedule_step(self, step):
        self.steps.append(step)

    def match_step(self, match):
        step = self.steps.popleft()
        self.start_behave_step(step)

    def start_behave_step(self, step):

        self.current_step_uuid = uuid4()
        name = u'{keyword} {title}'.format(keyword=step.keyword, title=step.name)

        allure_step = TestStepResult(name=name, start=now())
        self.logger.start_step(None, self.current_step_uuid, allure_step)

        if step.text:
            self.logger.attach_data(uuid4(), step.text, name='.text', attachment_type=AttachmentType.TEXT)

        if step.table:
            self.logger.attach_data(uuid4(), step_table(step), name='.table', attachment_type=AttachmentType.CSV)

    def stop_behave_step(self, result):
        status = step_status(result)
        status_details = step_status_details(result)
        self.logger.stop_step(self.current_step_uuid, stop=now(), status=status, statusDetails=status_details)

    def flush_steps(self):
        while self.steps:
            step = self.steps.popleft()
            self.start_behave_step(step)
            self.stop_behave_step(step)

    @allure_commons.hookimpl
    def start_step(self, uuid, title, params):
        parameters = [Parameter(name=name, value=value) for name, value in params.items()]
        step = TestStepResult(name=title, start=now(), parameters=parameters)
        self.logger.start_step(None, uuid, step)

    @allure_commons.hookimpl
    def stop_step(self, uuid, exc_type, exc_val, exc_tb):
        self.logger.stop_step(uuid,
                              stop=now(),
                              status=get_status(exc_val),
                              statusDetails=get_status_details(exc_type, exc_val, exc_tb))

    @allure_commons.hookimpl
    def attach_data(self, body, name, attachment_type, extension):
        self.logger.attach_data(uuid4(), body, name=name, attachment_type=attachment_type, extension=extension)

    @allure_commons.hookimpl
    def attach_file(self, source, name, attachment_type, extension):
        self.logger.attach_file(uuid4(), source, name=name, attachment_type=attachment_type, extension=extension)
Пример #3
0
class AllureListener(object):
    def __init__(self, behave_config):
        self.behave_config = behave_config
        self.logger = AllureReporter()
        self.current_step_uuid = None
        self.current_scenario_uuid = None
        self.execution_context = Context()
        self.fixture_context = Context()
        self.steps = deque()

    def __del__(self):
        for group in self.fixture_context.exit():
            group.children.extend(self.execution_context)
            self.logger.stop_group(group.uuid)

    @allure_commons.hookimpl
    def start_fixture(self, parent_uuid, uuid, name, parameters):
        parameters = [
            Parameter(name=param_name, value=param_value)
            for param_name, param_value in parameters.items()
        ]

        if name in FIXTURES and not self.fixture_context:
            group = TestResultContainer(uuid=uuid4())
            self.logger.start_group(group.uuid, group)
            self.fixture_context.append(group)

        if name in BEFORE_FIXTURES:
            fixture = TestBeforeResult(name=name,
                                       start=now(),
                                       parameters=parameters)
            for group in self.fixture_context:
                self.logger.start_before_fixture(group.uuid, uuid, fixture)

        elif name in AFTER_FIXTURES:
            fixture = TestAfterResult(name=name,
                                      start=now(),
                                      parameters=parameters)
            for group in self.fixture_context:
                self.logger.start_after_fixture(group.uuid, uuid, fixture)

    @allure_commons.hookimpl
    def stop_fixture(self, parent_uuid, uuid, name, exc_type, exc_val, exc_tb):
        if name in FIXTURES:
            self.logger.stop_before_fixture(uuid=uuid,
                                            stop=now(),
                                            status=get_status(exc_val),
                                            statusDetails=get_status_details(
                                                exc_type, exc_val, exc_tb))

    def start_feature(self):
        self.execution_context.enter()
        self.fixture_context.enter()

    def stop_feature(self):
        uuids = self.execution_context.exit()
        for group in self.fixture_context.exit():
            group.children.extend(uuids)
            self.logger.stop_group(group.uuid)
        self.execution_context.extend(uuids)

    @allure_commons.hookimpl
    def start_test(self, parent_uuid, uuid, name, parameters, context):
        self.start_scenario(context['scenario'])

    def start_scenario(self, scenario):
        self.current_scenario_uuid = uuid4()
        self.fixture_context.enter()
        self.execution_context.enter()
        self.execution_context.append(self.current_scenario_uuid)

        test_case = TestResult(uuid=self.current_scenario_uuid, start=now())
        test_case.name = scenario_name(scenario)
        test_case.historyId = scenario_history_id(scenario)
        test_case.description = '\n'.join(scenario.description)
        test_case.parameters = scenario_parameters(scenario)

        test_case.links.extend(scenario_links(scenario))
        test_case.labels.extend(scenario_labels(scenario))
        test_case.labels.append(
            Label(name=LabelType.FEATURE, value=scenario.feature.name))
        test_case.labels.append(Label(name=LabelType.FRAMEWORK,
                                      value='behave'))
        test_case.labels.append(
            Label(name=LabelType.LANGUAGE, value=platform_label()))

        self.logger.schedule_test(self.current_scenario_uuid, test_case)

    @allure_commons.hookimpl
    def stop_test(self, parent_uuid, uuid, name, context, exc_type, exc_val,
                  exc_tb):
        self.stop_scenario(context['scenario'])

    def stop_scenario(self, scenario):
        if scenario.status == 'skipped' and not self.behave_config.show_skipped:
            self.logger.drop_test(self.current_scenario_uuid)
        else:
            status = scenario_status(scenario)
            status_details = scenario_status_details(scenario)

            self.flush_steps()
            test_result = self.logger.get_test(self.current_scenario_uuid)
            test_result.stop = now()
            test_result.status = status
            test_result.statusDetails = status_details
            self.logger.close_test(self.current_scenario_uuid)
            self.current_step_uuid = None

            for group in self.fixture_context.exit():
                group.children.append(self.current_scenario_uuid)
                self.logger.stop_group(group.uuid)

        self.execution_context.exit()
        self.execution_context.append(self.current_scenario_uuid)
        self.current_scenario_uuid = None

    def schedule_step(self, step):
        self.steps.append(step)

    def match_step(self, match):
        step = self.steps.popleft()
        self.start_behave_step(step)

    def start_behave_step(self, step):

        self.current_step_uuid = uuid4()
        name = u'{keyword} {title}'.format(keyword=step.keyword,
                                           title=step.name)

        allure_step = TestStepResult(name=name, start=now())
        self.logger.start_step(None, self.current_step_uuid, allure_step)

        if step.text:
            self.logger.attach_data(uuid4(),
                                    step.text,
                                    name='.text',
                                    attachment_type=AttachmentType.TEXT)

        if step.table:
            self.logger.attach_data(uuid4(),
                                    step_table(step),
                                    name='.table',
                                    attachment_type=AttachmentType.CSV)

    def stop_behave_step(self, result):
        status = step_status(result)
        status_details = step_status_details(result)
        self.logger.stop_step(self.current_step_uuid,
                              stop=now(),
                              status=status,
                              statusDetails=status_details)

    def flush_steps(self):
        while self.steps:
            step = self.steps.popleft()
            self.start_behave_step(step)
            self.stop_behave_step(step)

    @allure_commons.hookimpl
    def start_step(self, uuid, title, params):
        parameters = [
            Parameter(name=name, value=value)
            for name, value in params.items()
        ]
        step = TestStepResult(name=title, start=now(), parameters=parameters)
        self.logger.start_step(None, uuid, step)

    @allure_commons.hookimpl
    def stop_step(self, uuid, exc_type, exc_val, exc_tb):
        self.logger.stop_step(uuid,
                              stop=now(),
                              status=get_status(exc_val),
                              statusDetails=get_status_details(
                                  exc_type, exc_val, exc_tb))

    @allure_commons.hookimpl
    def attach_data(self, body, name, attachment_type, extension):
        self.logger.attach_data(uuid4(),
                                body,
                                name=name,
                                attachment_type=attachment_type,
                                extension=extension)

    @allure_commons.hookimpl
    def attach_file(self, source, name, attachment_type, extension):
        self.logger.attach_file(uuid4(),
                                source,
                                name=name,
                                attachment_type=attachment_type,
                                extension=extension)
Пример #4
0
class AllureListener(object):
    def __init__(self, behave_config):
        self.behave_config = behave_config
        self.issue_pattern = behave_config.userdata.get(
            'AllureFormatter.issue_pattern', None)
        self.link_pattern = behave_config.userdata.get(
            'AllureFormatter.link_pattern', None)
        self.hide_excluded = behave_config.userdata.get(
            'AllureFormatter.hide_excluded', False)
        self.logger = AllureReporter()
        self.current_step_uuid = None
        self.current_scenario_uuid = None
        self.group_context = GroupContext(self.logger)
        self.group_context.enter()
        self.steps = deque()

    def start_file(self):
        self.group_context.enter()

    @allure_commons.hookimpl
    def start_fixture(self, parent_uuid, uuid, name, parameters):
        # parameters = [Parameter(name=param_name, value=param_value) for param_name, param_value in parameters.items()]

        if name.startswith("before_"):
            name = get_hook_name(name, parameters)
            fixture = TestBeforeResult(name=name, start=now(), parameters=None)
            group = self.group_context.current_group()
            self.logger.start_before_fixture(group.uuid, uuid, fixture)

        elif name.startswith("after_"):
            name = get_hook_name(name, parameters)
            fixture = TestAfterResult(name=name, start=now(), parameters=None)
            group = self.group_context.current_group()
            self.logger.start_after_fixture(group.uuid, uuid, fixture)

    @allure_commons.hookimpl
    def stop_fixture(self, parent_uuid, uuid, name, exc_type, exc_val, exc_tb):
        self.logger.stop_before_fixture(uuid=uuid,
                                        stop=now(),
                                        status=get_status(exc_val),
                                        statusDetails=get_status_details(
                                            exc_type, exc_val, exc_tb))

    def stop_feature(self):
        self.group_context.exit()

    @allure_commons.hookimpl
    def start_test(self, parent_uuid, uuid, name, parameters, context):
        self.start_scenario(context['scenario'])

    def start_scenario(self, scenario):
        self.current_scenario_uuid = uuid4()
        self.group_context.enter()

        test_case = TestResult(uuid=self.current_scenario_uuid, start=now())
        test_case.name = scenario_name(scenario)
        test_case.fullName = get_fullname(scenario)
        test_case.historyId = scenario_history_id(scenario)
        test_case.description = '\n'.join(scenario.description)
        test_case.parameters = scenario_parameters(scenario)

        test_case.links.extend(
            scenario_links(scenario,
                           issue_pattern=self.issue_pattern,
                           link_pattern=self.link_pattern))
        test_case.labels.extend(scenario_labels(scenario))
        test_case.labels.append(
            Label(name=LabelType.FEATURE, value=scenario.feature.name))
        test_case.labels.append(Label(name=LabelType.FRAMEWORK,
                                      value='behave'))
        test_case.labels.append(
            Label(name=LabelType.LANGUAGE, value=platform_label()))

        self.logger.schedule_test(self.current_scenario_uuid, test_case)

    @allure_commons.hookimpl
    def stop_test(self, parent_uuid, uuid, name, context, exc_type, exc_val,
                  exc_tb):
        self.stop_scenario(context['scenario'])

    def stop_scenario(self, scenario):
        should_run = (scenario.should_run_with_tags(self.behave_config.tags)
                      and scenario.should_run_with_name_select(
                          self.behave_config))
        should_drop_skipped_by_option = scenario.status == 'skipped' and not self.behave_config.show_skipped
        should_drop_excluded = self.hide_excluded and (
            scenario.skip_reason == TEST_PLAN_SKIP_REASON or not should_run)

        if should_drop_skipped_by_option or should_drop_excluded:
            self.logger.drop_test(self.current_scenario_uuid)
        else:
            status = scenario_status(scenario)
            status_details = scenario_status_details(scenario)

            self.flush_steps()
            test_result = self.logger.get_test(self.current_scenario_uuid)
            test_result.stop = now()
            test_result.status = status
            test_result.statusDetails = status_details
            self.logger.close_test(self.current_scenario_uuid)
            self.current_step_uuid = None
            self.group_context.append_test(self.current_scenario_uuid)
            self.group_context.exit()

        self.current_scenario_uuid = None

    def schedule_step(self, step):
        self.steps.append(step)

    def match_step(self, match):
        step = self.steps.popleft()
        self.start_behave_step(step)

    def start_behave_step(self, step):

        self.current_step_uuid = uuid4()
        name = u'{keyword} {title}'.format(keyword=step.keyword,
                                           title=step.name)

        allure_step = TestStepResult(name=name, start=now())
        self.logger.start_step(None, self.current_step_uuid, allure_step)

        if step.text:
            self.logger.attach_data(uuid4(),
                                    step.text,
                                    name='.text',
                                    attachment_type=AttachmentType.TEXT)

        if step.table:
            self.logger.attach_data(uuid4(),
                                    step_table(step),
                                    name='.table',
                                    attachment_type=AttachmentType.CSV)

    def stop_behave_step(self, result):
        status = step_status(result)
        status_details = step_status_details(result)
        self.logger.stop_step(self.current_step_uuid,
                              stop=now(),
                              status=status,
                              statusDetails=status_details)

    def flush_steps(self):
        while self.steps:
            step = self.steps.popleft()
            self.start_behave_step(step)
            self.stop_behave_step(step)

    @allure_commons.hookimpl
    def start_step(self, uuid, title, params):
        parameters = [
            Parameter(name=name, value=value)
            for name, value in params.items()
        ]
        step = TestStepResult(name=title, start=now(), parameters=parameters)
        self.logger.start_step(None, uuid, step)

    @allure_commons.hookimpl
    def stop_step(self, uuid, exc_type, exc_val, exc_tb):
        self.logger.stop_step(uuid,
                              stop=now(),
                              status=get_status(exc_val),
                              statusDetails=get_status_details(
                                  exc_type, exc_val, exc_tb))

    @allure_commons.hookimpl
    def attach_data(self, body, name, attachment_type, extension):
        self.logger.attach_data(uuid4(),
                                body,
                                name=name,
                                attachment_type=attachment_type,
                                extension=extension)

    @allure_commons.hookimpl
    def attach_file(self, source, name, attachment_type, extension):
        self.logger.attach_file(uuid4(),
                                source,
                                name=name,
                                attachment_type=attachment_type,
                                extension=extension)

    @allure_commons.hookimpl
    def add_description(self, test_description):
        test_result = self.logger.get_test(None)
        if test_result:
            test_result.description = test_description

    @allure_commons.hookimpl
    def add_description_html(self, test_description_html):
        test_result = self.logger.get_test(None)
        if test_result:
            test_result.descriptionHtml = test_description_html

    @allure_commons.hookimpl
    def add_link(self, url, link_type, name):
        test_result = self.logger.get_test(None)
        if test_result:
            pattern = u'{}'
            if link_type == LinkType.ISSUE and self.issue_pattern:
                pattern = self.issue_pattern
            elif link_type == LinkType.LINK and self.link_pattern:
                pattern = self.link_pattern

            link_url = pattern.format(url)
            new_link = Link(link_type, link_url,
                            link_url if name is None else name)
            for link in test_result.links:
                if link.url == new_link.url:
                    return

            test_result.links.append(new_link)

    def stop_session(self):
        self.group_context.exit()