-
Notifications
You must be signed in to change notification settings - Fork 119
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
Combining shrinking with resource usage is seemingly unsupported. #331
Comments
It's unclear to me what module Main where
import Test.QuickCheck
import Control.Concurrent.STM
main :: IO ()
main = do
var <- newTVarIO True
let withTrue func = do
atomically $ writeTVar var True
r <- func
atomically $ writeTVar var False
pure r
quickCheck $ forAllShrink (sized $ \ n -> pure n ) shrink $ \i -> ioProperty $ withTrue $ do
b <- readTVarIO var
if b
then return (i < 20)
else return (error "Invariant violated?") -- this should never happen, do I understand right? I get
which is expected failure, isn't it? |
@phadej quickcheck/src/Test/QuickCheck/Property.hs Line 164 in 2dcfbf6
That's not a solution but at least it's not bugged. This is what hspec does: |
For the record: I just spent a few minutes trying to "just" get rid of that |
I'm not sure what you mean by "properties don't use any resources while they are being tested", but at least I can try to describe the situation. The call to At the user level we have (as you noted) What you would of course like is for
Here, |
Just to be more explicit, here QuickCheck is able to shrink the counterexample (note the "2 shrinks" below): module Main where
import Test.QuickCheck
import Control.Concurrent.STM
main :: IO ()
main = do
var <- newTVarIO True
let withTrue func = do
atomically $ writeTVar var True
r <- func
atomically $ writeTVar var False
pure r
quickCheck $ \i -> ioProperty $ withTrue $ do
b <- readTVarIO var
if b
then return (i < 20)
else return (error "Invariant violated?") -- this should never happen, do I understand right?
> main
*** Failed! Falsified (after 27 tests and 2 shrinks):
20 |
Thank you this has been really helpful already. This So what I want to have happen is something like:
(Here the "start server" and "stop server" would be supplied as a When implementing a testing framework like runPropertyTestWithArg ::
(outerArgs -> innerArg -> Property) ->
TestRunSettings ->
((outerArgs -> innerArg -> IO r) -> IO r) ->
IO TestRunResult Here the first argument is the function that produces the property under test.
Because we just get a EDIT: I would be happy to go into detail on a video call if that would help! I'm a very big user of QuickCheck and I care deeply about property testing so I hope I can help. |
For the record, I tried rewriting my
|
Yes, I think so. The way About the function you want to implement: runPropertyTestWithArg ::
(outerArgs -> innerArg -> Property) ->
TestRunSettings ->
((outerArgs -> innerArg -> IO r) -> IO r) ->
IO TestRunResult Here, the problem is that your One workaround could be to pass the property an |
@nick8325 I have just spent the last few hours completely nerd-sniped trying to convince myself that what I was trying was at all possible. Here is what I've done. It is just a sketch but the output looks promising: https://gist.github.com/NorfairKing/ff8ede08df7ee809be01e57f4634f197 And indeed, we see this output:
I really thought that I understood what you were saying, so now I no longer understand why this works. I had convinced myself that it wasn't possible.
Now I'm going to take a break, this was infuriating :p |
Is there a way to make this work if I can get the user to pinkie-promise that the inner resource is not used to change the shape of the generator or shrinking function?
Yes I could actually just pass the entire |
This been on my mind for a while now and I think I've been able to explain to myself why this seems to work. EDIT: I just figured out that what I made is actually still broken because the wrapper is not re-executed per run of a shrunken example's test. This means that a test could leak state into the next run and break the whole idea. I also need to think about this a bit more.. EDIT again: I think I may have figured something out, but it required quite the definition of how properties work. |
Gentle ping. In the meantime I've added this to sydtest to turn off shrinking when resources are in use: NorfairKing/sydtest@bbc7dcb#diff-f4f9ca3eba6b0fecf61df5940928227897178cad50db39356c016015382e29e8R178 |
Ref hspec/hspec#531
It looks like quickcheck assumes that properties don't use any resources while they are being tested.
In particular
reduceRose
is called before starting shrinking:quickcheck/src/Test/QuickCheck/Test.hs
Line 349 in 2dcfbf6
This uses the assumption that the
IO
actions inIORose
don't clean up resources that could affect the outcome of a test. (I think, please correct me if I'm wrong.)Is this fixable? If not I might have to write my own
Property
tester to support this use-case.The text was updated successfully, but these errors were encountered: