Skip to content

Track exception occurrences across test runs - #325

Merged
timdegroot1996 merged 3 commits into
mainfrom
exceptions-tracking
Sep 16, 2026
Merged

timdegroot1996 merged 3 commits into
mainfrom
exceptions-tracking

Conversation

@timdegroot1996

Copy link
Copy Markdown
Collaborator

Summary

Closes #103. Reimplements #253 (which had drifted 5 months and conflicted in 10 files) on a fresh branch off main, using its diff as the spec rather than resolving merge conflicts.

  • New ExceptionProcessor (processors.py): a ResultVisitor that tracks TRY/EXCEPT depth and records the message of the innermost failing keyword per TRY block. Nested TRY blocks, a FOR loop inside TRY, and a keyword wrapping another failing keyword all correctly count only the leaf failure, never the parent/ancestor keywords.
  • New exceptions SQLite table (queries.py, database.py): created for both fresh and legacy databases (CREATE TABLE IF NOT EXISTS, so opening an existing DB just adds it), inserted per-run in insert_output_data, included in get_data(), and cleaned up in _remove_run() — all defensively tolerant of a missing table (custom database classes, or a table dropped out-of-band).
  • New "Keyword Exceptions" graph (Bar/Timeline, keyword.js + new graph_data/exceptions.js) and "Table Exception" (tables.js), wired through the existing graphMetadata-driven layout system. No changes were needed to layout.js/graphs.js/settings.js — graph visibility, default show/hide state, and GridStack placement are all fully data-driven from graphmetadata.js, so a new entry there is sufficient.
  • filter.js: filteredExceptions flows through the same timezone-conversion/filter/sort pipeline as the other filtered arrays (runs/suites/tests/keywords).

Test plan

  • bash scripts/python-tests.sh — 340/340 passing (30 new tests: ExceptionProcessor unit tests covering TRY depth tracking and leaf-only counting, database insert/get/remove-run round-trips including a missing-exceptions-table legacy-DB case, dashboard placeholder embedding)
  • bash scripts/javascript-tests.sh — 266/266 passing (10 new tests for get_exceptions_data(): bar/timeline aggregation, sorting by total count, Top-10 limit, run-alias labeling)
  • Real end-to-end validation (not just mocks): ran an actual Robot Framework suite through the full CLI pipeline exercising nested TRY/EXCEPT, a FOR loop inside TRY, and a keyword wrapping another failing keyword. ExceptionProcessor's counts matched hand-counted expectations exactly (3/3/1 across three distinct exception messages); the exceptions SQLite table and the generated dashboard HTML both embedded the correct compressed data; the bundled <script> extracted from the generated HTML is syntax-clean (node --check) with no duplicate function declarations from the multi-file JS merge.
  • npm run docs:build — clean
  • Updated docs/graphs-tables.md, .github/skills/dashboard.md, CLAUDE.md, .github/copilot-instructions.md, README.md, setup.py long_description

🤖 Generated with Claude Code

timdegroot1996 and others added 3 commits September 14, 2026 03:28
Reimplements the exception-tracking feature from the stale PR #253 on a fresh
branch off main (5 months of drift made the original diff conflict in 10
files), using its diff as the spec rather than resolving merge conflicts.

- New ExceptionProcessor (processors.py): a ResultVisitor that tracks
  TRY/EXCEPT depth and records the message of the innermost failing keyword
  per TRY block (nested TRY, FOR-loops inside TRY, and keyword-wrapping-
  keyword cases all only count the leaf failure, not parents/ancestors).
- New `exceptions` SQLite table (queries.py, database.py): created for both
  fresh and legacy databases, inserted per-run, included in get_data(), and
  cleaned up in _remove_run() — all defensively tolerant of a missing table
  for custom database classes.
- New "Keyword Exceptions" graph (bar/timeline, keyword.js +
  graph_data/exceptions.js) and "Table Exception" (tables.js), wired through
  the existing graphMetadata-driven layout system — no changes needed to
  layout.js/graphs.js/settings.js since graph visibility and GridStack
  placement are fully data-driven from graphMetadata.js.
- filter.js: filteredExceptions flows through the same timezone/filter/sort
  pipeline as the other filtered arrays.

Validated end-to-end against a real Robot Framework suite exercising nested
TRY/EXCEPT, a FOR loop inside TRY, and a keyword wrapping another failing
keyword — exception counts matched hand-counted expectations exactly, the
`exceptions` table and dashboard HTML embed the right data, and the bundled
JS (extracted from the generated HTML) is syntax-clean with no duplicate
function declarations.

Tests: 30 new Python tests (ExceptionProcessor unit tests, database
insert/get/remove-run round-trips including a missing-table legacy-DB case,
dashboard placeholder embedding) and 10 new JS tests for
get_exceptions_data() (bar/timeline aggregation, sorting, limits, aliasing).
340 Python / 266 JS tests passing overall.

Docs: docs/graphs-tables.md, .github/skills/dashboard.md, CLAUDE.md,
.github/copilot-instructions.md, README.md, setup.py long_description.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
# Conflicts:
#	.github/copilot-instructions.md
#	CLAUDE.md
The new Exceptions tile makes the keyword statistics section taller than
the 1600px test viewport, so the page scrolled and the sticky navbar bled
into the element screenshot. Raise the viewport height to 2000px and
update the reference screenshot with the Linux-rendered result.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
@timdegroot1996
timdegroot1996 merged commit c08d50c into main 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.

[Feature Request] Track exception occurrences accros test runs

1 participant