Skip to content

Commit c4338af

Browse files
kamaxeonIsrael Santana Aleman
andauthored
Add web-link field to Result for browsable test links (#4878)
## Summary Add a `web_link` field to the `Result` dataclass in `tmt/result.py` that serializes the browsable test source URL directly into `results.yaml` as `web-link`, so downstream consumers (gluetools, kcidb) get a ready-to-use link instead of having to reconstruct it from `fmf-id`. - The field name is consistent with the existing `Core.web_link()` method and `tmt test show` output - Populated via `Test.web_link()` in `from_test_invocation()` - Returns `None` for local tests / shell discover (no URL available) - Returns a browsable URL for tests from Git repos (GitLab, GitHub, Pagure, etc.) ### Example output in results.yaml ```yaml - name: /tests/nvidia/driver-install result: pass fmf-id: url: https://gitlab.cee.redhat.com/gpu-accelerators/tests ref: main name: /tests/nvidia/driver-install path: . web-link: https://gitlab.cee.redhat.com/gpu-accelerators/tests/-/blob/main/tests/nvidia/driver-install/main.fmf duration: 00:05:23 serial-number: 1 ``` Ref: TFT-2683 --------- Signed-off-by: Israel Santana Aleman <isantana@redhat.com> Co-authored-by: Israel Santana Aleman <isantana@redhat.com>
1 parent d5de8e1 commit c4338af

5 files changed

Lines changed: 57 additions & 0 deletions

File tree

docs/releases/pending/4878.fmf

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
description: |
2+
Test results now include a ``web-link`` field containing a browsable
3+
URL that points to the test's fmf metadata source. This is the same
4+
URL shown by ``tmt test show`` under the ``web`` key. Downstream
5+
consumers such as reporting tools can use this link directly instead
6+
of reconstructing it from the ``fmf-id`` mapping.

spec/results.fmf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ description: |
7373
# Integer, serial number of the test in the sequence of all tests of a plan.
7474
serial-number: 1
7575

76+
# String, a browsable URL pointing to the test's fmf metadata source.
77+
# Matches the value produced by ``tmt test show`` under the ``web`` key.
78+
web-link: https://github.com/teemtee/tmt/-/blob/main/tests/core/smoke/main.fmf
79+
7680
# Mapping, describes the guest on which the test was executed.
7781
guest:
7882
name: client-1

tests/unit/test_results.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,3 +1045,42 @@ def test_save_failures(tmppath: Path, root_logger) -> None:
10451045
assert tmt.utils.from_yaml(read_yaml) == ['foo', _GOOD_STRING, 'bar']
10461046
assert tmt.utils.from_yaml(read_yaml, yaml_type='safe') == ['foo', _GOOD_STRING, 'bar']
10471047
assert tmt.utils.yaml_to_list(read_yaml) == ['foo', _GOOD_STRING, 'bar']
1048+
1049+
1050+
def test_result_web_link_default() -> None:
1051+
"""Verify that web_link defaults to None for backward compatibility."""
1052+
result = Result(name="/test", result=ResultOutcome.PASS)
1053+
assert result.web_link is None
1054+
1055+
1056+
def test_result_web_link_roundtrip() -> None:
1057+
"""Verify that web_link survives serialization and deserialization."""
1058+
url = "https://gitlab.example.com/repo/-/blob/main/tests/test.fmf"
1059+
result = Result(name="/test", result=ResultOutcome.PASS, web_link=url)
1060+
1061+
serialized = result.to_serialized()
1062+
assert serialized["web-link"] == url
1063+
1064+
restored = Result.from_serialized(serialized)
1065+
assert restored.web_link == url
1066+
1067+
1068+
def test_result_web_link_none_roundtrip() -> None:
1069+
"""Verify that web_link=None serializes and deserializes correctly."""
1070+
result = Result(name="/test", result=ResultOutcome.PASS, web_link=None)
1071+
1072+
serialized = result.to_serialized()
1073+
assert serialized["web-link"] is None
1074+
1075+
restored = Result.from_serialized(serialized)
1076+
assert restored.web_link is None
1077+
1078+
1079+
def test_result_web_link_missing_in_serialized() -> None:
1080+
"""Verify backward compat: old results without web-link deserialize with None."""
1081+
result = Result(name="/test", result=ResultOutcome.PASS)
1082+
serialized = result.to_serialized()
1083+
del serialized["web-link"]
1084+
1085+
restored = Result.from_serialized(serialized)
1086+
assert restored.web_link is None

tmt/result.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@ class Result(BaseResult):
325325
"""
326326

327327
serial_number: int = 0
328+
web_link: Optional[str] = None
328329
fmf_id: Optional['tmt.base.core.FmfId'] = field(
329330
default=cast(Optional['tmt.base.core.FmfId'], None),
330331
serialize=lambda fmf_id: fmf_id.to_minimal_spec() if fmf_id is not None else {},
@@ -395,6 +396,7 @@ def from_test_invocation(
395396
_result = Result(
396397
name=invocation.test.name,
397398
serial_number=invocation.test.serial_number,
399+
web_link=invocation.test.web_link(),
398400
fmf_id=invocation.test.fmf_id,
399401
context=invocation.phase.step.plan.fmf_context,
400402
result=result,

tmt/schemas/results.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,12 @@ items:
123123
serial-number:
124124
type: integer
125125

126+
web-link:
127+
oneOf:
128+
- type: "null"
129+
- type: string
130+
format: uri
131+
126132
result:
127133
$ref: "/schemas/common#/definitions/result_outcome"
128134

0 commit comments

Comments
 (0)