LTS: populate duration_in_ms + attach per-step meta.steps on Nightwatch TestRunFinished - #60
Merged
shubhamkd merged 3 commits intoJul 30, 2026
Conversation
Main-path (non-cucumber, non-hook, non-skipped) Nightwatch TestRunFinished never carried duration_in_ms. Downstream is a straight passthrough (observability-pipeline EventProcessorService line 874 + 1325 in buildBtcerForLts), so BTCER.duration ended up NULL on every LTS Nightwatch row — and every duration-derived Tests-tab metric (min/avg/p50/p75/p90/p95/p99/max) rendered as 0. Fix gated on helper.isLoadTestingSession() so non-LTS emits stay byte-identical. Duration computed from the envelope timestamps (finished_at - started_at) that sendTestRunEvent already assigns for the TestRunFinished branch. Verified end-to-end: patched plugin + local Selenium jar + real Chrome + BROWSERSTACK_LTS_SESSION_ID set → TestRunFinished payload carries duration_in_ms = 145 (matches the timestamp delta). Contract check with LTS env off → duration_in_ms absent from payload. Two unit tests added to sendTestRunEvent.spec cover both paths. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The LCNC compiler emits each recorded step wrapped in a bstackStep()
helper that captures per-step timings and pushes them to
globalThis.__bstack_steps. This change lets the plugin surface that
buffer to Testhub so the mv_btcer_step_metrics_v5 MV can fan it out
into btcer_step_metrics_v5 — the table Step Insights aggregates on
across builds.
Two touch points, both gated on helper.isLoadTestingSession() (same
gate as the duration_in_ms fix, so non-LTS Automate customers see
byte-identical uploads):
- nightwatch/globals.js: reset globalThis.__bstack_steps on every
TestRunStarted so retries and per-VU iterations get clean buffers.
- src/testObservability.js: attach the buffer to testData.meta.steps
on TestRunFinished. Non-destructive merge — preserves whatever meta
fields (e.g. configuration_id) the LT pipeline had already written.
Verified end-to-end against real Testhub:
- Compiled a sample LCNC-style Nightwatch spec (tests/lcnc_mimic_test.js
in local mimic) with 6 bstackStep-wrapped steps.
- Ran through local chromedriver with BROWSERSTACK_LTS_SESSION_ID set
→ build creation succeeded, TestRunFinished payload carried
test_run.meta.steps as a 6-entry array.
- ClickHouse: build_test_case_execution_results_v5 row landed with
meta.steps present, mv_btcer_step_metrics_v5 fanned out 6 rows into
btcer_step_metrics_v5 with correct step_text, step_result and
step_duration values (846, 597, 118, 72, 47, 24 ms).
Three unit tests added to sendTestRunEvent.spec cover: attach on LTS,
omit on non-LTS, and empty/missing buffer.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
MihirR-BS
marked this pull request as ready for review
July 29, 2026 22:57
The repo's eslint config doesn't declare es2020 env, so globalThis trips no-undef. `global` is Node's builtin and works in every runtime this plugin actually ships to. Also splits the one-line if-block so the `semi` rule's omitLastInOneLineBlock stops flagging the assignment's own terminator.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two LTS-only reporting improvements to the Nightwatch main-path (
sendTestRunEvent), both gated onhelper.isLoadTestingSession()so non-LTS Automate customers see byte-identical uploads.1. Populate
duration_in_ms(regression fix — commit 389d6a8)Main-path Nightwatch
TestRunFinishednever carriedduration_in_ms(cucumber / hook / skipped paths do). Downstream is a straight passthrough (observability-pipelineEventProcessorServiceL874 + L1325 inbuildBtcerForLts), so BTCER.duration ended up NULL on every LTS Nightwatch row — every duration-derived Tests-tab metric (min/avg/p50/p75/p90/p95/p99/max) rendered as 0.Fix: compute duration from the envelope timestamps that
sendTestRunEventalready assigns for theTestRunFinishedbranch (finished_at - started_at).2. Attach per-step data to
meta.steps(new capability — commit c976a0b)Enables the Step Insights feature for LTS Nightwatch builds. The LCNC compiler wraps every recorded step in a
bstackStep(idx, text, id, async fn)helper that captures per-step timings and pushes{id, text, keyword, duration, started_at, finished_at, result, failure}toglobalThis.__bstack_steps. This change lets the plugin surface that buffer to Testhub so themv_btcer_step_metrics_v5MV fans it out intobtcer_step_metrics_v5— the table the Step Insights/cross-build-step-metricsendpoint aggregates on across builds.Two touch points:
nightwatch/globals.js: resetglobalThis.__bstack_stepson everyTestRunStartedso retries, reruns, and per-VU iterations get clean buffers.src/testObservability.js: onTestRunFinished, attach the buffer totestData.meta.steps. Non-destructive merge — preserves whatever meta fields (e.g.configuration_id) the LT pipeline had already written.Verification
duration_in_msPatched plugin + local Selenium jar + real Chrome +
BROWSERSTACK_LTS_SESSION_IDset →TestRunFinishedpayload carriesduration_in_ms = 145(matches the timestamp delta). Contract check with LTS env off →duration_in_msabsent from payload.meta.steps(end-to-end against real Testhub)bstackStep-wrapped steps) through local chromedriver withBROWSERSTACK_LTS_SESSION_ID=local-e2e-4set.TestRunFinishedpayload carriedtest_run.meta.stepsas a 6-entry array.build_test_case_execution_results_v5row landed withmeta.stepspresent (length(JSONExtractArrayRaw(meta,'steps'))= 6).mv_btcer_step_metrics_v5fanned out 6 rows intobtcer_step_metrics_v5with correctstep_text,step_result,step_duration(846, 597, 118, 72, 47, 24 ms),step_started_at,step_finished_at.Sample build in Automate:
98w1ld2w7qqihu9mnw1brpgnv582oezqktrkpxcf.Retries / re-runs
TestRunStarted→ reset zeros the array → fresh steps per attempt.sendTestRunEventcaptures the array reference synchronously at handler start, before any subsequent reset can happen.globalThis→ no cross-pollination.Test plan
test/src/test-observability/sendTestRunEvent.js:duration_in_mspopulated on LTS runsduration_in_msunset on non-LTS runsmeta.stepsattached on LTS runs when buffer populatedmeta.stepsomitted on non-LTS runs even when buffer populatedmeta.stepsomitted on LTS runs when buffer empty/missing🤖 Generated with Claude Code