Skip to content

Move .spy playground files in examples and test all examples#481

Open
paugier wants to merge 5 commits intospylang:mainfrom
paugier:playground-examples
Open

Move .spy playground files in examples and test all examples#481
paugier wants to merge 5 commits intospylang:mainfrom
paugier:playground-examples

Conversation

@paugier
Copy link
Copy Markdown
Contributor

@paugier paugier commented Apr 22, 2026

Fixes #416

@paugier paugier marked this pull request as draft April 22, 2026 14:30
@paugier paugier force-pushed the playground-examples branch 2 times, most recently from cc5ef8e to de97778 Compare April 22, 2026 14:59
@paugier paugier marked this pull request as ready for review April 22, 2026 15:07
@paugier paugier changed the title draft: Move .spy playground files in examples and test all examples Move .spy playground files in examples and test all examples Apr 22, 2026
@paugier
Copy link
Copy Markdown
Contributor Author

paugier commented Apr 22, 2026

This is a first step but it might be enough for now. At least, it can be useful to have feedback on this strategy.

Copy link
Copy Markdown
Member

@antocuni antocuni left a comment

Choose a reason for hiding this comment

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

thank you a lot for this!
I generally like the approach and I'm super happy to add this functionality.
I have added some minor comments.

One additional discussion point: have you considered to embed the expected output directly in the example files? Something like this:

def main() -> None:
    print("hello")

# ==== expected output ====
# hello

This would make the update logic slightly more complex but it has the advantage of avoiding creating a lot of new tiny files.

I'm not 100% sure it's a good idea though, happy to hear your thoughts about it

@@ -0,0 +1,2 @@
20
<spy struct _dict::dict[i32, i32]::_dict({'__ll__': W_Ptr('gc', _dict::dict[i32, i32]::DictData, 0x1001460, length=1)})>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this is a bit fragile (we should have a better repr for the dict, but that's a different story) because it contains a hardcoded address, which happens to be always the same because malloc on WASM is very deterministic.

If we want to be more robust, we probably want to support some kind of regexp/glob syntax in these "expected" files.

Anyway, not a big deal and not a merge blocker, just something to keep in mind for the future.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done with a regexp (line = re.sub(r"0x[0-9a-fA-F]+", "<ADDR>", line)).

Comment thread examples/test_examples.py
expected_file.read_text()
), (
f"Output of {spy_file.name} differs from {expected_file.relative_to(EXAMPLES_DIR)}"
)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

could you use spy.util.print_diff to print a readable diff here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

Comment thread examples/update_expected_output.py Outdated
python examples/update_expected_output.py

After running, review the diff and commit the updated files.
"""
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this works, but I propose a different UI.
What about introducing an option pytest --update-examples or similar?

This way:

  1. by default, test_example checks the output against the expected output
  2. with --update-examples, it SAVES the new expected output

This has some nice properties like the builtin ability to update only a single test by using pytest standard filtering mechanism.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I did that and I agree it's better!

@@ -0,0 +1,3 @@
argv:
/home/users/augier3pi/dev/spy/examples/exit_code.spy
exit code: 88
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

how is it possible that this test passes in CI? Doesn't it print a different path? 🤔

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The tests were not run in the CI because of

 [tool.pytest.ini_options]
testpaths = ["spy"]

I added an explicit step in the CI for the examples.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Note that I didn't change testpaths = ["spy"], meaning that just running pytest in the root directory does not run the examples. It seems to me that it is a reasonable behavior. To run the example tests locally:

pytest examples
# or
cd examples
pytest

0
1
4
9
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think it's fine to modify the example to print less numbers here :)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

@paugier paugier force-pushed the playground-examples branch from de97778 to 16e3c6e Compare May 3, 2026 04:00
@paugier
Copy link
Copy Markdown
Contributor Author

paugier commented May 3, 2026

One additional discussion point: have you considered to embed the expected output directly in the example files?

I don't love the idea. I think the advantage (avoiding few small files in examples/expected_output) is not that interesting. This is only one file per examples, and I don't see how these files would cause any issue to anyone.

Then I thought about the "advantage" of having the expected output directly in the examples in terms of pedagogy. However, it is not a very nice way to present the output, in particular when the examples will be used in the doc. We could of course trim this part for the doc but it seems to me that it's going to be hacky.

It is also not unreasonable to have in future examples with relatively long and not very interesting output, which is not a problem if the output is not embedded in the source file.

Therefore, I propose that we keep it simple with standard golden files in examples/expected_output. Would it be fine for you?

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.

Playground examples should be tested

2 participants