Skip to content

Commit 113f1a1

Browse files
committed
SwiftTesting: Enhance Event Stream JSON ABI
1 parent 85fb937 commit 113f1a1

File tree

1 file changed

+207
-0
lines changed

1 file changed

+207
-0
lines changed
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
# Include metadata for tags, bugs, and time limit traits in event stream
2+
3+
* Proposal: [ST-NNNN](NNNN-augment-event-json-abi.md)
4+
* Authors: [Sam Khouri](https://github.com/bkhouri),
5+
* Review Manager: TBD
6+
* Status: **Awaiting review**
7+
* Implementation: [swiftlang/swift-testing#1429](https://github.com/swiftlang/swift-testing/pull/1429)
8+
* Review: [pitch](https://forums.swift.org/t/adding-additional-information-to-the-abi-json/83426)
9+
10+
## Introduction
11+
12+
This proposal enhances Swift Testing's event JSON ABI by exposing test
13+
metadata that is currently unavailable to external tools. By including test
14+
tags, bug associations, and time limits in the JSON output, this allows third-party
15+
tools to provide richer insights and more sophisticated test management capabilities.
16+
17+
## Motivation
18+
19+
Swift Testing's event JSON stream provides data for external tooling,
20+
enabling developers to build test analysis and reporting tools.
21+
However, the current implementation lacks access to some test metadata that
22+
developers may want to use to organize and manage their test suites.
23+
24+
Currently missing from the JSON output are:
25+
- **Test tags**: Used for categorization
26+
- **Bug associations**: Critical for tracking which tests verify specific bug fixes
27+
- **Time limits**: Essential for performance monitoring and timeout management
28+
29+
This missing metadata limits the capabilities of external tools. For example:
30+
- IDE extensions cannot provide tag-based test filtering
31+
- CI/CD systems cannot generate reports grouped by test categories
32+
- Performance monitoring tools cannot track tests with specific time constraints
33+
- Bug tracking integrations cannot correlate test failures with known issues
34+
35+
By exposing this information, we unlock new possibilities for Swift Testing
36+
tooling ecosystem.
37+
38+
## Proposed solution
39+
40+
We propose enriching the test payload in the event JSON stream by adding three
41+
metadata fields:
42+
43+
- **`tags`**: An array of strings where each item represents a single tag applied to the test,
44+
enabling categorization and filtering
45+
- **`bugs`**: An array of bug references, providing traceability between tests
46+
and issue tracking
47+
- **`timeLimit`**: The test's time limit in seconds, enabling performance monitoring
48+
and timeout analysis
49+
50+
These additions leverage existing internal data structures, ensuring minimal performance
51+
impact while maximizing the value delivered to external tools.
52+
53+
## Detailed design
54+
55+
This enhancement builds upon the existing test metadata infrastructure already used
56+
internally by Swift Testing. The implementation reuses established data structures,
57+
ensuring consistency and minimizing complexity.
58+
59+
### Implementation Strategy
60+
61+
Fields are only included when the test actually has at least one matching trait applied, preserving
62+
backwards compatibility with previous versions.
63+
64+
### JSON Schema Changes
65+
66+
The **Modified Backus-Naur Form (BNF)** delta would be:
67+
68+
```diff
69+
diff --git a/Documentation/ABI/JSON.md b/Documentation/ABI/JSON.md
70+
index e4ff24a4..8d7d67ee 100644
71+
--- a/Documentation/ABI/JSON.md
72+
+++ b/Documentation/ABI/JSON.md
73+
@@ -157,10 +157,21 @@ additional `"testCases"` field describing the individual test cases.
74+
["displayName": <string>,] ; the user-supplied custom display name
75+
"sourceLocation": <source-location>, ; where the test is defined
76+
"id": <test-id>,
77+
- "isParameterized": <bool> ; is this a parameterized test function or not?
78+
+ "isParameterized": <bool>, ; is this a parameterized test function or not?
79+
+ ["tags": <array:tag>,] ; the tags associated with this test function
80+
+ ["bugs": <array:bug>,] ; the bugs associated with this test function
81+
+ ["timeLimit": <number>] ; the time limit associated with this test function
82+
}
83+
84+
<test-id> ::= <string> ; an opaque string representing the test case
85+
+
86+
+<tag> ::= "." <string> ; a string representation of a tag
87+
+
88+
+<bug> ::= {
89+
+ ["url": <string>,] ; the bug URL
90+
+ ["id": <string>,] ; the bug id
91+
+ ["title": <string>] ; the human readable bug title
92+
+} ;
93+
```
94+
95+
### Sample JSON Output
96+
97+
Given the following Test Case
98+
99+
```swift
100+
extention Tag {
101+
public static var blue: Self {
102+
Tag(kind: .staticMember("blue"))
103+
}
104+
105+
/// A tag representing the color red.
106+
public static var red: Self {
107+
Tag(kind: .staticMember("red"))
108+
}
109+
}
110+
111+
@Test(
112+
.tags(.blue),
113+
.tags(Tag.red),
114+
.bug("https://my.defect.com/1234"),
115+
.bug("other defect"),
116+
.timeLimit(Swift.Duration.seconds(testTimeLimit + 100)),
117+
.timeLimit(Swift.Duration.seconds(testTimeLimit)),
118+
.timeLimit(Swift.Duration.seconds(testTimeLimit + 10)),
119+
arguments: expectedArgs as [String]
120+
)
121+
func example {}
122+
```
123+
124+
The proposed JSON containing the new fields would looks like
125+
126+
```json
127+
{
128+
"kind": "test",
129+
"payload": {
130+
<...SNIP...>,
131+
"bugs": [
132+
{
133+
"url": "https:\/\/my.defect.com\/1234"
134+
},
135+
{
136+
"url": "other defect"
137+
}
138+
],
139+
"tags": [
140+
".blue",
141+
".red"
142+
],
143+
"timeLimit": 3
144+
},
145+
}
146+
```
147+
148+
## Source compatibility
149+
150+
This proposal maintains full backward compatibility through careful design:
151+
152+
- **ABI Version Protection**: New fields are conditionally included based on ABI
153+
version checks, ensuring older tools continue to function without modification
154+
- **Experimental Feature Migration**: The existing experimental `_tags` field is
155+
replaced with the `tags` array. Since experimental features don't provide
156+
stability guarantees, this replacement doesn't constitute a breaking change
157+
- **Graceful Degradation**: Tools that don't expect the new fields will simply ignore
158+
them, while updated tools can leverage the enhanced metadata
159+
160+
No existing functionality is affected, making this a purely additive enhancement.
161+
162+
## Integration with supporting tools
163+
164+
The enhanced JSON ABI opens up exciting possibilities for the Swift Testing ecosystem:
165+
166+
### Immediate Benefits for Tool Developers
167+
- **IDE Extensions**: Can now provide tag-based test filtering and organization
168+
- **CI/CD Integrations**: Can generate more detailed reports with test categorization
169+
- **Performance Monitoring**: Can track and alert on time limit violations
170+
- **Bug Tracking Integration**: Can correlate test results with known issues
171+
172+
### Migration Path
173+
Existing tools will continue to work unchanged, as the new fields are purely additive.
174+
Tool developers can incrementally adopt the enhanced metadata at their own pace,
175+
choosing which fields provide the most value for their specific use cases.
176+
177+
## Future directions
178+
179+
This enhancement establishes future richer tooling experiences:
180+
181+
### Alternative Field Naming
182+
- **`timeLimitInSeconds` vs `timeLimit`**: We chose the shorter `timeLimit` name for
183+
consistency with Swift Testing's existing API, with the time unit documented in the
184+
schema specification. The naming convention was discussed with the Testing Workgroup
185+
and it was decided that a seperata proposal should be made on how to represent
186+
the time units in the name/value.
187+
188+
### Potential Extensions
189+
- **Additional Metadata**: Other test traits could be exposed as the ecosystem evolves
190+
191+
## Alternatives considered
192+
193+
### Alternative Data Structures
194+
- **Flattened vs Structured Bug Information**: We chose a structured approach for bug
195+
metadata to accommodate various bug tracking systems while maintaining extensibility
196+
197+
### Unconditionally include optional field
198+
- We selected conditional inclusion to keep JSON output clean and avoid null values,
199+
improving the developer experience for tools consuming the data.
200+
201+
## Acknowledgments
202+
203+
Thanks to [Jonathan Grynspan](https://github.com/grynspan) for suggesting to me
204+
I write this proposal and for providing feedback.
205+
206+
Thanks to [Paul LeMarqaund](https://github.com/plemarquand) for providing proposal
207+
feedback before it was posted.

0 commit comments

Comments
 (0)