Skip to content

Commit c55bd61

Browse files
committed
Add tr_link_match to support pattern matching
1 parent b806add commit c55bd61

File tree

3 files changed

+122
-4
lines changed

3 files changed

+122
-4
lines changed

docs/functions.rst

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ from Sphinx-Needs documentation to know how to use them.
1010

1111

1212
tr_link
13-
---------
13+
-------
1414
Links a need (e.g testcase) automatically to other needs, which have a specific value in a given option.
1515

1616
**Usage**::
@@ -25,16 +25,16 @@ Links a need (e.g testcase) automatically to other needs, which have a specific
2525

2626
``tr_link`` needs the following arguments:
2727

28-
* **source_option**: Name of an option of the test-need, which is used for comparision. E.g. ``classname``.
29-
* **target_option**: Name of an option of all other needs, which is used for comparision. E.g. ``title``.
28+
* **source_option**: Name of an option of the test-need, which is used for comparison. E.g. ``classname``.
29+
* **target_option**: Name of an option of all other needs, which is used for comparison. E.g. ``title``.
3030

3131
The function reads the ``target_option`` from the need, where it is used.
3232
Then it goes through **all** other needs and checks if the value of their ``source_option`` is equal to
3333
the ``target_option``.
3434
If this is the case, their IDs get stored and finally returned.
3535

3636
``source_option`` can also reference an option with comma separated values.
37-
In this case a comparions is performed for each value, which may lead to multiple links.
37+
In this case a comparison is performed for each value, which may lead to multiple links.
3838

3939
**Example**::
4040

@@ -81,3 +81,25 @@ In this case a comparions is performed for each value, which may lead to multipl
8181

8282
.. needflow::
8383
:tags: link_example
84+
85+
86+
tr_link_match
87+
-------------
88+
89+
Similar to ``tr_link``, but allows using a regex to find needs to link to.
90+
When using ``tr_link_match``, the value of the ``source_option`` is compiled as a regular expression, and all other needs
91+
whose ``target_option`` values match this pattern are linked.
92+
93+
**Usage**::
94+
95+
.. test-case:: Tests/TestSuite.TestCase/*
96+
:id: TESTLINK_1
97+
:results: "[[tr_link_match('title', 'case')]]",
98+
99+
The example above will link all test results which have a classname starting with ``Tests/TestSuite.TestCase``
100+
(given that the ``results`` are defined as ``needs_extra_links`` in the ``conf.py``).
101+
102+
``tr_link_match`` needs the following arguments:
103+
104+
* **source_option**: Name of an option of the test-need (regex is taken from its value).
105+
* **target_option**: Name of an option in other needs, which must match the regex in ``source_option``.

sphinxcontrib/test_reports/functions/__init__.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import re
2+
3+
14
def tr_link(app, need, needs, test_option, target_option, *args, **kwargs):
25
if test_option not in need:
36
return ""
@@ -19,3 +22,31 @@ def tr_link(app, need, needs, test_option, target_option, *args, **kwargs):
1922
links.append(need_target["id"])
2023

2124
return links
25+
26+
27+
def tr_link_match(app, need, needs, test_option, target_option, *args, **kwargs):
28+
if test_option not in need:
29+
return ""
30+
test_option_value = need[test_option]
31+
if test_option_value is None or len(test_option_value) <= 0:
32+
return []
33+
34+
links = []
35+
test_pattern = re.compile(test_option_value)
36+
for need_target in needs.values():
37+
# Skip linking to itself
38+
if need_target["id"] == need["id"]:
39+
continue
40+
41+
if target_option not in need_target:
42+
continue
43+
44+
target_option_value = need_target[target_option]
45+
if (
46+
target_option_value is not None
47+
and len(target_option_value) > 0
48+
and test_pattern.match(target_option_value)
49+
):
50+
links.append(need_target["id"])
51+
52+
return links

tests/test_tr_link.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
from sphinxcontrib.test_reports.functions import tr_link, tr_link_match
2+
3+
4+
def test_tr_link_option_not_in_need():
5+
"""
6+
Return an empty string when the specified test option is missing from the need.
7+
"""
8+
assert tr_link(app=None, need={}, needs={}, test_option="a", target_option="b") == ""
9+
10+
def test_tr_link_no_target_option_in_needs():
11+
"""
12+
Return an empty list when the target option is missing in all items of needs.
13+
"""
14+
assert tr_link(app=None, need={"a": "1"}, needs={"x": {"id": "123"}}, test_option="a", target_option="b") == []
15+
16+
def test_tr_link_no_match():
17+
"""
18+
Returns an empty list when no matching value for the test option is found in any of the target options within needs.
19+
"""
20+
assert tr_link(app=None, need={"a": "1"}, needs={"x": {"b": "2", "id": "123"}}, test_option="a", target_option="b") == []
21+
22+
def test_tr_link_match():
23+
"""
24+
Returns a list of ids when there is a matching value in both need and needs.
25+
"""
26+
assert tr_link(app=None, need={"a": "1"}, needs={"x": {"b": "1", "id": "123"}}, test_option="a", target_option="b") == ["123"]
27+
28+
def test_tr_link_regex_match():
29+
"""
30+
Returns a list of ids when the test option value containing an asterisk (*)
31+
correctly matches target options using regular expression patterns.
32+
"""
33+
needs = {
34+
"x": {"b": "abc123", "id": "111"},
35+
"q": {"b": "abc/123", "id": "112"},
36+
"y": {"b": "def456", "id": "222"},
37+
"z": {"b": "ghi789", "id": "333"},
38+
}
39+
need = {"id": "1", "a": "abc.*"}
40+
assert tr_link_match(
41+
app=None, need=need, needs=needs, test_option="a", target_option="b"
42+
) == ["111", "112"]
43+
44+
45+
def test_tr_link_regex_no_match():
46+
"""
47+
Returns an empty list when the test option value containing an asterisk (*)
48+
does not match any target options using regular expression patterns.
49+
"""
50+
needs = {"x": {"b": "abc123", "id": "111"}, "y": {"b": "def456", "id": "222"}}
51+
need = {"id": "1", "a": "xyz.*"}
52+
assert (
53+
tr_link_match(app=None, need=need, needs=needs, test_option="a", target_option="b")
54+
== []
55+
)
56+
57+
def test_tr_link_regex_skip_linking_to_itself():
58+
"""
59+
Returns an empty list when the need and needs have the same 'id'.
60+
"""
61+
needs = {"x": {"b": "abc123", "id": "111"}, "y": {"b": "abc123", "id": "222"}}
62+
need = {"id": "111", "a": "abc123"}
63+
assert tr_link_match(
64+
app=None, need=need, needs=needs, test_option="a", target_option="b"
65+
) == ["222"]

0 commit comments

Comments
 (0)