Skip to content

Commit cbdddd2

Browse files
committed
add attribute plugin
1 parent 84b54c4 commit cbdddd2

6 files changed

Lines changed: 115 additions & 1 deletion

File tree

MODULE.bazel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ bazel_dep(name = "bazel_skylib", version = "1.9.0")
113113
# Score custom modules loading
114114
#
115115
###############################################################################
116-
bazel_dep(name = "score_tooling", version = "1.0.4")
116+
bazel_dep(name = "score_tooling", version = "1.1.2")
117117
bazel_dep(name = "score_bazel_platforms", version = "0.0.3")
118118
bazel_dep(name = "platforms", version = "1.0.0")
119119

pyproject.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,9 @@ junit_suite_name = "ITF"
1515
junit_duration_report = "call"
1616
junit_family = "xunit1"
1717

18+
markers = [
19+
"test_properties(dict)", # add custom properties to test XML output
20+
]
21+
1822
[tool.ruff]
1923
line-length = 120

pytest.ini

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,6 @@ log_file_date_format = %Y-%m-%d %H:%M:%S
1414
junit_suite_name = ITF
1515
junit_duration_report = call
1616
junit_family = xunit1
17+
18+
markers =
19+
test_properties(dict): Add custom properties to test XML output

score/itf/plugins/BUILD

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,12 @@ py_itf_plugin(
7070
py_library = "//score/itf/plugins/dlt",
7171
visibility = ["//visibility:public"],
7272
)
73+
74+
py_itf_plugin(
75+
name = "attribute_plugin",
76+
enabled_plugins = [
77+
"attribute_plugin",
78+
],
79+
py_library = "@score_tooling//python_basics/score_pytest:attribute_plugin",
80+
visibility = ["//visibility:public"],
81+
)

test/BUILD

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,3 +205,14 @@ py_itf_test(
205205
"@rules_python//python/runfiles",
206206
],
207207
)
208+
209+
210+
py_itf_test(
211+
name = "test_attribute_plugin",
212+
srcs = [
213+
"test_attribute_plugin.py",
214+
],
215+
plugins = [
216+
"//score/itf/plugins:attribute_plugin",
217+
],
218+
)

test/test_attribute_plugin.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# *******************************************************************************
2+
# Copyright (c) 2026 Contributors to the Eclipse Foundation
3+
#
4+
# See the NOTICE file(s) distributed with this work for additional
5+
# information regarding copyright ownership.
6+
#
7+
# This program and the accompanying materials are made available under the
8+
# terms of the Apache License Version 2.0 which is available at
9+
# https://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# SPDX-License-Identifier: Apache-2.0
12+
# *******************************************************************************
13+
14+
"""
15+
Example test demonstrating the use of @add_test_properties decorator.
16+
17+
This test shows how to add custom properties to test cases that will appear
18+
in the JUnit XML report, including requirement verification information and
19+
test classification metadata.
20+
"""
21+
22+
import os
23+
import xml.etree.ElementTree as ET
24+
from pathlib import Path
25+
26+
from attribute_plugin import add_test_properties
27+
28+
29+
@add_test_properties(
30+
fully_verifies=["REQ-001", "REQ-002"],
31+
test_type="requirements-based",
32+
derivation_technique="requirements-analysis",
33+
)
34+
def test_example_with_properties(request):
35+
"""
36+
Example test case with custom properties.
37+
38+
This test demonstrates the @add_test_properties decorator which adds
39+
custom metadata to the XML test report.
40+
"""
41+
assert True
42+
43+
44+
def pytest_sessionfinish(session, exitstatus):
45+
"""
46+
Hook that runs after all tests complete and XML is written.
47+
48+
This validates that the XML report contains the expected properties
49+
from the @add_test_properties decorator.
50+
"""
51+
xml_output_file = os.environ.get("XML_OUTPUT_FILE")
52+
xml_path = Path(xml_output_file)
53+
54+
assert xml_path.exists(), f"XML report not found at {xml_path}"
55+
56+
# Parse the XML file
57+
tree = ET.parse(xml_path)
58+
root = tree.getroot()
59+
60+
# Find the test case
61+
testcase = root.find(".//testcase[@name='test_example_with_properties']")
62+
assert testcase is not None, "test_example_with_properties not found in XML"
63+
64+
# Find and validate properties
65+
properties = testcase.find("properties")
66+
assert properties is not None, "No properties element found in testcase"
67+
68+
# Extract properties into a dictionary
69+
props_dict = {}
70+
for prop in properties.findall("property"):
71+
props_dict[prop.get("name")] = prop.get("value")
72+
73+
# Validate expected properties with clear assertions
74+
assert "fully_verifies" in props_dict, "fully_verifies property not found"
75+
assert props_dict["fully_verifies"] == "['REQ-001', 'REQ-002']", (
76+
f"fully_verifies: expected ['REQ-001', 'REQ-002'], got {props_dict['fully_verifies']}"
77+
)
78+
79+
assert "test_type" in props_dict, "test_type property not found"
80+
assert props_dict["test_type"] == "requirements-based", (
81+
f"test_type: expected 'requirements-based', got {props_dict['test_type']}"
82+
)
83+
84+
assert "derivation_technique" in props_dict, "derivation_technique property not found"
85+
assert props_dict["derivation_technique"] == "requirements-analysis", (
86+
f"derivation_technique: expected 'requirements-analysis', got {props_dict['derivation_technique']}"
87+
)

0 commit comments

Comments
 (0)