Skip to content

Commit 875e344

Browse files
authored
Merge pull request #328 from reportportal/develop
Release
2 parents fb09cc8 + 364cd19 commit 875e344

14 files changed

Lines changed: 180 additions & 53 deletions

File tree

.github/workflows/release.yml

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,27 @@ env:
3333

3434
jobs:
3535
deploy:
36-
runs-on: ubuntu-20.04
36+
runs-on: ubuntu-latest
3737
steps:
38-
- uses: actions/checkout@v3
38+
- name: Checkout repository
39+
uses: actions/checkout@v3
40+
41+
- name: Set up Python
42+
uses: actions/setup-python@v4
43+
with:
44+
python-version: '3.8'
45+
46+
- name: Install dependencies
47+
run: python -m pip install --upgrade pip setuptools wheel
48+
49+
- name: Build package
50+
run: python setup.py sdist bdist_wheel
51+
52+
- name: Publish package
53+
uses: pypa/gh-action-pypi-publish@release/v1
54+
with:
55+
user: ${{ secrets.PYPI_USERNAME }}
56+
password: ${{ secrets.PYPI_PASSWORD }}
3957

4058
- name: Generate versions
4159
uses: HardNorth/github-version-generate@v1
@@ -57,29 +75,6 @@ jobs:
5775
git tag -a ${{ env.RELEASE_VERSION }} -m "Release ${{ env.RELEASE_VERSION }}"
5876
git push --tags
5977
60-
- name: Set up Python
61-
uses: actions/setup-python@v4
62-
with:
63-
python-version: '3.6'
64-
65-
- name: Install dependencies
66-
run: python -m pip install --upgrade pip setuptools wheel
67-
68-
- name: Build package
69-
run: python setup.py sdist bdist_wheel
70-
71-
- name: Publish package
72-
uses: pypa/gh-action-pypi-publish@release/v1
73-
with:
74-
user: ${{ secrets.PYPI_USERNAME }}
75-
password: ${{ secrets.PYPI_PASSWORD }}
76-
77-
- name: Checkout develop branch
78-
uses: actions/checkout@v3
79-
with:
80-
ref: 'develop'
81-
fetch-depth: 0
82-
8378
- name: Update CHANGELOG.md
8479
id: changelogUpdate
8580
run: |
@@ -108,6 +103,12 @@ jobs:
108103
name: Release ${{ env.RELEASE_VERSION }}
109104
body: ${{ steps.readChangelogEntry.outputs.changes }}
110105

106+
- name: Checkout develop branch
107+
uses: actions/checkout@v3
108+
with:
109+
ref: 'develop'
110+
fetch-depth: 0
111+
111112
- name: Merge release branch into develop
112113
id: mergeIntoDevelop
113114
run: |

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
## [Unreleased]
44
### Added
5+
- Feature [#325](https://github.com/reportportal/agent-python-pytest/issues/325) Support of runtime attribute adding, by @yakovbabich, @HardNorth
6+
- `rp_launch_timeout` parameter to limit test execution in case of process hanging, by @HardNorth
7+
8+
## [5.1.3]
9+
### Added
510
- Support for thread logs and `rp_thread_logging` flag, by @dagansandler
611

712
## [5.1.2]

README.rst

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,19 @@ agent-python-pytest
77
:alt: Latest Version
88
.. image:: https://img.shields.io/pypi/pyversions/pytest-reportportal.svg
99
:target: https://pypi.org/project/pytest-reportportal
10+
:alt: Supported python versions
1011
.. image:: https://github.com/reportportal/agent-python-pytest/actions/workflows/tests.yml/badge.svg
1112
:target: https://github.com/reportportal/agent-python-pytest/actions/workflows/tests.yml
1213
:alt: Test status
1314
.. image:: https://codecov.io/gh/reportportal/agent-python-pytest/branch/master/graph/badge.svg
1415
:target: https://codecov.io/gh/reportportal/agent-python-pytest
16+
:alt: Test coverage
17+
.. image:: https://slack.epmrpp.reportportal.io/badge.svg
18+
:target: https://slack.epmrpp.reportportal.io/
19+
:alt: Join Slack chat!
1520

16-
Pytest plugin for reporting test results of the Pytest to the Reportal Portal.
21+
22+
Pytest plugin for reporting test results of the Pytest to the Report Portal.
1723

1824
* Usage
1925
* Installation
@@ -70,7 +76,7 @@ any one using pytest command line option:
7076
The :code:`pytest.ini` file should have next mandatory fields:
7177

7278
- :code:`rp_uuid` - value could be found in the User Profile section
73-
- :code:`rp_project` - name of project in Report Potal
79+
- :code:`rp_project` - name of project in Report Portal
7480
- :code:`rp_endpoint` - address of Report Portal Server
7581

7682
Example of :code:`pytest.ini`:
@@ -114,6 +120,8 @@ The following parameters are optional:
114120
- :code:`rp_verify_ssl = True` - Verify SSL when connecting to the server
115121
- :code:`rp_mode = DEFAULT` - DEBUG or DEFAULT launch mode. DEBUG launches are displayed in a separate tab and not visible to anyone except owner
116122
- :code:`rp_thread_logging` - EXPERIMENTAL - Enables support for reporting logs from threads by patching the builtin Thread class. Use with caution.
123+
- :code:`rp_launch_timeout = 86400` - Maximum time to wait for child processes finish, default value: 86400 seconds (1 day)
124+
117125

118126

119127
If you like to override the above parameters from command line, or from CI environment based on your build, then pass

examples/attributes/test_one_attribute.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
@pytest.mark.scope("smoke")
1818
def test_custom_attributes_report():
1919
"""
20-
This is a test with one custom markers which shall appear on
20+
This is a test with one custom marker which shall appear on
2121
ReportPortal on test's item
2222
"""
2323
assert True
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Copyright (c) 2022 https://reportportal.io .
2+
# Licensed under the Apache License, Version 2.0 (the "License");
3+
# you may not use this file except in compliance with the License.
4+
# You may obtain a copy of the License at
5+
#
6+
# https://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# Unless required by applicable law or agreed to in writing, software
9+
# distributed under the License is distributed on an "AS IS" BASIS,
10+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
# See the License for the specific language governing permissions and
12+
# limitations under the License
13+
14+
import pytest
15+
16+
17+
@pytest.mark.scope("smoke")
18+
def test_custom_attributes_report(request):
19+
"""
20+
This is a test with one custom marker as a decorator and one custom marker
21+
added at runtime which shall both appear on ReportPortal on test's item
22+
"""
23+
request.node.add_marker(
24+
pytest.mark.runtime()
25+
)
26+
assert True

pytest_reportportal/config.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ def __init__(self, pytest_config):
8282
self.rp_verify_ssl = bool(strtobool(rp_verify_ssl))
8383
except (ValueError, AttributeError):
8484
self.rp_verify_ssl = rp_verify_ssl
85+
self.rp_launch_timeout = int(
86+
self.find_option(pytest_config, 'rp_launch_timeout'))
8587

8688
# noinspection PyMethodMayBeStatic
8789
def find_option(self, pytest_config, option_name, default=None):

pytest_reportportal/config.pyi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class AgentConfig:
3131
rp_skip_connection_test: bool = ...
3232
rp_uuid: Text = ...
3333
rp_verify_ssl: Union[bool, Text] = ...
34+
rp_launch_timeout: int = ...
3435

3536
def __init__(self, pytest_config: Config) -> None: ...
3637

pytest_reportportal/plugin.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,3 +447,9 @@ def add_shared_option(name, help, default=None, action='store'):
447447
default=False,
448448
type='bool',
449449
help='Skip Report Portal connection test')
450+
parser.addini(
451+
'rp_launch_timeout',
452+
default=86400,
453+
help='Maximum time to wait for child processes finish, default value: '
454+
'86400 seconds (1 day)'
455+
)

pytest_reportportal/service.py

Lines changed: 54 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ def _get_issue(self, mark):
515515
"""Add issues description and issue_type to the test item.
516516
517517
:param mark: pytest mark
518+
:return: Issue object
518519
"""
519520
default_url = self._config.rp_issue_system_url
520521

