skip to content

How do you make a provider-recorded session video findable from a failing test's report?

level: seniorimportance: should knowfreq 52%

answer

  1. the archive is complete and unsearchable
  2. the service names it after itself
  3. correlation is always the client's job
  4. the identifier comes back in the reply
  5. a stored name is a normalised name

basics

~20 s

By default the service names the artefact after its own session identifier, which no report carries unless you put it there. Either name the file from the test on the session request, or record the identifier the reply gives back.

solid answer

~50 s

By default the far side names the artefact after its **own** identifier for the session, which your report does not carry unless you put it there — so correlation is the client's job, arranged either on the session request or in what the run records. Selenoid — unmaintained by its own README — accepts a `videoName` in `selenoid:options` and renames the finished file to it at close, warning that the value must carry the `mp4` extension; without one the file becomes `<session-id>.mp4`. `docker-selenium`'s recorder, set to derive names automatically with `SE_VIDEO_FILE_NAME`, takes the name from the session's own capabilities, still appends the session id unless `SE_VIDEO_FILE_NAME_SUFFIX` is turned off, and normalises the result — spaces to underscores, other punctuation stripped. Against a closed provider you may not assume any naming key exists, so capture the identifier the session reply hands you.

code

java · 14 lines
java
String testId = "membership-renewal-lapsed-" + runId;

Map<String, Object> selenoid = new HashMap<>();
selenoid.put("enableVideo", true);
// Selenoid renames the finished file to this at session close
selenoid.put("videoName", testId + ".mp4");

ChromeOptions options = new ChromeOptions();
options.setCapability("selenoid:options", selenoid);
// docker-selenium's recorder instead reads Selenium Grid's se:name
options.setCapability("se:name", "Renew lapsed museum membership");

RemoteWebDriver driver = new RemoteWebDriver(gridUrl, options);
log.info("session {} -> video for {}", driver.getSessionId(), testId);

go deeper

for a junior

Know that the recording is named after the session, not after your test, and that finding the right one later is something the run has to arrange while it is still running.

for a middle

Be able to name both directions: put a name on the session request, or keep the identifier the reply returns. Say which one still works when the provider offers no naming setting.

for a senior

This is your tier. Expect to be asked why a naming scheme collided or why report links break, and to reach for uniqueness across re-runs and parallel workers and for name normalisation.

for a principal

Own the convention across teams: one artefact-naming scheme, one place the session identifier is recorded, and a rule that links are stored rather than reconstructed. Inconsistency here is what makes shared triage slow.

