-
Notifications
You must be signed in to change notification settings - Fork 39
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
Proof of concept: allow Debug.log in fuzz tests #156
base: master
Are you sure you want to change the base?
Conversation
…prints when testing the final shrunken value is actually printed to stdout
@@ -128,6 +144,10 @@ findSimplestFailure (Rose failingValue branches) getExpectation oldExpectation = | |||
|
|||
-- base case: we cannot simplify any more | |||
Nothing -> | |||
let | |||
_ = | |||
getExpectation { log = Debug.log } failingValue |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would we want to let the test runner hook into this in someway, so that it can provide a custom logging function? I guess this would require the function to return a Cmd
(for port logging) so may not be possible.
This is really cool! |
imo this puts an extremely high burden on the user... it seems like if they wanted to log something in their code, they would have to thread through the meta.log function all the way down to wherever they want to actually log something, or am I missing something about what this does or where it's headed? I wonder if there's a way to change the test runner to be able to do this without having to change the public API and put the burden on the user to learn a new way of logging for fuzz tests. |
I guess the alternative is a |
The javascript test runner ava uses a logging function passed to each test when it is run (like we do in this PR) so there is precedent for @drathier's approach. |
Is there a way to make it work without the user having to do anything special? elm-test controls the execution environment of each test, so I'd expect there'd be a way for it to set up Wasn't there also some discussion about being able to capture the console logs for each test so that any output can be put next to the correct error message? If that were done, then wouldn't this basically be solved as well, as the console output for any individual run could be discarded at the runner's (in this case the fuzz test module's) discretion? |
Yeah, this is the pure fp approach, but we do have kernel code available so we could have a collection mechanism for this instead, if the test runner does the actual collection, or replaces the js implementation of Debug.log. I prefer a non-pure approach, because it just works. |
How about this then? We try to gather up log prints using help from kernel code and the test runner.
|
Could we have an internal API like capture: (a -> b) -> { output: b, logs: List (String, String) } function _Test_capture(func) {
assert(__Debug_divertLogsTo === null);
_Debug_divertLogsTo = [];
var output = func();
var logs = __Debug_divertLogsTo ;
__Debug_divertLogsTo = null;
return {
__$output: output,
__$logs: logs
};
} Although this API would require a patch to |
1 similar comment
Could we have an internal API like capture: (a -> b) -> { output: b, logs: List (String, String) } function _Test_capture(func) {
assert(__Debug_divertLogsTo === null);
_Debug_divertLogsTo = [];
var output = func();
var logs = __Debug_divertLogsTo ;
__Debug_divertLogsTo = null;
return {
__$output: output,
__$logs: logs
};
} Although this API would require a patch to |
That sounds good, yes. We should probably disable Debug.log outside of this function, just passing through values without printing or logging them, for performance reasons. |
If someone is logging outside of a test (I guess the only way to do this is to have log statements in the code that runs on load) then I think we should not do anything special with those logs. |
When generating the log output for fuzz tests we'd do this:
Steps 1 and 2 would generate a ton of unneeded log output and performance would be really bad. I'm expecting people to add log statements to their tests and just leave them in, expecting them to have zero performance impact on successful tests. That's at least how I would want to treat them. |
Would what you are suggesting work as the following two APIs? suppressLogs: (a -> b) -> b
captureLogs: (a -> b) -> { output: b, logs: List (String, String) } |
It could, yes |
To solve the problem of people leaving logging in tests forever, you could mark tests containing logging as pending rather than passed. |
Is it a problem if people leave logging in tests forever? |
Why not let them leave the logging in? |
What's the point of logging that exists just to get discarded? |
What is the point of a test that doesn't fail? I guess the idea is that you can put logging in your tests and then debugging a test failure becomes much easier because the failure message comes with log messages. |
Just to chip in on the discussion. In elm-test-rs capturing calls to It works well for unit tests, but isn't much useful with the huge amount of logging in fuzz tests. Having an alteration of the log function that would deactivate it except for the shrinked pass would be awesome. |
Proof of concept! Allow Debug.log to be used effectively in fuzz tests.
Idea: pass an extra argument to all fuzzer test functions
{ log : String -> a -> a }
. This function is a no-op until we've found the simplest failing test case. The we run that simplest test case with a record that contains the real Debug.log function. Since it inherently works with side-effects, we can't easily capture and re-print stdout.Fuzz tests:
Output: