In an Allure `-result.json` file, what is the difference between the `labels` array and the `links` array, and what does one entry of each hold?
answer
- two arrays, two different jobs
- one indexes, one leaves the report
- name and value versus name, url, type
- link type is issue, tms or custom
basics
~20 sLabels are name-and-value pairs the report groups and filters by, such as epic, feature, suite, owner and severity. Links point outside the report: each holds a name, a url and a type, which is issue, tms or custom.
solid answer
~40 sBoth live on the test result and both are arrays, but they answer different questions. A `Label` is a `{name, value}` pair and it is what the report *groups* by: `parentSuite`/`suite`/`subSuite` build the suite tree, `epic`/`feature`/`story` build the behaviour grouping, and `severity` and `owner` drive their own views. A `Link` is `{name, url, type}` and it is what the report *leaves* by -- `type` is `issue`, `tms` or `custom`, and `url` is where a reader lands when they click. The practical consequence of the difference: a label whose name nothing groups on is still written and still shown on that test's page but forms no tree, and a link whose `url` was never derived renders as text you cannot click.
code
json · 17 lines{
"uuid": "9f2b1c7e-4a3d-4a51-9d0e-1b2c3d4e5f60",
"name": "checkout applies the promo code",
"status": "passed",
"labels": [
{ "name": "parentSuite", "value": "Checkout" },
{ "name": "suite", "value": "Promotions" },
{ "name": "epic", "value": "Billing" },
{ "name": "feature", "value": "Promo codes" },
{ "name": "owner", "value": "a.ivanova" },
{ "name": "severity", "value": "critical" }
],
"links": [
{ "name": "TC-431", "url": "https://tms.example.com/case/TC-431", "type": "tms" },
{ "name": "BUG-88", "url": "https://tracker.example.com/BUG-88", "type": "issue" }
]
}go deeper
Be able to point at the two arrays in a result file and say what one entry of each holds: a label is a name and a value, a link is a name, a url and a type.
Explain which label names the report's groupings actually consume, and that an unrecognised label name is written and displayed but builds no tree.
Show how you would audit a consolidated report's metadata: which labels the adaptor derives for you, which the test source declares, and which arrive missing.
Own which label names your reports are allowed to group on and which stay free-form annotation, and be able to say what a report can honestly promise once several suites feed it.
## Two arrays, two jobs An Allure `-result.json` file is one test's record, and two of its arrays carry **metadata** rather than outcome. They look alike -- both are short lists of small objects -- and they are routinely conflated, but they do opposite things. - **`labels`** is a list of `{name, value}` pairs. A label is an **index**: it says which group this result belongs to, so the report can build a tree or a filter out of many results. - **`links`** is a list of `{name, url, type}` objects. A link is an **exit**: it says where a reader goes to see something the report does not itself hold. Neither decides whether the test passed; `status` does that, and it is a separate field. Both arrays are filled in by the *adaptor* -- the framework integration that turns a test-framework callback into a result file -- and both are read again by the generator that turns a results directory into a report. ## The label vocabulary A `Label` has no schema beyond `name` and `value`, so the **names are the vocabulary**. The report's built-in groupings are keyed to a known set of them: | label name | what the report does with it | |---|---| | `parentSuite`, `suite`, `subSuite` | the three levels of the suite tree | | `epic`, `feature`, `story` | the three levels of the behaviour grouping | | `severity` | resolved against `SeverityLevel`: `BLOCKER`, `CRITICAL`, `NORMAL`, `MINOR`, `TRIVIAL`, written lowercase | | `owner` | a plain string naming who is answerable for the test | Two consequences follow from "the name is the vocabulary": 1. **A name nothing groups on is still legal.** The writer serialises whatever it is given. A label whose name your team invented reaches the file and appears among that test's own metadata, but no built-in tree keys off it, so it indexes nothing. 2. **A name may repeat.** `labels` is a list, not a map. A result can carry two `feature` labels, and the grouping treats that as membership of two branches rather than as a conflict to resolve. ## The link vocabulary `Link` has exactly three fields. `type` is `issue`, `tms` or `custom` -- `issue` for a tracker item, `tms` for a case in a case repository, `custom` for anything else -- and the type is not a closed list, it is just a string. `name` is what the reader sees on the page. `url` is where the click goes. The important asymmetry is that **`url` may be null**. Annotations such as `@Issue` and `@TmsLink` record only an id; the url is derived from it at write time, and if nothing supplies the derivation the link is still written -- with a name, a type, and no target. The report then shows the id as plain text. Nothing errors, and the file is perfectly valid. ## Where the values come from Three sources feed these arrays, and telling them apart is most of what makes a consolidated report readable: - **The adaptor**, automatically. It knows the class and method it just ran, so it can derive suite labels from the test's own structure without anyone writing an annotation. - **The test source**, explicitly. Annotations on the class or method add `epic`, `feature`, `story`, `owner`, `severity` and links. - **The run's configuration**, uniformly. Values supplied to the whole run land on every result the run produces. Because the arrays are plain lists, all three sources simply append. There is no merge step, no last-writer-wins rule, and no validation that a name was used only once. ## Why the distinction matters when results are consolidated When one report is generated from several suites' results, `labels` and `links` fail differently and the fixes live in different places. - Labels fail **structurally**. If one suite sets `parentSuite` and another does not, the two are grouped at different depths in the same tree, and the tree is the thing readers navigate by. The symptom is a lopsided tree, not an error message. - Links fail **individually**. A link with no url is a dead id on one test's page. It costs that one reader a lookup; it does not distort anything the report aggregates. That difference is worth stating out loud in an interview, because it decides what you go and check first. A report whose grouping is unusable is a metadata-vocabulary problem across suites. A report full of unclickable ticket ids is a configuration problem in whatever wrote the results. ## Things that are easy to get wrong - **A label is not a tag with special powers.** It has no type, no validation and no closed set of permitted values. `severity` is resolved against a known list, but that resolution happens in the report, not in the file: the file just holds the string. - **A link is not a copy of the ticket.** It holds a name, a url and a type. Nothing in the result file records the ticket's state, and nothing revalidates the url. - **Neither array is keyed.** Both are ordered lists of small objects, and duplicates are ordinary.
- A result carries a label whose name is not one the report groups on. Is it dropped?No. The writer serialises every label into the result file and the report shows it among that test's own metadata, but the built-in groupings key off the names they know, so an invented name contributes to no tree and to no filter derived from one. It documents that single result rather than indexing many.
- Where does a `Link`'s `url` come from if the annotation supplied only a ticket id?From the writer. `allure-java` derives it when the result is written, by substituting the recorded id into the `allure.link.<type>.pattern` property read from `allure.properties`. If no such property is found the derivation returns null and the link is written with a name and a type but no url.
saying these in an interview costs you the question
- Calls every piece of result metadata a tag
- Thinks a link stores only the ticket id
- Assumes any label name builds a tree
- Confuses a label's value with a link url