## The default name is the service's, not yours The open implementations of this mechanism share one default, and it is the right one: the artefact is named after the **session identifier** the service minted. It is guaranteed unique, it needs nothing from the client, and it is meaningless to anyone reading a test report. A run of your museum membership-renewal suite produces a directory of correctly-named files and no way to tell which one is the renewal that failed. Correlation is therefore always the client's job. There are two directions to do it in, and a mature suite usually does both. ## Direction one: name the artefact from the test You put a name on the session request and the service uses it for the file. - **Selenoid** — unmaintained by its own README — reads `videoName` from its `selenoid:options` map and renames the finished file to that value in its session-close path. Its own documentation warns that the value must carry the `mp4` extension, because nothing appends one for you. - **`docker-selenium`**'s recorder, when `SE_VIDEO_FILE_NAME` is set to derive names automatically rather than to a literal, reads the name off the session's capabilities — preferring a dedicated video-name capability and otherwise falling back to Selenium Grid's `se:name` test-metadata capability — and uses the session identifier only when neither is present. Both are the same idea: the client already knows what the test is called, and the service does not. ## Direction two: record the identifier the reply gives you The session-creation reply carries the identifier the service is going to use. Write it into whatever your run already records, and the default naming stops being a problem: the file named after the session is findable because your record points at it. This direction has one large advantage: it works **whatever the service lets you configure**. Naming the file from the test needs a setting the service accepts, and against a closed provider you may not assume any particular key exists — but every WebDriver session has an identifier, in the reply. ## The traps | Trap | What happens | |---|---| | A test name that is not unique | a re-run writes the same file and the first is gone | | Turning off the id suffix | uniqueness now depends entirely on your naming discipline | | A literal fixed name | every session writes the same file, and only the last one survives | | Reconstructing the URL from the raw test name | the stored name was normalised; your URL is not found | The normalisation trap is the one that catches experienced people. `docker-selenium`'s recorder replaces spaces with underscores and strips characters outside letters, digits, hyphen and underscore, with the pattern itself configurable through `SE_VIDEO_FILE_NAME_TRIM_REGEX`, and it trims the result so the file name cannot grow unbounded. A test called `Renew membership (lapsed, gift-aid)` is not stored under that string, so a report that builds a link by concatenating the raw test name onto a base path produces a link that does not resolve. The fix is to construct the name the same way the recorder does, or better, to record the name the service reported back rather than the name you hoped for. The uniqueness trap is the reason the id suffix exists in the first place. Names collide in ways people do not expect: - the same test re-run after a flake, in the same account; - the same test running in parallel workers against different data sets; - a parameterised case whose display name is identical for every parameter row; - separate branches' pipelines sharing a single provider account. Appending the session identifier makes every one of those safe at the cost of an ugly file name, which is why it is the default rather than an option you have to find. ## What to do 1. **Name from the test where you can**, using the identity your framework already computes for the case rather than a hand-written string. 2. **Keep the service's identifier in the name too**, unless you are certain the test identity is unique across re-runs and parallel workers — and be honest that you usually are not. 3. **Record the session identifier in the run's own output regardless**, because it is the one handle that survives a provider that will not let you name anything. 4. **Never reconstruct an artefact address from a raw human string.** Store what came back. ## On a closed provider Everything above is stated as a shape on purpose. You may not assume that a particular hosted product exposes a naming key, what it is called, or what characters it accepts, and nothing in a closed product can be checked. What you can rely on is the invariant the open implementations make visible: **the service names artefacts after its own session identifier unless told otherwise, and that identifier is in the reply you already received.** Build your correlation on that, and add service-side naming as a convenience where the provider offers it.

  • Why do these recorders append the session identifier even when the test supplied a name?
    Because a test name is not a unique key and the recorder cannot tell. The same case re-runs after a flake, runs in two parallel workers, or appears identically for every row of a parameterised set — and a second session writing the same file name means one recording is lost. Appending the identifier makes collisions impossible at the cost of a longer name, which is why it is the default rather than an opt-in.
  • Your suite names videos from the test title and half the links in the report resolve. What is the likely cause?
    The stored name was normalised and your link was not. Recorders replace spaces and strip punctuation before writing the file, so titles containing brackets, colons or slashes are stored under a different string than the one you concatenated. The links that work are the titles that happened to survive normalisation unchanged. Store the name the service used, or apply the same transformation before building the link.
  • A provider gives you no way to name the recording. How do you still correlate?
    Record the session identifier from the creation reply into the run's own output at the moment the session starts, before anything can fail. Whatever the provider exposes for browsing its own recordings, the session is the unit it organises them by, so a reader holding that identifier has the handle to present. This direction needs nothing from the provider beyond a session, which is why it is the one to build on.

Naming every recording after the session identifier is filing photographs by negative number: the archive is complete, perfectly ordered, and useless to anyone who did not write the negative number down. Putting the test's own name on the file is what makes the shelf browsable instead.

saying these in an interview costs you the question

  • Assumes the provider names recordings after the test by default
  • Builds artefact links by concatenating a raw human-readable test name
  • Turns off the session-id suffix without checking test names are unique
  • Sets one fixed file name and wonders why only one video survives
  • Never records the session identifier anywhere in the run's output