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

Add debugging mode so arbitraries are easier to understand in the Java debugger #330

Open
vlsi opened this issue May 16, 2022 · 6 comments

Comments

@vlsi
Copy link
Contributor

vlsi commented May 16, 2022

Testing Problem

Understanding the nature of Arbitrary, Combinator, etc in the runtime debugger is hard since the classes provide virtually no information that users can relate to the source code.

It is hard to debug exceptions coming from Arbitratries, and it is hard to understand the contents of Java debugger.

Suggested Solution

Add a mode where ArbitraryImpl, Combinator, etc would capture stacktrace (or just the most top frame excluding certain library-specific ones), so Arbitrary#toString could provide the source code location where the arbitrary was created.

An additional or alternative approach could be adding displayName or something like that to Arbitrary, Combiner, so users could provide meaningful names.

There's a similar case in Google Guice. When Guice identifies a configuration error, it attempts to provide the exact line in the user code which triggered the error. They do that by adding their own stacktrace filtering: https://google.github.io/guice/api-docs/latest/javadoc/com/google/inject/Binder.html#skipSources(java.lang.Class...)

Discussion

Collecting stack traces always might be time-consuming, so I suggest adding a feature flag.
I'm not sure if there's a good way to require displayName from the end-user without redoing all the jqwik API.

JavaScript treats .displayName for naming "anonymous functions" for quite some time now: https://bugs.chromium.org/p/chromium/issues/detail?id=17356, https://rreverser.com/gh-stack-displayname/

@vlsi
Copy link
Contributor Author

vlsi commented May 16, 2022

A relavant issue: net.jqwik.engine.properties.arbitraries.randomized.IgnoreExceptionGenerator@4e4395c missed more than 10000 times.

@vlsi
Copy link
Contributor Author

vlsi commented May 18, 2022

My current workaround for "missed more than 10000 times" is to add maxMisses parameter with a random (hard-coded) value, so when I see Filtering [net.jqwik.api.RandomGenerator$$Lambda$497/0x000000080042a440@6391b276] missed more than 934 times I can check for 934 in my code.

@jlink
Copy link
Collaborator

jlink commented Jun 3, 2022

Add a mode where ArbitraryImpl, Combinator, etc would capture stacktrace (or just the most top frame excluding certain library-specific ones), so Arbitrary#toString could provide the source code location where the arbitrary was created.

That means it would have to be captured on each creation of an arbitrary, right? And then the (potentially filtered) stack trace used in toString()? Quite some overhead so using a property attribute with a default would definitely be required.

@vlsi
Copy link
Contributor Author

vlsi commented Jun 3, 2022

That means it would have to be captured on each creation of an arbitrary, right? And then the (potentially filtered) stack trace used in toString()?

Exactly.

Quite some overhead

That is why I think it should be disabled by default, and it should be activated on demand only, or only when jqwik detects a failure.

For instance, if jqwik is about to print the final results, it might re-execute the test with debugging mode, so the output stacktrace is easier to understand.

@jlink
Copy link
Collaborator

jlink commented Jun 3, 2022

An additional or alternative approach could be adding displayName or something like that to Arbitrary, Combiner, so users could provide meaningful names.

Something like that has been in my backlog for a while. There're two reasons that I've refrained from doing it:

  • It would require an implementation for each and every arbitrary to be useful
  • Some interesting stuff just cannot be captured at runtime, like the concrete type of a type variable or the actual predicate of a filtering lambda. So the description string would only be so useful.

@jlink
Copy link
Collaborator

jlink commented Jun 3, 2022

For instance, if jqwik is about to print the final results, it might re-execute the test with debugging mode, so the output stacktrace is easier to understand.

It wouldn't even have to re-execute the full property, just the arbitrary creation phase should suffice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants