forked from allure-framework/allure-python
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
allure-robotframework adapter (via allure-framework#214)
- Loading branch information
1 parent
54dc03b
commit d6e4f79
Showing
39 changed files
with
915 additions
and
74 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,53 +1,32 @@ | ||
|
||
import os | ||
from setuptools import setup | ||
|
||
PACKAGE = "allure-robotframework" | ||
|
||
classifiers = [ | ||
'Development Status :: 5 - Production/Stable', | ||
'Framework :: Robot Framework', | ||
'Framework :: Robot Framework :: Tool', | ||
'Intended Audience :: Developers', | ||
'License :: OSI Approved :: Apache Software License', | ||
'Topic :: Software Development :: Quality Assurance', | ||
'Topic :: Software Development :: Testing', | ||
] | ||
|
||
setup_requires = [ | ||
"setuptools_scm" | ||
] | ||
|
||
install_requires = [ | ||
"allure-python-commons==2.3.4b1", | ||
] | ||
|
||
|
||
def prepare_version(): | ||
from setuptools_scm import get_version | ||
configuration = {"root": "..", "relative_to": __file__} | ||
version = get_version(**configuration) | ||
install_requires.append("allure-python-commons=={version}".format(version=version)) | ||
return configuration | ||
PACKAGE = "allure-robotframework" | ||
VERSION = "0.1.3" | ||
|
||
|
||
def get_readme(fname): | ||
def read(fname): | ||
return open(os.path.join(os.path.dirname(__file__), fname)).read() | ||
|
||
|
||
if __name__ == '__main__': | ||
setup( | ||
name=PACKAGE, | ||
use_scm_version=prepare_version, | ||
version=VERSION, | ||
description="Allure Robot Framework integration", | ||
license="Apache-2.0", | ||
install_requires=install_requires, | ||
setup_requires=setup_requires, | ||
keywords="allure reporting robotframework", | ||
packages=['allure_robotframework', 'AllureLibrary'], | ||
package_dir={"allure_robotframework": "src/listener", 'AllureLibrary': 'src/library'}, | ||
packages=['allure_robotframework'], | ||
package_dir={"allure_robotframework": "src"}, | ||
install_requires=install_requires, | ||
py_modules=['allure_robotframework'], | ||
url="https://github.com/allure-framework/allure-python", | ||
url="https://github.com/skhomuti/allure-python", | ||
author="Sergey Khomutinin", | ||
author_email="[email protected]", | ||
long_description=get_readme('README.rst'), | ||
classifiers=classifiers, | ||
long_description=read('README.rst'), | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from allure_robotframework.listener import allure_robotframework | ||
|
||
__all__ = ['allure_robotframework'] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
class RobotStatus(object): | ||
FAILED = 'FAIL' | ||
PASSED = 'PASS' | ||
|
||
|
||
class RobotKeywordType(object): | ||
SETUP = 'Setup' | ||
TEARDOWN = 'Teardown' | ||
KEYWORD = 'Keyword' | ||
LOOP = 'FOR' | ||
LOOP_ITEM = 'FOR ITEM' | ||
FIXTURES = [SETUP, TEARDOWN] | ||
|
||
|
||
class RobotLogLevel(object): | ||
FAIL = 'FAIL' | ||
ERROR = 'ERROR' | ||
WARNING = 'WARN' | ||
INFORMATION = 'INFO' | ||
DEBUG = 'DEBUG' | ||
TRACE = 'TRACE' | ||
|
||
CRITICAL_LEVELS = [FAIL, ERROR] | ||
|
||
|
||
class RobotBasicKeywords(object): | ||
BUILTIN_LIB = 'BuiltIn' | ||
NO_OPERATION = BUILTIN_LIB + '.No Operation' | ||
FAIL = BUILTIN_LIB + '.Fail' | ||
LOG = BUILTIN_LIB + '.Log' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
from __future__ import absolute_import | ||
|
||
from collections import OrderedDict | ||
from allure_commons.model2 import TestResultContainer, TestResult, TestStepResult, TestAfterResult, TestBeforeResult, \ | ||
StatusDetails, Label, Link | ||
from allure_commons.reporter import AllureReporter | ||
from allure_commons.utils import now, uuid4, md5, host_tag | ||
from allure_commons.logger import AllureFileLogger | ||
from allure_commons.types import AttachmentType, LabelType, LinkType | ||
from allure_commons import plugin_manager | ||
from robot.libraries.BuiltIn import BuiltIn | ||
from allure_robotframework.constants import RobotKeywordType, RobotLogLevel | ||
from allure_robotframework import utils | ||
import os | ||
|
||
|
||
# noinspection PyPep8Naming | ||
class allure_robotframework(object): | ||
ROBOT_LISTENER_API_VERSION = 2 | ||
DEFAULT_OUTPUT_PATH = os.path.join('output', 'allure') | ||
LOG_MESSAGE_FORMAT = '{full_message}<p><b>[{level}]</b> {message}</p>' | ||
FAIL_MESSAGE_FORMAT = '{full_message}<p style="color: red"><b>[{level}]</b> {message}</p>' | ||
|
||
def __init__(self, logger_path=DEFAULT_OUTPUT_PATH): | ||
self.reporter = AllureReporter() | ||
self.logger = AllureFileLogger(logger_path) | ||
self.stack = [] | ||
self.items_log = {} | ||
self.pool_id = None | ||
self.links = OrderedDict() | ||
plugin_manager.register(self.reporter) | ||
plugin_manager.register(self.logger) | ||
|
||
def start_suite(self, name, attributes): | ||
if not self.pool_id: | ||
self.pool_id = BuiltIn().get_variable_value('${PABOTEXECUTIONPOOLID}') | ||
self.pool_id = int(self.pool_id) if self.pool_id else 0 | ||
self.start_new_group(name, attributes) | ||
|
||
def end_suite(self, name, attributes): | ||
self.stop_current_group() | ||
|
||
def start_test(self, name, attributes): | ||
self.start_new_group(name, attributes) | ||
self.start_new_test(name, attributes) | ||
|
||
def end_test(self, name, attributes): | ||
self.stop_current_test(name, attributes) | ||
self.stop_current_group() | ||
|
||
def start_keyword(self, name, attributes): | ||
self.start_new_keyword(name, attributes) | ||
|
||
def end_keyword(self, name, attributes): | ||
self.end_current_keyword(name, attributes) | ||
|
||
def log_message(self, message): | ||
level = message.get('level') | ||
if level == RobotLogLevel.FAIL: | ||
self.reporter.get_item(self.stack[-1]).statusDetails = StatusDetails(message=message.get('message')) | ||
self.append_message_to_last_item_log(message, level) | ||
|
||
# listener event ends | ||
def start_new_group(self, name, attributes): | ||
uuid = uuid4() | ||
self.set_suite_link(attributes.get('metadata'), uuid) | ||
if self.stack: | ||
parent_suite = self.reporter.get_last_item(TestResultContainer) | ||
parent_suite.children.append(uuid) | ||
self.stack.append(uuid) | ||
suite = TestResultContainer(uuid=uuid, | ||
name=name, | ||
description=attributes.get('doc'), | ||
start=now()) | ||
self.reporter.start_group(uuid, suite) | ||
|
||
def stop_current_group(self): | ||
uuid = self.stack.pop() | ||
self.remove_suite_link(uuid) | ||
self.reporter.stop_group(uuid, stop=now()) | ||
|
||
def start_new_test(self, name, attributes): | ||
uuid = uuid4() | ||
self.reporter.get_last_item(TestResultContainer).children.append(uuid) | ||
self.stack.append(uuid) | ||
test_case = TestResult(uuid=uuid, | ||
historyId=md5(attributes.get('longname')), | ||
name=name, | ||
fullName=attributes.get('longname'), | ||
start=now()) | ||
self.reporter.schedule_test(uuid, test_case) | ||
|
||
def stop_current_test(self, name, attributes): | ||
uuid = self.stack.pop() | ||
test = self.reporter.get_test(uuid) | ||
test.status = utils.get_allure_status(attributes.get('status')) | ||
test.labels.extend(utils.get_allure_suites(attributes.get('longname'))) | ||
test.labels.extend(utils.get_allure_tags(attributes.get('tags'))) | ||
test.labels.append(utils.get_allure_thread(self.pool_id)) | ||
test.labels.append(Label(LabelType.HOST, value=host_tag())) | ||
test.statusDetails = StatusDetails(message=attributes.get('message')) | ||
test.description = attributes.get('doc') | ||
last_link = list(self.links.values())[-1] if self.links else None | ||
if last_link: | ||
test.links.append(Link(LinkType.LINK, last_link, 'Link')) | ||
test.stop = now() | ||
self.reporter.close_test(uuid) | ||
|
||
def start_new_keyword(self, name, attributes): | ||
uuid = uuid4() | ||
parent_uuid = self.stack[-1] | ||
step_name = '{} = {}'.format(attributes.get('assign')[0], name) if attributes.get('assign') else name | ||
args = { | ||
'name': step_name, | ||
'description': attributes.get('doc'), | ||
'parameters': utils.get_allure_parameters(attributes.get('args')), | ||
'start': now() | ||
} | ||
keyword_type = attributes.get('type') | ||
last_item = self.reporter.get_last_item() | ||
if keyword_type in RobotKeywordType.FIXTURES and not isinstance(last_item, TestStepResult): | ||
if isinstance(last_item, TestResult): | ||
parent_uuid = self.stack[-2] | ||
if keyword_type == RobotKeywordType.SETUP: | ||
self.reporter.start_before_fixture(parent_uuid, uuid, TestBeforeResult(**args)) | ||
elif keyword_type == RobotKeywordType.TEARDOWN: | ||
self.reporter.start_after_fixture(parent_uuid, uuid, TestAfterResult(**args)) | ||
self.stack.append(uuid) | ||
return | ||
self.stack.append(uuid) | ||
self.reporter.start_step(parent_uuid=parent_uuid, | ||
uuid=uuid, | ||
step=TestStepResult(**args)) | ||
|
||
def end_current_keyword(self, name, attributes): | ||
uuid = self.stack.pop() | ||
if uuid in self.items_log: | ||
self.reporter.attach_data(uuid=uuid4(), | ||
body=self.items_log.pop(uuid).replace('\n', '<br>'), | ||
name='Keyword Log', | ||
attachment_type=AttachmentType.HTML) | ||
args = { | ||
'uuid': uuid, | ||
'status': utils.get_allure_status(attributes.get('status')), | ||
'stop': now() | ||
} | ||
keyword_type = attributes.get('type') | ||
parent_item = self.reporter.get_last_item() | ||
if keyword_type in RobotKeywordType.FIXTURES and not isinstance(parent_item, TestStepResult): | ||
if keyword_type == RobotKeywordType.SETUP: | ||
self.reporter.stop_before_fixture(**args) | ||
return | ||
elif keyword_type == RobotKeywordType.TEARDOWN: | ||
self.reporter.stop_after_fixture(**args) | ||
return | ||
self.reporter.stop_step(**args) | ||
|
||
def append_message_to_last_item_log(self, message, level): | ||
full_message = self.items_log[self.stack[-1]] if self.stack[-1] in self.items_log else '' | ||
message_format = self.FAIL_MESSAGE_FORMAT if level in RobotLogLevel.CRITICAL_LEVELS else self.LOG_MESSAGE_FORMAT | ||
self.items_log[self.stack[-1]] = message_format.format(full_message=full_message, | ||
level=message.get('level'), | ||
message=message.get('message')) | ||
|
||
def set_suite_link(self, metadata, uuid): | ||
if metadata: | ||
link = metadata.get('Link') | ||
if link: | ||
self.links[uuid] = link | ||
|
||
def remove_suite_link(self, uuid): | ||
if self.links.get(uuid): | ||
self.links.pop(uuid) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
from __future__ import absolute_import | ||
from allure_commons.model2 import Status, Label, Parameter | ||
from allure_commons.types import LabelType | ||
from allure_robotframework.constants import RobotStatus | ||
|
||
|
||
def get_allure_status(status): | ||
return Status.PASSED if status == RobotStatus.PASSED else Status.FAILED | ||
|
||
|
||
def get_allure_parameters(parameters): | ||
return [Parameter(name="arg{}".format(i + 1), value=param) for i, param in enumerate(parameters)] | ||
|
||
|
||
def get_allure_suites(longname): | ||
""" | ||
>>> get_allure_suites('Suite1.Test') | ||
[Label(name='suite', value='Suite1')] | ||
>>> get_allure_suites('Suite1.Suite2.Test') | ||
[Label(name='suite', value='Suite1'), Label(name='subSuite', value='Suite2')] | ||
>>> get_allure_suites('Suite1.Suite2.Suite3.Test') # doctest: +NORMALIZE_WHITESPACE | ||
[Label(name='parentSuite', value='Suite1'), | ||
Label(name='suite', value='Suite2'), | ||
Label(name='subSuite', value='Suite3')] | ||
""" | ||
labels = [] | ||
suites = longname.split('.') | ||
if len(suites) > 3: | ||
labels.append(Label('parentSuite', suites.pop(0))) | ||
labels.append(Label('suite', suites.pop(0))) | ||
if len(suites) > 1: | ||
labels.append(Label('subSuite', '.'.join(suites[:-1]))) | ||
return labels | ||
|
||
|
||
def get_allure_tags(tags): | ||
return [Label(LabelType.TAG, tag) for tag in tags] | ||
|
||
|
||
def get_allure_thread(pool_id): | ||
return Label(LabelType.THREAD, 'Thread #{number}'.format(number=pool_id)) |
Empty file.
Empty file.
8 changes: 8 additions & 0 deletions
8
allure-robotframework/test/description/case_with_description.robot
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
*** Test Cases *** | ||
Case With Description | ||
[Documentation] Case description | ||
No Operation | ||
|
||
Case With Dynamic Description | ||
[Documentation] Start description | ||
Set Test Documentation End description |
Oops, something went wrong.