Skip to content

test(verify): compare what the two paths produced - #8359

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

test(verify): compare what the two paths produced#8359
kz930 wants to merge 9 commits into
apache:mainfrom
kz930:feat/verify-compare-two-answers

Conversation

@kz930

@kz930 kz930 commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

What changes were proposed in this PR?

Two frames agree when they hold the same rows in the same order with the same
values, and the comparison says which of those failed rather than that they
differ. A float is compared within a tolerance, since the two paths reach the
same number by different arithmetic.

A visualization has no frame to compare at all. The two comparators that read
what one draws are in #8509.

Any related issues, documentation, discussions?

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

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

How was this PR tested?

The tests in this change cover it. The whole set is exercised together once the last piece lands: every operator run through the engine and through its generated script, and the two answers compared.

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

Generated-by: Claude Code (Opus 5)

Two frames agree when they hold the same rows in the same order with the same
values, and the comparison says which of those failed rather than that they
differ. A float is compared within a tolerance, since the two paths reach the
same number by different arithmetic.

A visualization has no frame to compare. What it emits is a figure, and the
meaning of a figure is in the numbers behind it, so the figures are compared
number by number; a plot that renders as an image is compared as the HTML it
emits instead.

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 2, 2026
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Automated Reviewer Suggestions

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

  • No candidates found from git blame history.

@codecov-commenter

codecov-commenter commented Sep 2, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.00%. Comparing base (7976744) to head (8fd71bc).
⚠️ Report is 35 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff              @@
##               main    #8359      +/-   ##
============================================
- Coverage     94.11%   94.00%   -0.11%     
- Complexity     4811     4862      +51     
============================================
  Files          1197     1204       +7     
  Lines         48813    49076     +263     
  Branches       5906     5948      +42     
============================================
+ Hits          45939    46135     +196     
- Misses         1420     1465      +45     
- Partials       1454     1476      +22     
Flag Coverage Δ *Carryforward flag
access-control-service 80.18% <ø> (-0.82%) ⬇️
agent-service 99.32% <ø> (ø) Carriedforward from 080f100
amber 90.08% <ø> (ø) Carriedforward from 080f100
computing-unit-managing-service 77.14% <ø> (+3.47%) ⬆️
config-service 87.12% <ø> (+0.12%) ⬆️
file-service 83.65% <ø> (-4.27%) ⬇️ Carriedforward from 080f100
frontend 96.86% <ø> (ø) Carriedforward from 080f100
notebook-migration-service 83.73% <ø> (+4.42%) ⬆️
pyamber 98.47% <ø> (ø) Carriedforward from 080f100
workflow-compiling-service 77.19% <ø> (ø) Carriedforward from 080f100

*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.

`read_json` infers a type per file, so a column one side wrote as "6" and the
other wrote as "6.0" both arrive as the number 6, and a null beside the text
"nan" both arrive as NaN. Two different answers compared as one, on every
string column of every operator.

The engine writes a schema beside its output naming which columns are strings,
and both sides are now read that way.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
kz930 added a commit to kz930/texera that referenced this pull request Sep 3, 2026
`astype(str)` gets three things wrong against `toString`: an empty cell
renders as the text "nan", a column holding one has become a float by then so
6 reads "6.0", and a boolean capitalises where the executor writes it lower.

The comparison could not see any of it until apache#8359 stopped inferring a type
per file, which is why a cast to STRING has been passing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Three kinds of comment came out. A drawing of the string the code below
assembles. A restatement of a branch the reader can see. And the word MVP,
which dated the scope to a moment rather than stating it.

What replaces them says the same thing shorter, or says what the code cannot:
which cases the harness does not drive and why none of them has an operator
asking for it.

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 result comparison looks good.

@kz930
kz930 marked this pull request as draft September 4, 2026 17:44
It ignores column order. Row order is settled by --unordered, which lex-sorts
both frames unless the operator declares itself order-sensitive.

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.

Reviewed alongside the related export and verification PRs. These findings are based on code inspection and focused Python checks, not a full Scala suite run.

Comment thread workflow-compiling-service/src/test/resources/python/compare.py Outdated
A requested column is one the engine declared as a model, so a side that
never emitted it is the divergence. Skipping it hid that: the column was
dropped from both frames afterwards and a path that produced no model at
all compared equal.

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.

Follow-up review of the series. Runtime findings were checked locally against the current code; deployment routing was checked from configuration.

The standalone script writes its page through Python's text mode, so on Windows
the file holds CRLF while the runtime path's JSONL carries the same markup with
LF. Five operators reported a mismatch that was only that. The line ending is
the platform writing the file rather than anything the operator chose, so it is
normalized away like the Styler uuid already is.

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.

Further review with local regression tests and connected execution checks.

Comment thread workflow-compiling-service/src/test/resources/python/compare.py
kz930 and others added 2 commits September 10, 2026 13:01
The comparison gave every numeric column the tolerance a double needs,
so two whole numbers a workflow would never call the same passed it: at
rtol=1e-5, LONG 100000 and 100001 compare equal. The declared integer
columns are split out and compared exactly; the rest keep the tolerance.

Reading them again is the other half. `read_json` parses a column
holding a null through float64, so 9007199254740993 is already
9007199254740992 before anything compares it, and pinning the dtype does
not help: the rounding happens on the way in. Python's json reads the
integer exactly. A value that is not whole in a column the engine
declared integral is itself the divergence, so it is reported.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
It restated its own signature and listed a codec table that lives in
TupleIO. The reasons a reader cannot derive stay.

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

kz930 commented Sep 11, 2026

Copy link
Copy Markdown
Contributor Author

@carloea2 all three are fixed: a missing model column now fails, line endings are normalized, and integer columns are compared exactly. Would you take another look when you have a moment?

The two chart comparators go to a change of their own. They answer a
different question and share no code with this one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature platform Non-amber Scala service paths

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Compare what the two paths produced

3 participants