Skip to content

Commit 88ae640

Browse files
authored
Merge pull request #398 from ramir-dn/ramir_test
Add an option to ignore param value in test case id
2 parents ffbeecb + fb7c883 commit 88ae640

File tree

5 files changed

+172
-1
lines changed

5 files changed

+172
-1
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
"""A simple example test with Test Case ID decorator using parameter values."""
2+
3+
# Copyright (c) 2023 https://reportportal.io .
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# https://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License
15+
16+
import pytest
17+
18+
TEST_CASE_ID = "ISSUE-USE-INDEX-FALSE"
19+
20+
21+
@pytest.mark.parametrize(("param1", "param2"), [("value1", "value2")])
22+
@pytest.mark.tc_id(TEST_CASE_ID, parameterized=True, use_index=False)
23+
def test_case_id_decorator(param1, param2):
24+
assert True
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
"""A simple example test with Test Case ID decorator using parameter indices with selected params."""
2+
3+
# Copyright (c) 2023 https://reportportal.io .
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# https://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License
15+
16+
import pytest
17+
18+
TEST_CASE_ID = "ISSUE-USE-INDEX-PARTIAL"
19+
20+
21+
@pytest.mark.parametrize(("param1", "param2"), [("value1", "value2")])
22+
@pytest.mark.tc_id(TEST_CASE_ID, parameterized=True, params=["param1"], use_index=True)
23+
def test_case_id_decorator(param1, param2):
24+
assert True
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
"""A simple example test with Test Case ID decorator using parameter indices."""
2+
3+
# Copyright (c) 2023 https://reportportal.io .
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# https://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License
15+
16+
import pytest
17+
18+
TEST_CASE_ID = "ISSUE-USE-INDEX-TRUE"
19+
20+
21+
@pytest.mark.parametrize(("param1", "param2"), [("value1", "value2")])
22+
@pytest.mark.tc_id(TEST_CASE_ID, parameterized=True, use_index=True)
23+
def test_case_id_decorator(param1, param2):
24+
assert True

pytest_reportportal/service.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -599,18 +599,26 @@ def _get_code_ref(self, item: Item) -> str:
599599

600600
def _get_test_case_id(self, mark, leaf: Dict[str, Any]) -> str:
601601
parameters: Optional[Dict[str, Any]] = leaf.get("parameters", None)
602+
parameters_indices: Optional[Dict[str, Any]] = leaf.get("parameters_indices") or {}
602603
parameterized = True
603604
selected_params: Optional[List[str]] = None
605+
use_index = False
604606
if mark is not None:
605607
parameterized = mark.kwargs.get("parameterized", False)
606608
selected_params: Optional[Union[str, List[str]]] = mark.kwargs.get("params", None)
609+
use_index = mark.kwargs.get("use_index", False)
607610
if selected_params is not None and not isinstance(selected_params, list):
608611
selected_params = [selected_params]
609612

610613
param_str = None
611614
if parameterized and parameters is not None and len(parameters) > 0:
612615
if selected_params is not None and len(selected_params) > 0:
613-
param_list = [str(parameters.get(param, None)) for param in selected_params]
616+
if use_index:
617+
param_list = [str((param, parameters_indices.get(param, None))) for param in selected_params]
618+
else:
619+
param_list = [str(parameters.get(param, None)) for param in selected_params]
620+
elif use_index:
621+
param_list = [str(param) for param in parameters_indices.items()]
614622
else:
615623
param_list = [str(param) for param in parameters.values()]
616624
param_str = "[{}]".format(",".join(sorted(param_list)))
@@ -729,6 +737,19 @@ def _get_parameters(self, item) -> Optional[Dict[str, Any]]:
729737
return None
730738
return {str(k): v.replace("\0", "\\0") if isinstance(v, str) else v for k, v in params.items()}
731739

