Skip to content

test(verify): compare the charts the two paths drew - #8509

Draft
kz930 wants to merge 8 commits into
apache:mainfrom
kz930:feat/verify-compare-two-charts
Draft

kz930 wants to merge 8 commits into
apache:mainfrom
kz930:feat/verify-compare-two-charts

Conversation

@kz930

@kz930 kz930 commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

What changes were proposed in this PR?

A visualization operator produces no table, so the table comparison has nothing to read. It writes a plotly figure and an HTML page, and this compares those.

A chart's meaning is in the numbers behind it, so the comparison reads those rather than the rendered picture, which would fail over a layout detail that carries none. The figure is compared trace by trace.

The page needs two things normalized away first, neither of which is markup the operator chose: a Styler id, which pandas regenerates on every run, and the line ending, which on Windows is CRLF for a file Python opened in text mode while the same markup carried through JSONL keeps the LF the engine wrote.

#8359 compares two tables, which is a different question and shares no code with this one.

Any related issues, documentation, discussions?

Part of #8325, 7 of 27; that issue lists the set in order.

Closes #8508, the task this change is the whole of.

How was this PR tested?

VisualizationHtmlComparatorSpec pins both normalizations: two pages differing only in a Styler id compare equal, and so do two differing only in line endings, while a page differing in the markup itself does not.

Was this PR authored or co-authored using generative AI tooling?

Generated-by: Claude Code (Claude Opus 5)

🤖 Generated with Claude Code

A chart's meaning is in the numbers behind it, so the comparison reads
those rather than the rendered picture, which would fail over a layout
detail that carries none. Plotly writes both a JSON figure and an HTML
page, and each needs its own reading: the figure is compared trace by
trace, and the page has a Styler id regenerated per run and a line ending
chosen by whichever platform wrote the file, neither of which is markup
the operator chose.

Split out of apache#8359 on review. That change compares two tables, which is a
different question and shares no code with this one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added feature platform Non-amber Scala service paths labels Sep 11, 2026
@github-actions

github-actions Bot commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

Automated Reviewer Suggestions

Based on the git blame history of the changed files, we recommend the following reviewers:

  • Contributors with relevant context: @mengw15
    You can notify them by mentioning @mengw15 in a comment.

@codecov-commenter

codecov-commenter commented Sep 11, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.51%. Comparing base (1fbd346) to head (739b316).
⚠️ Report is 83 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff              @@
##               main    #8509      +/-   ##
============================================
- Coverage     93.69%   92.51%   -1.19%     
- Complexity     4826     4922      +96     
============================================
  Files          1209     1223      +14     
  Lines         49871    51029    +1158     
  Branches       6099     6254     +155     
============================================
+ Hits          46727    47208     +481     
- Misses         1652     2258     +606     
- Partials       1492     1563      +71     
Flag Coverage Δ *Carryforward flag
access-control-service 77.38% <ø> (-2.81%) ⬇️
agent-service 99.32% <ø> (ø) Carriedforward from e47995c
amber 88.59% <ø> (-1.33%) ⬇️ Carriedforward from e47995c
computing-unit-managing-service 60.41% <ø> (-16.74%) ⬇️
config-service 87.37% <ø> (+0.24%) ⬆️
file-service 81.53% <ø> (-2.12%) ⬇️ Carriedforward from e47995c
frontend 96.16% <ø> (ø) Carriedforward from e47995c
notebook-migration-service 83.73% <ø> (ø)
pyamber 98.47% <ø> (ø) Carriedforward from e47995c
workflow-compiling-service 74.09% <ø> (-3.10%) ⬇️ Carriedforward from e47995c

*This pull request uses carry forward flags. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

kz930 and others added 2 commits September 12, 2026 00:51
The uuid pattern matched anywhere in the page, so two tables whose cells
read T_dead and T_beef compared equal and a real difference in exported
data went unreported. Replace the uuid only where a Styler writes it, in
the id attribute and the selector that targets it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A cell is not escaped, so a value reading `#T_dead` looked like a CSS
selector and two tables disagreeing about it still compared equal. The
uuid is now replaced inside the `<style>` element and inside tags, which
is everywhere a Styler writes one and nowhere the table speaks.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@carloea2

Copy link
Copy Markdown
Contributor

There is also a build dependency missing in this PR: VisualizationJsonComparator imports PythonWorkerPool from WorkflowOperator test sources, but WorkflowCompilingService does not depend on those test classes. The current CI job fails to compile that import. Please include the test dependency here so this PR builds independently. CI: https://github.com/apache/texera/actions/runs/34804943402/job/103854922027

VisualizationJsonComparator reuses PythonWorkerPool, which lives in
workflow-operator's test sources, so the module needs it in test scope.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@kz930

kz930 commented Sep 14, 2026

Copy link
Copy Markdown
Contributor Author

Good catch, thanks. Added the test-scope dependency in dfa14dc, so the PR builds on its own now. The same line is in #8357 with identical wording, so the two merge without a conflict.

@github-actions github-actions Bot added dependencies Pull requests that update a dependency file common labels Sep 14, 2026
@github-actions

github-actions Bot commented Sep 14, 2026 •

Copy link
Copy Markdown
Contributor

