Skip to content

LTS: populate duration_in_ms + attach per-step meta.steps on Nightwatch TestRunFinished - #59

Closed
MihirR-BS wants to merge 2 commits into
nightwatchjs:mainfrom
MihirR-BS:lts-nightwatch-step-insights
Closed

LTS: populate duration_in_ms + attach per-step meta.steps on Nightwatch TestRunFinished#59
MihirR-BS wants to merge 2 commits into
nightwatchjs:mainfrom
MihirR-BS:lts-nightwatch-step-insights

Conversation

@MihirR-BS

Copy link
Copy Markdown
Contributor

Summary

Two LTS-only reporting improvements to the Nightwatch main-path (sendTestRunEvent), both gated on helper.isLoadTestingSession() so non-LTS Automate customers see byte-identical uploads.

1. Populate duration_in_ms (regression fix)

Main-path Nightwatch TestRunFinished never carried duration_in_ms (cucumber / hook / skipped paths do). Downstream is a straight passthrough (observability-pipeline EventProcessorService L874 + L1325 in buildBtcerForLts), 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 sendTestRunEvent already assigns for the TestRunFinished branch (finished_at - started_at).

2. Attach per-step data to meta.steps (new capability)

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} to globalThis.__bstack_steps. This change lets the plugin surface that buffer to Testhub so the mv_btcer_step_metrics_v5 MV fans it out into btcer_step_metrics_v5 — the table the Step Insights /cross-build-step-metrics endpoint aggregates on across builds.

Two touch points:

  • nightwatch/globals.js: reset globalThis.__bstack_steps on every TestRunStarted so retries, reruns, and per-VU iterations get clean buffers.
  • src/testObservability.js: on TestRunFinished, attach the buffer to testData.meta.steps. Non-destructive merge — preserves whatever meta fields (e.g. configuration_id) the LT pipeline had already written.

Verification

duration_in_ms

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.

meta.steps (end-to-end against real Testhub)

  • Ran a sample LCNC-style Nightwatch spec (6 bstackStep-wrapped steps) through local chromedriver with BROWSERSTACK_LTS_SESSION_ID=local-e2e-4 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 (length(JSONExtractArrayRaw(meta,'steps')) = 6).
  • MV mv_btcer_step_metrics_v5 fanned out 6 rows into btcer_step_metrics_v5 with correct step_text, step_result, step_duration (846, 597, 118, 72, 47, 24 ms), step_started_at, step_finished_at.

Sample build in Automate: 98w1ld2w7qqihu9mnw1brpgnv582oezqktrkpxcf (build_id 143028133, source=TO,LTS).

Retries / re-runs

  • Each Nightwatch retry attempt fires its own TestRunStarted → reset zeros the array → fresh 6 steps per attempt.
  • Each attempt gets its own BTCER row via a distinct uuid.
  • sendTestRunEvent captures the array reference synchronously at handler start, before any subsequent reset can happen.
  • Parallel BLU pods run in separate Node processes → separate globalThis → no cross-pollination.

Test plan

  • Unit tests added to test/src/test-observability/sendTestRunEvent.js:
    • duration_in_ms populated on LTS runs (existing from prior commit)
    • duration_in_ms unset on non-LTS runs (existing from prior commit)
    • meta.steps attached on LTS runs when buffer populated
    • meta.steps omitted on non-LTS runs even when buffer populated
    • meta.steps omitted on LTS runs when buffer empty/missing
  • Local end-to-end mimic against real Testhub — see Verification section.
  • Full LTS pod run against a Playwright/Selenium-generated LCNC test (deferred — pairs with the matching LCNC compiler PR that emits bstackStep(...) wrappers).

🤖 Generated with Claude Code

MihirR-BS and others added 2 commits July 24, 2026 06:02
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

Copy link
Copy Markdown
Contributor Author

Closing — filed against the wrong target. LTS-scoped changes shouldn't go to the public upstream. Will re-open against the internal LTS fork's target branch once the paired LCNC compiler PR is up. Branch remains available on MihirR-BS:lts-nightwatch-step-insights for reference.

@MihirR-BS MihirR-BS closed this Jul 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant