hedgehogqa / haskell-hedgehog

Release with confidence, state-of-the-art property testing for Haskell.
677 stars 107 forks source link

Provide a `check` function that does not use `displayRegion` #236

Open ProofOfKeags opened 5 years ago

ProofOfKeags commented 5 years ago

It'd be nice if there was a way to run check such that it didn't overwrite all my terminal output. I think that using these display regions by default is perfectly reasonable but I guess I had somewhat hoped there was a way to opt out of terminal overwriting for the case when you're debugging a test.

Some sort of function like checkNoReport that doesn't actually do any of the display region stuff

The use case here is primarily for running the test in ghci such that you can reliably see the log output without it getting overwritten by the reporting mechanism

moodmosaic commented 5 years ago

such that you can reliably see the log output without it getting overwritten by the reporting mechanism

What do you mean exactly?

ProofOfKeags commented 5 years ago

If any of the functions under test by hedgehog have any log output, regardless of whether it is trace or $logInfo or the like, it gives unreliable log output because the reporting mechanism uses display regions rather than just regular stdout logging. This causes it to overwrite some of the log output generated by your code under test.

This is less of a problem for the test itself because you can just footnote or annotate in the test, but if any of the functions in the test are themselves generating log output, it will be overwritten by the test report.

This is fairly easily reproducible by the following:

  1. open up GHCI with the tests and function
  2. add some logging to one of the functions you want to test
  3. check $ withTests 1 $ <the test you want to run>
  4. observe mangled log output
HuwCampbell commented 5 years ago

I haven't used it personally, but do you think something like silently would solve your problem?

moodmosaic commented 5 years ago

Yeah, I assume that's exactly what silently does. Even though it's under the Hspec umbrella, it's standalone so it can be used with other testing systems as well.

ProofOfKeags commented 5 years ago

would silently mute all output or just the output generated by check. It seems like if it mutes all output it doesn't really answer this particular issue.

HuwCampbell commented 5 years ago

The point of silently is that the IO functions inside your test can be silenced or captured. You can then, if you choose, use that output as an annotation in the case or failure.

So you can do something like:

import System.IO.Silently (capture)
import Hedgehog

loud = putStrLn "hi" >> return (2 + 4)

x = property $ do
  (hi, sum) <- liftIO . capture $ loud
  annotate hi
  sum === 5
moodmosaic commented 5 years ago

What @HuwCampbell suggests should work. For sure though we ought to put some more on the README or even introduce some docs thing.

ProofOfKeags commented 5 years ago

Understood, this makes more sense now.

joelburget commented 5 years ago

This solution looks great for cases where you're actually printing in IO. Unfortunately I don't see how to use silently to fix trace output.

HuwCampbell commented 5 years ago

I would imagine that using evaluate from Control.Exception to run the action in IO may help.