JSON schema

July 15, 2026 · View on GitHub

This document outlines the JSON schemas used by the testing library for its ABI entry point and for the --event-stream-output-path command-line argument. For more information about the ABI entry point, see the documentation for ABI.v0.EntryPoint.

Modified Backus-Naur form

This schema is expressed using a modified Backus-Naur syntax. {, }, :, and , represent their corresponding JSON tokens. \n represents an ASCII newline character.

The order of keys in JSON objects is not normative. Whitespace in this schema is not normative; it is present to help the reader understand the content of the various JSON objects in the schema. The event stream is output using the JSON Lines format and does not include newline characters (except one at the end of the <output-record-line> rule.)

Trailing commas in JSON objects and arrays are only to be included where syntactically valid.

Common data types

<string> and <number> are defined as in JSON. <array:T> represents an array (also defined as in JSON) whose elements all follow rule <T>.

<bool> ::= true | false ; as in JSON

<source-location> ::= {
  ["fileID": <string>,] ; the Swift file ID of the file if available, as per
                        ; SE-0274 § "Specification of the #file string format"
  "filePath": <string>, ; the compile-time path to the file
  "line": <number>,
  "column": <number>,
}

<instant> ::= {
  "absolute": <number>, ; floating-point seconds since system-defined epoch
  "since1970": <number>, ; floating-point seconds since 1970-01-01 00:00:00 UT
}

<version> ::= "version": <version-number>
<version-number> ::= 0 | "<version core>" ; as per https://semver.org

Streams

A stream consists of a sequence of values encoded as JSON Lines. A single instance of <output-stream> is defined per test process and can be accessed by passing --event-stream-output-path to the test executable created by swift build --build-tests.

<output-stream> ::= <output-record>\n | <output-record>\n <output-stream>

Records

Records represent the values produced on a stream. Each record is encoded on a single line and can be decoded independently of other lines. If a decoder encounters a record whose "kind" field is unrecognized, the decoder should ignore that line.

<output-record> ::= <test-record> | <event-record>

<test-record> ::= {
  <version>,
  "kind": "test",
  "payload": <test>
}

<event-record> ::= {
  <version>,
  "kind": "event",
  "payload": <event>
}

Tests

Test records represent individual test functions and test suites. Test records are passed through the record stream before most events.

<test> ::= <test-suite> | <test-function>

<test-suite> ::= {
  "kind": "suite",
  "name": <string>, ; the unformatted, unqualified type name
  ["displayName": <string>,] ; the user-supplied custom display name
  "sourceLocation": <source-location>, ; where the test suite is defined
  "id": <test-id>,
}

<test-function> ::= {
  "kind": "function",
  "name": <string>, ; the unformatted function name
  ["displayName": <string>,] ; the user-supplied custom display name
  "sourceLocation": <source-location>, ; where the test is defined
  "id": <test-id>,
  "isParameterized": <bool>, ; is this a parameterized test function or not?
  ["tags": <array:tag>,] ; the tags associated with this test function
  ["bugs": <array:bug>,] ; the bugs associated with this test function
  ["timeLimit": <number>] ; the time limit associated with this test function
}

<test-id> ::= <string> ; an opaque string representing the test case

<tag> ::= <string> ; a string representation of a tag

<bug> ::= {
  ["url": <string>,] ; the bug URL
  ["id": <string>,] ; the bug id
  ["title": <string>] ; the human readable bug title
}

Events

Event records represent things that can happen during testing. They include information about the event such as when it occurred and where in the test source it occurred. They also include a "messages" field that contains sufficient information to display the event in a human-readable format.

<event> ::= {
  "kind": <event-kind>,
  "instant": <instant>, ; when the event occurred
  ["issue": <issue>,] ; the recorded issue (if "kind" is "issueRecorded")
  ["attachment": <attachment>,] ; the attachment (if kind is "valueAttached")
  "messages": <array:message>,
  ["testID": <test-id>,]
  ["iteration": <number>,] ; the iteration number (if the event is recorded
                           ; during test execution)
}

<event-kind> ::= "runStarted" | "testStarted" | "testCaseStarted" |
  "issueRecorded" | "testCaseEnded" | "testEnded" | "testSkipped" |
  "runEnded" | "valueAttached" | "testCancelled" | "testCaseCancelled"
  ; additional event kinds may be added in the future

<issue> ::= {
  "isKnown": <bool>, ; is this a known issue or not?
  "severity": <string>, ; the severity of the issue
  "isFailure": <bool>, ; if the issue is a failing issue
  ["sourceLocation": <source-location>,] ; where the issue occurred, if known
}

<attachment> ::= {
  "path": <string>, ; the absolute path to the attachment on disk
}

<message> ::= {
  "symbol": <message-symbol>,
  "text": <string>, ; the human-readable text of this message
}

<message-symbol> ::= "default" | "skip" | "pass" | "passWithKnownIssue" |
  "fail" | "difference" | "warning" | "details"

See Also

Relevant Swift Evolution proposals

Proposal NumberSummarySwift VersionSchema Version
ST-0002Introduced the initial version of this JSON schema.6.00
ST-0009Added attachments.6.20
ST-0013Added test issue severity and isFailure.6.3"6.3"
ST-0016Added test cancellation.6.3"6.3"
ST-0019Added tags, bugs, and timeLimit.6.4"6.4"
ST-0020Added filePath.6.3"6.3"
ST-0024Added iteration.6.4"6.4"