740+
def _get_parameters_indices(self, item) -> Optional[Dict[str, Any]]:
741+
"""
742+
Get params indices of item.
743+
744+
:param item: Pytest.Item
745+
:return: dict of params indices
746+
"""
747+
indices = item.callspec.indices if hasattr(item, "callspec") else None
748+
if not indices:
749+
return None
750+
751+
return indices
752+
732753
def _process_test_case_id(self, leaf: Dict[str, Any]) -> str:
733754
"""
734755
Process Test Case ID if set.
@@ -793,6 +814,7 @@ def _process_metadata_item_start(self, leaf: Dict[str, Any]) -> None:
793814
leaf["name"] = self._process_item_name(leaf)
794815
leaf["description"] = self._get_item_description(item)
795816
leaf["parameters"] = self._get_parameters(item)
817+
leaf["parameters_indices"] = self._get_parameters_indices(item)
796818
leaf["code_ref"] = self._get_code_ref(item)
797819
leaf["test_case_id"] = self._process_test_case_id(leaf)
798820
leaf["issue"] = self._process_issue(item)
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# Copyright (c) 2023 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+
"""This module includes integration tests for Test Case ID report with use_index parameter."""
15+
16+
from unittest import mock
17+
18+
import pytest
19+
20+
from examples.test_case_id import (
21+
test_case_id_decorator_use_index_false,
22+
test_case_id_decorator_use_index_partial_params,
23+
test_case_id_decorator_use_index_true,
24+
)
25+
from tests import REPORT_PORTAL_SERVICE
26+
from tests.helpers import utils
27+
28+
29+
@mock.patch(REPORT_PORTAL_SERVICE)
30+
@pytest.mark.parametrize(
31+
["test", "expected_id"],
32+
[
33+
# Test use_index=True: should use parameter indices instead of values
34+
# Format should be: ('param1', 0),('param2', 0) instead of value1,value2
35+
(
36+
"examples/test_case_id/test_case_id_decorator_use_index_true.py",
37+
test_case_id_decorator_use_index_true.TEST_CASE_ID + "[('param1', 0),('param2', 0)]",
38+
),
39+
# Test use_index=False: should use parameter values (default behavior)
40+
(
41+
"examples/test_case_id/test_case_id_decorator_use_index_false.py",
42+
test_case_id_decorator_use_index_false.TEST_CASE_ID + "[value1,value2]",
43+
),
44+
# Test use_index=True with selected params: should use index for selected param only
45+
# Should be ('param1', 0) instead of value1
46+
(
47+
"examples/test_case_id/test_case_id_decorator_use_index_partial_params.py",
48+
test_case_id_decorator_use_index_partial_params.TEST_CASE_ID + "[('param1', 0)]",
49+
),
50+
],
51+
)
52+
def test_use_index_parameters(mock_client_init, test, expected_id):
53+
"""Verify the use_index parameter in Test Case ID functionality.
54+
55+
This test verifies that the new use_index parameter works correctly for parameterized tests.
56+
When use_index=True, the test case ID should include parameter indices instead of parameter values.
57+
This is useful for scenarios where parameter values might change between test runs but the indices
58+
remain constant, ensuring that retry groups are properly maintained.
59+
60+
The test covers:
61+
1. use_index=True with all parameters - should use (param_name, index) format
62+
2. use_index=False - should use parameter values (default behavior)
63+
3. use_index=True with selected parameters - should use indices only for selected params
64+
65+
:param mock_client_init: Pytest fixture for mocking the ReportPortal client
66+
:param test: a test file path to run
67+
:param expected_id: the expected Test Case ID format
68+
"""
69+
result = utils.run_pytest_tests(tests=[test])
70+
assert int(result) == 0, "Exit code should be 0 (no errors)"
71+
72+
mock_client = mock_client_init.return_value
73+
assert mock_client.start_test_item.call_count > 0, '"start_test_item" called incorrect number of times'
74+
75+
call_args = mock_client.start_test_item.call_args_list
76+
step_call_args = call_args[-1][1]
77+
assert step_call_args["test_case_id"] == expected_id

0 commit comments

Comments
 (0)