Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 26 additions & 4 deletions docs/functions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ from Sphinx-Needs documentation to know how to use them.


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

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

``tr_link`` needs the following arguments:

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

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

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

**Example**::

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

.. needflow::
:tags: link_example


tr_link_match
-------------

Similar to ``tr_link``, but allows using a regex to find needs to link to.
When using ``tr_link_match``, the value of the ``source_option`` is compiled as a regular expression, and all other needs
whose ``target_option`` values match this pattern are linked.

**Usage**::

.. test-case:: Tests/TestSuite.TestCase/*
:id: TESTLINK_1
:results: "[[tr_link_match('title', 'case')]]",

The example above will link all test results which have a classname starting with ``Tests/TestSuite.TestCase``
(given that the ``results`` are defined as ``needs_extra_links`` in the ``conf.py``).

``tr_link_match`` needs the following arguments:

* **source_option**: Name of an option of the test-need (regex is taken from its value).
* **target_option**: Name of an option in other needs, which must match the regex in ``source_option``.
31 changes: 31 additions & 0 deletions sphinxcontrib/test_reports/functions/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import re


def tr_link(app, need, needs, test_option, target_option, *args, **kwargs):
if test_option not in need:
return ""
Expand All @@ -19,3 +22,31 @@ def tr_link(app, need, needs, test_option, target_option, *args, **kwargs):
links.append(need_target["id"])

return links


def tr_link_match(app, need, needs, test_option, target_option, *args, **kwargs):
if test_option not in need:
return ""
test_option_value = need[test_option]
if test_option_value is None or len(test_option_value) <= 0:
return []

links = []
test_pattern = re.compile(test_option_value)
for need_target in needs.values():
# Skip linking to itself
if need_target["id"] == need["id"]:
continue

if target_option not in need_target:
continue

target_option_value = need_target[target_option]
if (
target_option_value is not None
and len(target_option_value) > 0
and test_pattern.match(target_option_value)
):
links.append(need_target["id"])

return links
65 changes: 65 additions & 0 deletions tests/test_tr_link.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
from sphinxcontrib.test_reports.functions import tr_link, tr_link_match


def test_tr_link_option_not_in_need():
"""
Return an empty string when the specified test option is missing from the need.
"""
assert tr_link(app=None, need={}, needs={}, test_option="a", target_option="b") == ""

def test_tr_link_no_target_option_in_needs():
"""
Return an empty list when the target option is missing in all items of needs.
"""
assert tr_link(app=None, need={"a": "1"}, needs={"x": {"id": "123"}}, test_option="a", target_option="b") == []

def test_tr_link_no_match():
"""
Returns an empty list when no matching value for the test option is found in any of the target options within needs.
"""
assert tr_link(app=None, need={"a": "1"}, needs={"x": {"b": "2", "id": "123"}}, test_option="a", target_option="b") == []

def test_tr_link_match():
"""
Returns a list of ids when there is a matching value in both need and needs.
"""
assert tr_link(app=None, need={"a": "1"}, needs={"x": {"b": "1", "id": "123"}}, test_option="a", target_option="b") == ["123"]

def test_tr_link_regex_match():
"""
Returns a list of ids when the test option value containing an asterisk (*)
correctly matches target options using regular expression patterns.
"""
needs = {
"x": {"b": "abc123", "id": "111"},
"q": {"b": "abc/123", "id": "112"},
"y": {"b": "def456", "id": "222"},
"z": {"b": "ghi789", "id": "333"},
}
need = {"id": "1", "a": "abc.*"}
assert tr_link_match(
app=None, need=need, needs=needs, test_option="a", target_option="b"
) == ["111", "112"]


def test_tr_link_regex_no_match():
"""
Returns an empty list when the test option value containing an asterisk (*)
does not match any target options using regular expression patterns.
"""
needs = {"x": {"b": "abc123", "id": "111"}, "y": {"b": "def456", "id": "222"}}
need = {"id": "1", "a": "xyz.*"}
assert (
tr_link_match(app=None, need=need, needs=needs, test_option="a", target_option="b")
== []
)

def test_tr_link_regex_skip_linking_to_itself():
"""
Returns an empty list when the need and needs have the same 'id'.
"""
needs = {"x": {"b": "abc123", "id": "111"}, "y": {"b": "abc123", "id": "222"}}
need = {"id": "111", "a": "abc123"}
assert tr_link_match(
app=None, need=need, needs=needs, test_option="a", target_option="b"
) == ["222"]