typelevel / typelevel/scalacheck

Integer shrinking is less efficient than it could be.

Open
#735 7 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Scala
Stars
2k
Forks
393
Avg merge
6h 42m
Merged PRs (30d)
4

Description

See https://gist.github.com/jonaskoelker/4390fcc8bec868cd3b4f4ef43f29b830, in particular in run the sbt command testOnly DefaultShrinking -- -f triple and testOnly FancyShrinking -- -f triple to compare.

The current shrinking shrinks n to n/2, n/4, n/8, ..., interleaved with the negation of this stream. Ideally (I guess?) the shrinking process does a binary search for the smallest failing value. However, given that shrinking is restarted every time a failing example is found, the tail of the shrink stream is only looked at if running the test on the first shrink succeeds.

Thus, if we want to approximate a binary search, we can use the knowledge that prior shrinks succeeded to decide the next shrunk. In particular, I think 0, n - n/2, n - n/4, n - n/8, ... is a better stream of candidates (for positive n): it repeatedly bisects a range which is known to contain a boundary case until the next failure is found, at which point it repeats this effective search for a boundary value. (This is also, perhaps approximately, the integral-type shrinking used in rust-quickcheck.)

If you run the commands I mentioned above, you will see that my suggested shrinking reduces the failing example in fewer shrinks (easy to eyeball for small values of n) than the current built-in shrinker.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by running the sbt commands testOnly DefaultShrinking -- -f triple and testOnly FancyShrinking -- -f triple from the issue, using the linked gist as context. Trace the built-in integer shrinker and compare how many shrinks each case needs. Done means the proposed candidate sequence is implemented and the comparison demonstrates fewer shrinks without breaking existing shrinking behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
scala
Domain
testing-qa
Issue type
Feature
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.