@@ -562,29 +563,40 @@ def _get_parameters(self, item):
562563
"""
563564
return item.callspec.params if hasattr(item, 'callspec') else None
564565

565-
def _process_attributes(self, leaf):
566+
def _process_test_case_id(self, leaf):
566567
"""
567-
Process all types of attributes of item.
568+
Process Test Case ID if set.
568569
569570
:param leaf: item context
571+
:return: Test Case ID string
570572
"""
571-
item = leaf['item']
573+
for marker in leaf['item'].iter_markers():
574+
if marker.name == 'tc_id':
575+
return self._get_test_case_id(marker, leaf)
572576

573-
parameters = self._get_parameters(item)
574-
leaf['parameters'] = parameters
577+
return self._get_test_case_id(None, leaf)
575578

576-
code_ref = self._get_code_ref(item)
577-
leaf['code_ref'] = code_ref
579+
def _process_issue(self, item):
580+
"""
581+
Process Issue if set.
578582
583+
:param item: Pytest.Item
584+
:return: Issue
585+
"""
586+
for marker in item.iter_markers():
587+
if marker.name == 'issue':
588+
return self._get_issue(marker)
589+
590+
def _process_attributes(self, item):
591+
"""
592+
Process attributes of item.
593+
594+
:param item: Pytest.Item
595+
:return: a set of attributes
596+
"""
579597
attributes = set()
580-
for marker in leaf['item'].iter_markers():
581-
if marker.name == 'tc_id':
582-
test_case_id = self._get_test_case_id(marker, leaf)
583-
leaf['test_case_id'] = test_case_id
584-
continue
598+
for marker in item.iter_markers():
585599
if marker.name == 'issue':
586-
issue = self._get_issue(marker)
587-
leaf['issue'] = issue
588600
if self._config.rp_issue_id_marks:
589601
for issue_id in self._get_issue_ids(marker):
590602
attributes.add((marker.name, issue_id))
@@ -597,11 +609,29 @@ def _process_attributes(self, leaf):
597609
else:
598610
attributes.add((None, marker.name))
599611

600-
leaf['attributes'] = [self._to_attribute(attribute)
601-
for attribute in attributes]
612+
return [self._to_attribute(attribute)
613+
for attribute in attributes]
614+
615+
def _process_metadata_item_start(self, leaf):
616+
"""
617+
Process all types of item metadata for its start event.
602618
603-
if 'test_case_id' not in leaf:
604-
leaf['test_case_id'] = self._get_test_case_id(None, leaf)
619+
:param leaf: item context
620+
"""
621+
item = leaf['item']
622+
leaf['parameters'] = self._get_parameters(item)
623+
leaf['code_ref'] = self._get_code_ref(item)
624+
leaf['test_case_id'] = self._process_test_case_id(leaf)
625+
leaf['issue'] = self._process_issue(item)
626+
leaf['attributes'] = self._process_attributes(item)
627+
628+
def _process_metadata_item_finish(self, leaf):
629+
"""
630+
Process all types of item metadata for its finish event.
631+
632+
:param leaf: item context
633+
"""
634+
leaf['attributes'] = self._process_attributes(leaf['item'])
605635

606636
def _build_start_step_rq(self, leaf):
607637
payload = {
@@ -647,7 +677,7 @@ def start_pytest_item(self, test_item=None):
647677
# Details at:
648678
# https://github.com/reportportal/agent-Python-RobotFramework/issues/56
649679
current_leaf = self._tree_path[test_item][-1]
650-
self._process_attributes(current_leaf)
680+
self._process_metadata_item_start(current_leaf)
651681
item_id = self._start_step(self._build_start_step_rq(current_leaf))
652682
current_leaf['item_id'] = item_id
653683
current_leaf['exec'] = ExecStatus.IN_PROGRESS
@@ -683,6 +713,7 @@ def _build_finish_step_rq(self, leaf):
683713
if status == 'PASSED':
684714
issue = None
685715
payload = {
716+
'attributes': leaf.get('attributes', None),
686717
'end_time': timestamp(),
687718
'status': status,
688719
'issue': issue,
@@ -741,6 +772,7 @@ def finish_pytest_item(self, test_item):
741772

742773
path = self._tree_path[test_item]
743774
leaf = path[-1]
775+
self._process_metadata_item_finish(leaf)
744776
self._finish_step(self._build_finish_step_rq(leaf))
745777
leaf['exec'] = ExecStatus.FINISHED
746778
self._finish_parents(leaf)
@@ -759,7 +791,9 @@ def finish_suites(self):
759791
at once.
760792
"""
761793
# Ensure there is no running items
762-
while len(self._get_items(ExecStatus.IN_PROGRESS)) > 0:
794+
finish_time = time()
795+
while len(self._get_items(ExecStatus.IN_PROGRESS)) > 0 \
796+
and time() - finish_time <= self._config.rp_launch_timeout:
763797
sleep(0.1)
764798
skipped_items = self._get_items(ExecStatus.CREATED)
765799
for item in skipped_items:

setup.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from setuptools import setup
66

77

8-
__version__ = '5.1.3'
8+
__version__ = '5.1.4'
99

1010

1111
def read_file(fname):
@@ -23,13 +23,13 @@ def read_file(fname):
2323
version=__version__,
2424
description='Agent for Reporting results of tests to the Report Portal',
2525
long_description=read_file('README.rst'),
26-
long_description_content_type='text/markdown',
27-
author_email='SupportEPMC-TSTReportPortal@epam.com',
26+
long_description_content_type='text/x-rst',
27+
author_email='support@reportportal.io',
2828
url='https://github.com/reportportal/agent-python-pytest',
2929
packages=['pytest_reportportal'],
3030
install_requires=read_file('requirements.txt').splitlines(),
3131
license='Apache 2.0',
32-
keywords=['testing', 'reporting', 'reportportal', 'pytest'],
32+
keywords=['testing', 'reporting', 'reportportal', 'pytest', 'agent'],
3333
classifiers=[
3434
'Framework :: Pytest',
3535
'Programming Language :: Python :: 2.7',

0 commit comments

Comments
 (0)