Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create CursorTest harness #227

Merged
merged 10 commits into from
Dec 22, 2024
Merged

Create CursorTest harness #227

merged 10 commits into from
Dec 22, 2024

Conversation

PoignardAzur
Copy link
Contributor

This is a long-awaited feature, letting us write user-friendly tests of Parley's cursor behavior.

Copy link
Member

@tomcur tomcur left a comment

Choose a reason for hiding this comment

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

Really good to see this progress. I think the main concern raised in the Zulip thread is whether terminal output can work well enough for all the errors that may need to be reported.

One possibility is to just debug-print the actual and expected cursors for now.

I think spanning selections should also be in scope for testing, but that can be done later.

@PoignardAzur
Copy link
Contributor Author

One possibility is to just debug-print the actual and expected cursors for now.

The PR already does.

@PoignardAzur
Copy link
Contributor Author

image

@tomcur
Copy link
Member

tomcur commented Dec 11, 2024

I mean only debug-printing the cursor structs to the terminal: printing a report to the terminal as in the screenshot may not be possible for all the layouts that are interesting to test selection for (RTL text, very long lines, line breaks). A report like that is very useful to have though, perhaps something very similar could be rendered to an image.

parley/src/cursor_test.rs Outdated Show resolved Hide resolved
parley/src/cursor_test.rs Outdated Show resolved Hide resolved
parley/src/cursor_test.rs Outdated Show resolved Hide resolved
Comment on lines 162 to 165
// TODO - Check that the tested string doesn't include difficult
// characters (newlines, tabs, RTL text, etc.)
// If it does, we should still print the text on a best effort basis, but
// without visual cursors and with a warning that the text may not be accurate.
Copy link
Member

Choose a reason for hiding this comment

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

As discussed on Zulip, the alternative/fallback is to do screenshots. I'd suggest that we should have screenshots unconditionally if this fails, and show the in-terminal version if there is no RTL region (we should strive to handle newlines properly, and we can't possibly detect non-tab extra-wide terminal characters so it's not worth trying)

This doesn't need to happen in this PR, but it might be worth leaving these breakcrumbs in the code

///
/// Uses the same format as assertion failures.
#[track_caller]
pub fn print_cursor(&self, cursor: Cursor) {
Copy link
Member

Choose a reason for hiding this comment

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

Hmm, this is a bit harder to have with screenshots for debugging. I suppose we can't know if a test will fail until it fails. We could queue these up?

Not a problem for this PR to solve.


#[test]
fn cursor_next_visual() {
let (mut lcx, mut fcx) = (LayoutContext::new(), FontContext::new());
Copy link
Member

Choose a reason for hiding this comment

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

Ideally this would use the build-in Roboto font, but of course it doesn't really matter what font is chosen, so long as it is not fundamentally misbehaving

Copy link
Member

Choose a reason for hiding this comment

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

Actually of course it matters, for "up/down" button pressing test cases

Copy link
Member

@tomcur tomcur Dec 11, 2024

Choose a reason for hiding this comment

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

Hmm does the font really not matter? Edit: you replied one second before my comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think we shouldn't worry about up-down testing for now, until we have a UI for tests with multi-line strings.

Like, yes, in theory we could just stick to comparing the numeric values of cursors, but if we want to do that we don't need this PR at all, just assert_eq.

@@ -124,6 +125,7 @@ pub use peniko::Font;

pub use builder::{RangedBuilder, TreeBuilder};
pub use context::LayoutContext;
pub use cursor_test::CursorTest;
Copy link
Member

Choose a reason for hiding this comment

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

What is the advantage of making this public?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For writing tests for something like the text editor widget in Masonry. We can always stop exporting it in future versions if we find nobody uses it.

Copy link
Member

Choose a reason for hiding this comment

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

I can't imagine a user story which would want this exported in its current form, but I can imagine that some of this code would be useful if made more modular.

I do think that the publicly exported "get the debug print of a cursor from the text and its corresponding layout" could be useful (where the layout is used only to find the soft line breaks in the text for debug printing) - caveated of course that it's a best effort. However, if we were actually doing that, we'd probably also want to properly use unicode_width, which I'm not sure we want to do. As it currently stands, this functionality is also tied in with the constructor creating the layout, which is pretty far from ideal.

The "quickly create a cursor from a needle in a string" is also useful to export publicly for people testing e.g. rich text, but again I think it's conflated with the other stuff.

@PoignardAzur
Copy link
Contributor Author

The CI is blowing up. Not sure where these errors are coming from.

@PoignardAzur
Copy link
Contributor Author

To re-iterate what was mentioned in Office Hours:

The purpose of this PR is to be able to write tests for cursor values where the intent of the test can be understood by reading the code of the test alone. This is in contrast to tests where you compare the cursor to a numeric value (the reader needs to visualize what position the number represents) and screenshot tests (the reader needs to open the screenshot file).

In future versions of this API, we'll probably dump screenshots directly to the console where possible, or other similar tricks.

The important part is that in any tests we write, readers should understand the intent of the test form the code alone.

@DJMcNab
Copy link
Member

DJMcNab commented Dec 13, 2024

The purpose of this PR is to be able to write tests for cursor values where the intent of the test can be understood by reading the code of the test alone.

Again, I agree entirely that we should have this, and I agree that the "needle" based API achieves this very cleverly and unambiguously. But I still don't believe that this infrastructure as provided can possibly be useful for external users, and so we shouldn't export it.
I'd happily approve as-is if this new code were in the test utils module or otherwise cfg(test)ed.

@PoignardAzur
Copy link
Contributor Author

But I still don't believe that this infrastructure as provided can possibly be useful for external users, and so we shouldn't export it.

Do you think there's a downside to exporting it, besides potential confusion?

The obvious downside would be that people might end up depending on it and be upset if we remove it later, but if you think this will never be useful to external users, then that doesn't really apply.

I'd be in favor of exporting it, maybe with a feature flag or a #[doc(hidden)] attribute, and if 6 months later we find out nobody uses it we can make it private again.

@DJMcNab
Copy link
Member

DJMcNab commented Dec 13, 2024

I strongly agree that some of these features would be useful for someone creating their own editor or similar on top of Parley's primitives. Using a needle to create a cursor is brilliant, nicely simple code but very clear.

However, I'm still really struggling to imagine a user story for someone who would use what you are proposing we export - as this only exposes those features in a very straitjacketed way. I feel that I must be missing something fundamental here.
As far as I can tell, the only possible tests which can be written using this API are for moving a (single) cursor in different ways in entirely plain text - currently on one line, but in the future across many lines. However, the implementations of all the reasonable operations you would want to have (and if we've missed any, it's our bug) live in this crate, and so should be tested here, not by our external users.

My earlier conditional approval still stands. I'm not going to block this if someone else approves.

@PoignardAzur
Copy link
Contributor Author

I've made the implementation private again, and added some TODOs for future reference.

@@ -1,6 +1,9 @@
// Copyright 2024 the Parley Authors
// SPDX-License-Identifier: Apache-2.0 OR MIT

// TODO - Figure out which tests can run without std
Copy link
Member

Choose a reason for hiding this comment

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

Hmm, why do we want this? Afaik, we only enable no_std when not running tests.

Copy link
Contributor

Choose a reason for hiding this comment

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

IIRC, the test runner itself requires std so tests are always run with std regardless of whether you enable it anyway.

@PoignardAzur PoignardAzur added this pull request to the merge queue Dec 22, 2024
Merged via the queue into main with commit 65e4c7f Dec 22, 2024
20 checks passed
@PoignardAzur PoignardAzur deleted the test_api branch December 22, 2024 15:33
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.

5 participants