Skip to content

Commit d961527

Browse files
authored
feat: xray cli tool supports test-plan-key (#566)
1 parent 5675d8e commit d961527

6 files changed

Lines changed: 99 additions & 7 deletions

File tree

docs/tools/xray.rst

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@ Export results to Xray
66

77
The ``xray`` CLI utility takes your Pykiso Junit test results report and export them on `Xray <https://xray.cloud.getxray.app/>`__.
88

9-
Upload your results
10-
-------------------
9+
Upload your results on XRAY using JUNIT xml files
10+
-------------------------------------------------
11+
12+
Upload the test results to a test execution ticket
13+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1114

1215
Upload the test results to an existing Xray test execution ticket
1316
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -35,13 +38,14 @@ Options:
3538
--test-execution-description TEXT Set or update the description (Jira ticket title) of the Xray test execution ticket
3639
[optional][default value: None] Required when creating a new test execution ticket;
3740
optional when updating an existing one.
41+
--test-plan-key TEXT Xray test plan ticket key's where to add a new test execution for the test results from a JUNIT xml
42+
(e.g PROJ-456) [optional][default value: None]
3843
--merge-xml-files Merge all the xml files to be send in one xml file
3944
--not-append-test-results, -na Do not append new test keys from the .xml(s) to the updated test execution,
4045
only overwrite already existing ones
4146
--help Show this message and exit.
4247

4348

44-
4549
Upload the test results on a new Xray test execution ticket
4650
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4751

@@ -87,6 +91,22 @@ This is useful when you want to:
8791
- Maintain a fixed set of tests in your test execution ticket
8892
- Prevent accidental addition of new tests to an existing test execution
8993

94+
Upload the test results to a test plan ticket
95+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
96+
97+
Upload the test results on an existing test plan ticket
98+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
99+
100+
A test plan contains multiple test executions.
101+
A test plan has a unique JIRA key. A test execution also has a unique JIRA key.
102+
The user must provide either a test plan key or a test execution key, not both.
103+
If a test plan key is given, results are uploaded only to new test execution(s) linked to the test plan.
104+
When creating a new test execution ticket, you must also specify the test execution **summary** and **description**.
105+
106+
.. code:: bash
107+
108+
xray --user USER_ID --password MY_API_KEY --url "https://xray.cloud.getxray.app/" upload --path-results path/reports/folder --test-plan-key "PROJ-456" --test-execution-summary "My test execution summary" --test-execution-description "My test execution description"
109+
90110
91111
Add the Xray decorator to the test functions
92112
--------------------------------------------

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "pykiso"
3-
version = "1.6.3"
3+
version = "1.6.4"
44
description = "Embedded integration testing framework."
55
authors = ["Sebastian Fischer <sebastian.fischer@de.bosch.com>"]
66
license = "Eclipse Public License - v 2.0"

src/pykiso/tool/xray/cli.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,13 @@ def cli_xray(ctx: dict, user: str, password: str, url: str) -> None:
6969
default=None,
7070
type=click.STRING,
7171
)
72+
@click.option(
73+
"--test-plan-key",
74+
help="Key of the test plan ticket where to add new test execution for the test results from a JUnit xml",
75+
required=False,
76+
default=None,
77+
type=click.STRING,
78+
)
7279
@click.option(
7380
"-m",
7481
"--merge-xml-files",
@@ -91,6 +98,7 @@ def cli_upload(
9198
test_execution_key: str,
9299
test_execution_description: str,
93100
test_execution_summary: str,
101+
test_plan_key: str,
94102
merge_xml_files: bool,
95103
not_append_test_results: bool,
96104
) -> None:
@@ -101,10 +109,15 @@ def cli_upload(
101109
:param test_execution_key: test execution key where to upload the test results
102110
:param test_execution_description: update the test execution ticket description - otherwise, keep current description
103111
:param test_execution_summary: update the test execution ticket summary - otherwise, keep current summary
112+
:param test_plan_key: test plan key where to create a new test execution ticket for the test results
104113
:param merge_xml_files: if True, merge the xml files, else do nothing
105114
:param not_append_test_results: if True, only overwrite the existing ones (update only), else append the new results from the .xml file(s) to the test execution
106115
107116
"""
117+
if test_plan_key and test_execution_key:
118+
raise ValueError(
119+
"You cannot specify both a test plan key and a test execution key. " "Please use either one or the other."
120+
)
108121
# If a new test execution ticket is being created (no key), the user should pass a description and a summary.
109122
if not test_execution_key and (not test_execution_description or not test_execution_summary):
110123
raise ValueError(
@@ -134,6 +147,7 @@ def cli_upload(
134147
test_execution_key=test_execution_key,
135148
test_execution_summary=test_execution_summary,
136149
test_execution_description=test_execution_description,
150+
test_plan_key=test_plan_key,
137151
)
138152

139153
responses = []

src/pykiso/tool/xray/xray.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ def __call__(self, r: requests.PreparedRequest) -> requests.PreparedRequest:
4141
auth_data = {"client_id": self.client_id, "client_secret": self.client_secret}
4242

4343
try:
44-
response = requests.post(self.endpoint_url, data=json.dumps(auth_data), headers=headers, verify=self.verify)
44+
response = requests.post(
45+
self.endpoint_url, data=json.dumps(auth_data), headers=headers, verify=self.verify
46+
)
4547
except requests.exceptions.ConnectionError as exc:
4648
err_message = f"ConnectionError: cannot authenticate with {self.endpoint_url}"
4749
raise XrayException(err_message) from exc
@@ -59,7 +61,9 @@ def __init__(self, base_url: str, client_id: str, client_secret: str, verify: bo
5961
self.verify = verify
6062

6163
# Create authentication
62-
self.auth = ClientSecretAuth(base_url=base_url, client_id=client_id, client_secret=client_secret, verify=verify)
64+
self.auth = ClientSecretAuth(
65+
base_url=base_url, client_id=client_id, client_secret=client_secret, verify=verify
66+
)
6367

6468
# Define the endpoints
6569
self.rest_endpoint = f"{self.base_url}/api/v2/import/execution"
@@ -317,6 +321,7 @@ def extract_test_results(
317321
test_execution_key: str | None = None,
318322
test_execution_summary: str | None = None,
319323
test_execution_description: str | None = None,
324+
test_plan_key: str | None = None,
320325
) -> list[str]:
321326
"""
322327
Extract the test results linked to an xray test key. Filter the JUnit xml files generated by the execution of tests,
@@ -330,6 +335,7 @@ def extract_test_results(
330335
if none is specified a new test execution ticket will be created
331336
:param test_execution_summary: update the test execution ticket summary - otherwise, keep current summary
332337
:param test_execution_description: update the test execution ticket description - otherwise, keep current description
338+
:param test_plan_key: test plan key where to create a new test execution ticket for the test results
333339
334340
:return: the filtered test results"""
335341
xml_results = []
@@ -359,7 +365,7 @@ def extract_test_results(
359365

360366
test_suites = data_dict["testsuites"]["testsuite"]
361367
xray_dict = create_result_dictionary(
362-
test_suites, jira_keys, test_execution_summary, test_execution_description
368+
test_suites, jira_keys, test_execution_summary, test_execution_description, test_plan_key
363369
)
364370
xml_results = reformat_xml_results(xray_dict, test_execution_key)
365371
return xml_results

src/pykiso/tool/xray/xray_report.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ def create_result_dictionary(
101101
jira_keys: list[str],
102102
test_execution_summary: str | None = None,
103103
test_execution_description: str | None = None,
104+
test_plan_key: str | None = None,
104105
) -> dict:
105106
"""
106107
Processes test suite data and generates a dictionary containing information
@@ -111,6 +112,7 @@ def create_result_dictionary(
111112
:param jira_keys: the list of jira keys inside the test execution ticket containing the test results
112113
:param test_execution_summary: update the test execution ticket description - otherwise, keep current summary
113114
:param test_execution_description: update the test execution ticket description - otherwise, keep current description
115+
:param test_plan_key: test plan key where to create a new test execution ticket for the test results
114116
115117
:return: A dictionary with two keys:
116118
- "info": Contains metadata about the test execution, including summary,
@@ -144,6 +146,10 @@ def create_result_dictionary(
144146
"startDate": start_time,
145147
"finishDate": end_time,
146148
}
149+
if test_plan_key is not None:
150+
# if a test plan key is specified, link the test results to the test plan
151+
test_execution_ticket["testPlanKey"] = test_plan_key
152+
147153
# if there is a test execution key, update the summary and the description of the test execution ticket
148154
if test_execution_summary is not None:
149155
test_execution_ticket["summary"] = test_execution_summary

tests/test_xray_report.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,52 @@ def test_create_result_dictionary_with_single_testcase_with_test_execution_summa
359359
)
360360

361361

362+
def test_create_result_dictionary_with_single_testcase_with_test_plan_and_test_execution_summary_and_test_execution_description():
363+
test_suites = [
364+
{
365+
"errors": "0",
366+
"failures": "0",
367+
"time": "10.5",
368+
"timestamp": "2023-01-01T12:00:00",
369+
"testcase": {
370+
"name": "test_case_1",
371+
"time": "10.5",
372+
"timestamp": "2023-01-01T12:00:00",
373+
"properties": {"property": [{"name": "test_key", "value": "TEST-1"}]},
374+
},
375+
}
376+
]
377+
378+
expected_result = {
379+
"info": {
380+
"description": "Ticket description",
381+
"summary": "Ticket summary",
382+
"startDate": "2023-01-01T12:00:00+0000",
383+
"finishDate": "2023-01-01T12:00:10+0000",
384+
"project": "TEST",
385+
"testPlanKey": "PROJ-123",
386+
},
387+
"tests": [
388+
{
389+
"testKey": "TEST-1",
390+
"comment": "test_case_1: Successful execution",
391+
"status": "PASSED",
392+
}
393+
],
394+
}
395+
396+
assert (
397+
create_result_dictionary(
398+
test_suites,
399+
jira_keys=["TEST-1"],
400+
test_execution_summary="Ticket summary",
401+
test_execution_description="Ticket description",
402+
test_plan_key="PROJ-123",
403+
)
404+
== expected_result
405+
)
406+
407+
362408
def test_create_result_dictionary_with_multiple_testcases():
363409
test_suites = [
364410
{

0 commit comments

Comments
 (0)