✅ No material benchmark regressions detected

🟢 2 better · 🔴 0 worse · ⚪ 13 noise (<±5%) · 0 without baseline

Compared against main fd09f20 benchmarked on this same runner, so the delta is largely free of cross-runner hardware noise. The "7d avg" column still reflects the gh-pages dashboard. Treat <±5% as noise unless repeated.

Dashboard · Run

config throughput MB/s latency max Δ latest / 7d
⚪ bs=10 sw=10 sl=64 395 0.241 25,189/35,311/35,311 us ⚪ within ±5% / 🔴 +107.1%
🟢 bs=100 sw=10 sl=64 822 0.502 121,227/138,640/138,640 us 🟢 -8.6% / 🔴 +20.4%
⚪ bs=1000 sw=10 sl=64 917 0.56 1,091,858/1,151,883/1,151,883 us ⚪ within ±5% / ⚪ within ±5%
Baseline details

Latest main fd09f20 from same runner

config metric PR latest main 7d avg Δ latest Δ 7d
bs=10 sw=10 sl=64 throughput 395 tuples/sec 405 tuples/sec 721.84 tuples/sec -2.5% -45.3%
bs=10 sw=10 sl=64 MB/s 0.241 MB/s 0.247 MB/s 0.441 MB/s -2.4% -45.3%
bs=10 sw=10 sl=64 p50 25,189 us 24,062 us 13,416 us +4.7% +87.8%
bs=10 sw=10 sl=64 p95 35,311 us 36,550 us 17,046 us -3.4% +107.1%
bs=10 sw=10 sl=64 p99 35,311 us 36,550 us 20,349 us -3.4% +73.5%
bs=100 sw=10 sl=64 throughput 822 tuples/sec 812 tuples/sec 914.39 tuples/sec +1.2% -10.1%
bs=100 sw=10 sl=64 MB/s 0.502 MB/s 0.496 MB/s 0.558 MB/s +1.2% -10.1%
bs=100 sw=10 sl=64 p50 121,227 us 121,558 us 108,507 us -0.3% +11.7%
bs=100 sw=10 sl=64 p95 138,640 us 151,607 us 115,131 us -8.6% +20.4%
bs=100 sw=10 sl=64 p99 138,640 us 151,607 us 127,181 us -8.6% +9.0%
bs=1000 sw=10 sl=64 throughput 917 tuples/sec 915 tuples/sec 937.6 tuples/sec +0.2% -2.2%
bs=1000 sw=10 sl=64 MB/s 0.56 MB/s 0.558 MB/s 0.572 MB/s +0.4% -2.1%
bs=1000 sw=10 sl=64 p50 1,091,858 us 1,100,041 us 1,065,461 us -0.7% +2.5%
bs=1000 sw=10 sl=64 p95 1,151,883 us 1,181,939 us 1,107,736 us -2.5% +4.0%
bs=1000 sw=10 sl=64 p99 1,151,883 us 1,181,939 us 1,133,556 us -2.5% +1.6%
Raw CSV
config_idx,batch_size,schema_width,string_len,num_batches,total_ms,total_tuples,total_bytes,tuples_per_sec,mb_per_sec,lat_p50_us,lat_p95_us,lat_p99_us
0,10,10,64,20,506.96,200,128000,395,0.241,25189.19,35310.87,35310.87
1,100,10,64,20,2433.05,2000,1280000,822,0.502,121226.92,138639.83,138639.83
2,1000,10,64,20,21798.41,20000,12800000,917,0.560,1091857.95,1151883.44,1151883.44

@carloea2 carloea2 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The HTML ID handling now preserves cell text. The comparator tests look good.

@carloea2 carloea2 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The HTML comparison reads only the first nonempty runtime row. If native returns HTML A and B but standalone returns only A, this still passes. Visualization operators can emit one HTML result per input row. Please compare every row and add a multirow case.

The comparison read the first row of the runtime path's output and stopped,
so a run that drew a chart the exported script never drew still passed. The
two sides are now compared as sequences, and the failure says how many each
path drew and what the unmatched one held.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@kz930

kz930 commented Sep 18, 2026

Copy link
Copy Markdown
Contributor Author

Fixed in fe7ac26: the two sides are compared as sequences now, so a run that drew a chart the exported script never drew fails instead of passing on its first row, and the message says how many each path drew. The multirow case is in, with the second chart named in the failure.

@carloea2 carloea2 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The HTML comparison now checks every runtime row and rejects a missing extra result. The earlier finding is fixed. Looks good.

kz930 and others added 2 commits September 18, 2026 15:52
The comparison had no spec of its own, and the case worth holding is the
multi-figure one: an operator that draws a figure per input row agrees on
the first long after it has stopped agreeing, so a comparison that read one
figure and stopped called that a match. A figure the other path drew
differently, and one it never drew at all, are each their own test.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The comparison says "the run drew 2 and the exported script drew 1" where the
assertion was still reading the wording this spec was written against.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@carloea2 carloea2 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The added figure comparison tests cover the revised chart handling. No new blocker found.

…own spec

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

common dependencies Pull requests that update a dependency file feature platform Non-amber Scala service paths

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Compare the charts the two paths drew

3 participants