spot icon indicating copy to clipboard operation
spot copied to clipboard

existsOnce incredibly slow

Open josh-burton opened this issue 6 months ago • 2 comments

I have an existing testsuite comprehensively using patrol, e.g.

await $(key).waitUntilVisible();

Tests run nice and quick.

Now that I'm starting to implement spot I'm replacing these patrol widget assertions with spot:

spot<Widget>().spotKey(key).existsOnce()

The same test now takes 50seconds to run instead of 500ms.

I've tracked the issue down to the snapshot.dart _tryMatchingLessSpecificCriteria function, specifically this line: https://github.com/passsy/spot/blob/257dfaec2afec635b665b83682977a5b5045302e/lib/src/spot/snapshot.dart#L776-L781

This particular test has 707 less specific matches, and calls toStringDeep on each one. This results in an extremely large error string that chokes IntelliJ or the cli (IntelliJ is much slower than via cli).

Changing toStringDeep to to String solves the problem, but is not super useful output. A good fix could be to only display possible matches when there are 5-10 possible matches?

I'm also wondering if a search for less specific widgets should even be run here. The particular key I'm matching on is a valuekey of string. Would anything less specific than that essentially be the entire widget tree?

josh-burton avatar Jun 16 '25 21:06 josh-burton

Good catch! I can reproduce it.

Multiple solutions pop into my mind:

  • limit the output to 10ish elements.
  • Check the output length of errorBuilder, and stop after ~2k lines or something like that.
  • Do not suggest less specific widgets when selector basically finds all widgets (first less specific search == rootView)
  • After printing a part of a widget tree, ignore all already printed widgets (nested) in the results. After the rootView print, everything else would be ignored.

Unfortunately, I don't see a workaround without a new release for you immediately.


btw, spot<Widget>().spotKey(key).existsOnce() is equal to spotKey(key).existsOnce(). The additional spot<Widget>() requires more computation but is not really measureable

passsy avatar Jun 18 '25 01:06 passsy

Ah thanks for the tip!

I think the solution should be both of :

  • limit the output to 10ish elements
  • Do not suggest less specific widgets when selector basically finds all widgets (first less specific search == rootView)

josh-burton avatar Jun 18 '25 04:06 josh-burton