Skip to content

Commit f56f077

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

File tree

1 file changed

+212
-0
lines changed

1 file changed

+212
-0
lines changed
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
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..b47a0257 100644
71+
--- a/Documentation/ABI/JSON.md
72+
+++ b/Documentation/ABI/JSON.md
73+
@@ -157,10 +157,26 @@ 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> ::= "." <chacters> | <tag> ; 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+
+<characters> ::= "" | <characters> <character>
95+
+<chacter> ::= <letter> | <digit>
96+
+<letter> ::= 'a' | 'b' | 'c' | ... | 'z' | 'A' | 'B' | ... | 'Z'
97+
+<digit> ::= '0' | '1' | '2' | ... | '9'
98+
```
99+
100+
### Sample JSON Output
101+
102+
Given the following Test Case
103+
104+
```swift
105+
extention Tag {
106+
public static var blue: Self {
107+
Tag(kind: .staticMember("blue"))
108+
}
109+
110+
/// A tag representing the color red.
111+
public static var red: Self {
112+
Tag(kind: .staticMember("red"))
113+
}
114+
}
115+
116+
@Test(
117+
.tags(.blue),
118+
.tags(Tag.red),
119+
.bug("https://my.defect.com/1234"),
120+
.bug("other defect"),
121+
.timeLimit(Swift.Duration.seconds(testTimeLimit + 100)),
122+
.timeLimit(Swift.Duration.seconds(testTimeLimit)),
123+
.timeLimit(Swift.Duration.seconds(testTimeLimit + 10)),
124+
arguments: expectedArgs as [String]
125+
)
126+
func example {}
127+
```
128+
129+
The proposed JSON containing the new fields would looks like
130+
131+
```json
132+
{
133+
"kind": "test",
134+
"payload": {
135+
<...SNIP...>,
136+
"bugs": [
137+
{
138+
"url": "https:\/\/my.defect.com\/1234"
139+
},
140+
{
141+
"url": "other defect"
142+
}
143+
],
144+
"tags": [
145+
".blue",
146+
".red"
147+
],
148+
"timeLimit": 3
149+
},
150+
}
151+
```
152+
153+
## Source compatibility
154+
155+
This proposal maintains full backward compatibility through careful design:
156+
157+
- **ABI Version Protection**: New fields are conditionally included based on ABI
158+
version checks, ensuring older tools continue to function without modification
159+
- **Experimental Feature Migration**: The existing experimental `_tags` field is
160+
replaced with the `tags` array. Since experimental features don't provide
161+
stability guarantees, this replacement doesn't constitute a breaking change
162+
- **Graceful Degradation**: Tools that don't expect the new fields will simply ignore
163+
them, while updated tools can leverage the enhanced metadata
164+
165+
No existing functionality is affected, making this a purely additive enhancement.
166+
167+
## Integration with supporting tools
168+
169+
The enhanced JSON ABI opens up exciting possibilities for the Swift Testing ecosystem:
170+
171+
### Immediate Benefits for Tool Developers
172+
- **IDE Extensions**: Can now provide tag-based test filtering and organization
173+
- **CI/CD Integrations**: Can generate more detailed reports with test categorization
174+
- **Performance Monitoring**: Can track and alert on time limit violations
175+
- **Bug Tracking Integration**: Can correlate test results with known issues
176+
177+
### Migration Path
178+
Existing tools will continue to work unchanged, as the new fields are purely additive.
179+
Tool developers can incrementally adopt the enhanced metadata at their own pace,
180+
choosing which fields provide the most value for their specific use cases.
181+
182+
## Future directions
183+
184+
This enhancement establishes future richer tooling experiences:
185+
186+
### Potential Extensions
187+
- **Additional Metadata**: Other test traits could be exposed as the ecosystem evolves
188+
189+
## Alternatives considered
190+
191+
### Alternative Field Naming
192+
- **`timeLimitInSeconds` vs `timeLimit`**: We chose the shorter `timeLimit` name for
193+
consistency with Swift Testing's existing API, with the time unit documented in the
194+
schema specification. The naming convention was discussed with the Testing Workgroup
195+
and it was decided that a seperata proposal should be made on how to represent
196+
the time units in the name/value.
197+
198+
### Alternative Data Structures
199+
- **Flattened vs Structured Bug Information**: We chose a structured approach for bug
200+
metadata to accommodate various bug tracking systems while maintaining extensibility
201+
202+
### Unconditionally include optional field
203+
- We selected conditional inclusion to keep JSON output clean and avoid null values,
204+
improving the developer experience for tools consuming the data.
205+
206+
## Acknowledgments
207+
208+
Thanks to [Jonathan Grynspan](https://github.com/grynspan) for suggesting to me
209+
I write this proposal and for providing feedback.
210+
211+
Thanks to [Paul LeMarqaund](https://github.com/plemarquand) for providing proposal
212+
feedback before it was posted.

0 commit comments

Comments
 (0)