Skip to content

Generated test fixtures, faster robot pipeline - #330

Merged
timdegroot1996 merged 8 commits into
exceptions-trackingfrom
fixture-generator
Sep 16, 2026
Merged

timdegroot1996 merged 8 commits into
exceptions-trackingfrom
fixture-generator

Conversation

@timdegroot1996

@timdegroot1996 timdegroot1996 commented Sep 16, 2026

Copy link
Copy Markdown
Collaborator

Stacked on #325 (exceptions-tracking).

Summary

  • Fixture generatortests/robot/resources/generator/ replaces the 15 hand-made output.xml/log.html fixtures with 18 generated from two simulated projects (WebshopUI, WebshopAPI). libraries/profiles.py declares what the data shows (persistent/flaky/broken-since/fixed-since tests, outage runs, an all-green and a pass+skip-only run, TRY/EXCEPT exceptions, feature-flag skips, duration trends, run/suite metadata), so every graph has data. Deterministic timestamps keep run identities stable across regenerations. Not part of any test runner; robot.toml gives RobotCode the python-path for the fake libraries.
  • Two product bugs surfaced by the new data
    • --messageconfig patterns containing quotes broke the inlined JS literal (dashboard stuck on the spinner) → json.dumps + proper escaping.
    • Run metadata order varied per process (set) → dict.fromkeys, document order.
  • Robot pipeline: ~4.7 min → ~1.5–2 min
    • Browser suites generate one shared dashboard per run instead of parsing all fixtures per test.
    • Chart animations off via tests/robot/resources/test_config.json (-j); the settings "duration" only scales the stagger delay, Chart.js still animated 1 s (the old Sleep 1s was covering that).
    • Wait For Dashboard Idle replaces sleeping: a test-only window.dashboard_is_idle() injected from tests/robot/resources/scripts/dashboard_idle.js (no product JS changed), true only when no spinner/overlay/modal/fade/Chart.js animation is active for 50 ms. Must stay synchronous — Playwright's waitForFunction treats a returned Promise as truthy.
    • 4 pabot processes; failed tests rerun once and merged (rebot --merge) so a transient browser crash does not fail the run.
    • Robot job runs in a prebuilt image ghcr.io/marketsquare/robotframework-dashboard-test-robot (existing robot Dockerfile, built by the new test-image.yml on main when requirements-test.txt/Dockerfile change, or manually). The image is chromium-only and flattened to a single layer (4.9 GB → 2.3 GB; same base, so reference screenshots are unchanged). First image pushed manually; the package is public.
  • scripts/example.py (cross-platform) builds the example dashboard; example.bat wraps it. Example, docs, CONTRIBUTING and agent skills updated.

Verification

  • Python 392 / JS 274 unit tests pass.
  • Full robot suite in Docker: 64 tests, 60 passed, 0 failed, 4 OS skips, ~70 s.
  • Docs site built and served: overview-card and graph-click log links resolve to example/tests/robot/resources/outputs/log-*.html.

Notes

  • database_output/keywords.txt averages come from the CI image's Python 3.10; Python ≥ 3.12 sum() rounds a few x.xxx5 values differently, so those references must be regenerated in Docker only.
  • Possible follow-up: pass duration: settings.show.duration in graph_config.js so the animation-duration setting means what it says.

🤖 Generated with Claude Code

timdegroot1996 and others added 8 commits September 16, 2026 23:04
Two issues surfaced by the new test fixtures:

- --messageconfig patterns were inlined with str(list).replace("'", '"'),
  so any quote in a pattern broke the JS string literal and left the
  dashboard on the loading spinner. Use json.dumps and escape for the
  single-quoted literal that data.js JSON.parses.
- Run metadata was deduplicated through a set, so its order changed per
  process (hash randomisation). Use dict.fromkeys to dedupe in document
  order; the old fixtures had no metadata so this never showed.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Replace the 15 hand-made output.xml/log.html fixtures with 18 generated
from two simulated projects (WebshopUI, WebshopAPI) whose behaviour is
declared in tests/robot/resources/generator/libraries/profiles.py:
persistent, flaky, broken-since and fixed-since tests, outage runs, an
all-green and a pass+skip-only run, TRY/EXCEPT exceptions, feature-flag
skips, duration trends and run/suite metadata, so every dashboard graph
has data. Timestamps are shifted to a fixed schedule and durations
scaled, so regenerating keeps run identities stable.

The generator suites are not picked up by any runner; robot.toml gives
RobotCode the python-path for their fake libraries.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Python unit tests pick fixtures by glob instead of file name. Robot CLI
and database references and reference screenshots regenerated in the
Docker image; obsolete overview screenshots removed. The timezone mask
in the database comparison accepts missing microseconds and negative
offsets, which the new fixtures use.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
CI robot job took ~4.7 min: ~110 s of container setup and 155 s of
tests. Now 75 s of tests and a checkout + pip install:

- Browser suites generate one shared dashboard per run (pabot lock)
  instead of parsing all 18 fixtures per test; each test still gets its
  own browser context. Cleanup lives in __init__.robot because pabot
  loads it without a resolvable path for Resource imports.
- Chart animations are disabled through tests/robot/resources/
  test_config.json (-j). The settings UI "duration" only scales the
  stagger delay in graph_config.js, Chart.js still animated 1 s, which
  the old Sleep 1s was covering.
- Wait For Dashboard Idle replaces that sleep: Open Dashboard injects a
  test-only window.dashboard_is_idle() (resources/scripts/
  dashboard_idle.js, unit-tested) that is true only when no spinner,
  overlay, modal/backdrop, jQuery fade or Chart.js animation is active
  and 50 ms have passed since. It must stay synchronous: Playwright's
  waitForFunction treats a returned Promise as truthy.
- pabot runs 4 processes (ROBOT_PROCESSES overrides). Failed tests are
  rerun once and merged with rebot --merge, so a transient browser
  crash or timing race does not fail the pipeline.
- The robot job runs in a prebuilt image published to GHCR by the new
  test-image.yml workflow (from the existing robot Dockerfile) instead
  of installing pip, the test requirements and rfbrowser every run.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Cross-platform replacement for the hard-coded command list in
example.bat: derives tags, versions, timezones and custom filters from
the generated fixtures and copies the result into example/. example.bat
is now a one-line wrapper. Example dashboard, database and message
config rebuilt from the new fixtures.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
The Browser library installs its own Playwright (node side), which can
be newer than the Playwright base image's, so rfbrowser init used to
download a second full browser set next to the base image's three.
Drop the base browsers, install only chromium for the library's
version and flatten the result into a single layer so the deleted files
and caches are really gone: 4.9 GB -> 2.3 GB, same fonts and system
libraries so the reference screenshots are unchanged.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
A single flattened layer is downloaded and decompressed serially, which
made the container start slower than with the larger layered image.
Copy the filesystem in a few similar-sized layers instead so they are
pulled in parallel, and push them zstd-compressed from test-image.yml.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
@timdegroot1996
timdegroot1996 merged commit bf110fa into exceptions-tracking Sep 16, 2026
3 checks passed
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