diff --git a/allure-pytest/src/plugin.py b/allure-pytest/src/plugin.py index 52a8eaff..0e0bbe5b 100644 --- a/allure-pytest/src/plugin.py +++ b/allure-pytest/src/plugin.py @@ -5,7 +5,7 @@ import os from allure_commons.types import LabelType, Severity -from allure_commons.logger import AllureFileLogger +from allure_commons.logger import AllureFileLogger, AllureHTTPLogger from allure_commons.utils import get_testplan from allure_pytest.utils import allure_label, allure_labels, allure_full_name @@ -24,6 +24,25 @@ def pytest_addoption(parser): default=None, help="Generate Allure report in the specified directory (may not exist)") + parser.getgroup("reporting").addoption('--allureserver', + action="store", + dest="allure_server", + metavar="URL", + default=None, + help="Generate Allure report to a remote allure server") + + parser.getgroup("reporting").addoption('--projectid', + action="store", + dest="project_id", + metavar="STR", + default=None, + help="Project id for remote allure server") + + parser.getgroup("reporting").addoption('--clean-allurehistory', + action="store_true", + dest="clean_allurehistory", + help="Clean allure history in remote server") + parser.getgroup("reporting").addoption('--clean-alluredir', action="store_true", dest="clean_alluredir", @@ -152,11 +171,15 @@ def pytest_addhooks(pluginmanager): def pytest_configure(config): report_dir = config.option.allure_report_dir clean = config.option.clean_alluredir + clean_history = config.option.clean_allurehistory + allure_server = config.option.allure_server + project_id = config.option.project_id test_helper = AllureTestHelper(config) allure_commons.plugin_manager.register(test_helper) config.add_cleanup(cleanup_factory(test_helper)) + test_listener = None if report_dir: report_dir = os.path.abspath(report_dir) test_listener = AllureListener(config) @@ -168,6 +191,19 @@ def pytest_configure(config): allure_commons.plugin_manager.register(file_logger) config.add_cleanup(cleanup_factory(file_logger)) + if allure_server: + if not test_listener: + test_listener = AllureListener(config) + config.pluginmanager.register(test_listener, 'allure_listener') + allure_commons.plugin_manager.register(test_listener) + config.add_cleanup(cleanup_factory(test_listener)) + + http_logger = AllureHTTPLogger(allure_server, project_id, clean_history) + allure_commons.plugin_manager.register(http_logger) + config.add_cleanup(cleanup_factory(http_logger)) + config.add_cleanup(http_logger.create_report) + config.add_cleanup(http_logger.send_results) + config.addinivalue_line("markers", f"{ALLURE_LABEL_MARK}: allure label marker") config.addinivalue_line("markers", f"{ALLURE_LINK_MARK}: allure link marker") config.addinivalue_line("markers", f"{ALLURE_DESCRIPTION_MARK}: allure description") diff --git a/allure-python-commons/src/logger.py b/allure-python-commons/src/logger.py index c3a69299..c03a500c 100644 --- a/allure-python-commons/src/logger.py +++ b/allure-python-commons/src/logger.py @@ -1,9 +1,11 @@ +import base64 import io import os from pathlib import Path import json import uuid import shutil +import requests from attr import asdict from allure_commons import hookimpl @@ -53,6 +55,86 @@ def report_attached_data(self, body, file_name): attached_file.write(body) +class AllureHTTPLogger: + + def __init__(self, allure_server, project_id, clean=False): + self._allure_server = allure_server + self._project_id = project_id + self._headers = {'Content-type': 'application/json'} + self._ssl_verification = True + self._results = [] + if clean: + self.clean_history() + + def _report_item(self, item): + filename = item.file_pattern.format(prefix=uuid.uuid4()) + data = asdict( + item, + filter=lambda attr, value: not ( + type(value) != bool and not bool(value) + ) + ) + json_data = json.dumps(data, ensure_ascii=False) + b64_content = base64.b64encode(json_data.encode('utf-8')) + self._results.append({'file_name': filename, 'content_base64': b64_content.decode('UTF-8')}) + + @hookimpl + def send_results(self): + if self._results: + self._send_post_request('send-results', self._results) + self._results = [] + + @hookimpl + def create_report(self, execution_name=None): + return self._send_get_request('generate-report', + params={'execution_name': execution_name or uuid.uuid4(), + 'execution_from': 'Python', + 'execution_type': 'github'}) + + @hookimpl + def report_result(self, result): + self._report_item(result) + + @hookimpl + def report_container(self, container): + self._report_item(container) + + @hookimpl + def report_attached_file(self, source, file_name): + b64_content = base64.b64encode(source) + self._results.append({'file_name': file_name, 'content_base64': b64_content.decode('UTF-8')}) + + @hookimpl + def report_attached_data(self, body, file_name): + if isinstance(body, str): + b64_content = base64.b64encode(body.encode('utf-8')) + else: + b64_content = base64.b64encode(body) + self._results.append({'file_name': file_name, 'content_base64': b64_content.decode('UTF-8')}) + + def clean_results(self): + self._send_get_request('clean-results') + + def clean_history(self): + self._send_get_request('clean-history') + + def _send_post_request(self, route: str, results: list): + request_body = {"results": results} + json_request_body = json.dumps(request_body) + + request_url = f'{self._allure_server}/allure-docker-service/{route}?project_id={self._project_id}' + response = requests.post(request_url, headers=self._headers, data=json_request_body, + verify=self._ssl_verification) + response.raise_for_status() # Raising exception if response is not ok + return json.loads(response.content) + + def _send_get_request(self, route: str, params: dict = None): + request_url = f'{self._allure_server}/allure-docker-service/{route}?project_id={self._project_id}' + response = requests.get(request_url, params=params, headers=self._headers, verify=self._ssl_verification) + response.raise_for_status() # Raising exception if response is not ok + return json.loads(response.content) + + class AllureMemoryLogger: def __init__(self): diff --git a/requirements/testing.txt b/requirements/testing.txt index 09919cdf..3dd7d86e 100644 --- a/requirements/testing.txt +++ b/requirements/testing.txt @@ -5,3 +5,4 @@ poethepoet PyHamcrest Pygments pytest +requests \ No newline at end of file diff --git a/requirements/testing/allure-python-commons.txt b/requirements/testing/allure-python-commons.txt index 84ed3139..c0608fc4 100644 --- a/requirements/testing/allure-python-commons.txt +++ b/requirements/testing/allure-python-commons.txt @@ -1 +1 @@ -# allure_commons testing deps +# allure_commons testing deps \ No newline at end of file