-
Notifications
You must be signed in to change notification settings - Fork 30
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
Generators generate the same values for each test? #451
Comments
Is this behavior bad or just surprising to you? |
Both. It is bad because it makes the amount of variation smaller. It also not integration-tests friendly at all (and this is where I had to stop using Hedgehog in this case). It is also extremely surprising because when asking to generate something I would totally expect at least some variation and not a full copy of what I already had before in a previous test. Are you saying that it is by design @TysonMN ? |
I think the first item generated is always the smallest element in the sample space. More generally, there is a Your code has extreme behavior because you specified that each test should only consider one test case. |
Yep.
My question would be is if this is always the case or often the case. I would expect often, but not always.
No. I would expect diverging results as the Edit: If you want to run just one test because integration tests are slow, you can pin the size to a larger value as documented here. |
Out of all the runs that I did manually it was always the case. But, of course, I cannot say that there cannot be a run in which it won't be the case.
Thanks, I will try that! |
I don't expect that will work though, because I expect the generator always returns the smallest value as it's first sample regardless of size. Instead, if you only want to run a slow test one time, then I think you should hardcore the values for that test. |
Hm, maybe that's the case in Hedgehog proper, but empirically its not the case in Hedgehog.Xunit:
I do find that surprising. Running the above test a few dozen times with 0 size I always observed |
I do not. I certainly don't want to run them 100 times, but 1 was just me debugging the issue.
No, I have two tests (two properties) in one run. The values always change between runs, but within the same run the property that runs second always observes the value that the first property has seen. |
Consider this example: open System
open Hedgehog
open Hedgehog.Xunit
type User = { id: Guid; name: String; age: int }
[<Properties(Tests = 1<tests>, Shrinks=0<shrinks>)>]
module Tests =
[<Property>]
let ``Test A`` (user1: User) =
user1.id = user1.id
[<Property>]
let ``Test B`` (user1: User, user2: User) =
user1.id = user1.id When I run it I always see that |
I just tested it with a "plain" |
I just quickly checked Haskell Hedgehog, and it doesn't have this behaviour. As expected, each test Here is a reference test: module TestSpec where
import HaskellWorks.Hspec.Hedgehog
import Hedgehog
import qualified Hedgehog.Gen as Gen
import qualified Hedgehog.Range as Range
import Test.Hspec
import Debug.Trace
data User = User {
name :: String,
age :: Int }
deriving (Show, Eq)
userGen :: MonadGen m => m User
userGen = User
<$> Gen.string (Range.linear 1 10) Gen.alpha
<*> Gen.int (Range.linear 0 100)
{- HLINT ignore "Redundant do" -}
spec :: Spec
spec = describe "First Spec" $ do
it "test A" $ require $ withTests 1 $ withShrinks 0 $ property $ do
user1 <- forAll userGen
traceShowId user1 === user1
it "test B" $ require $ withTests 1 $ withShrinks 0 $ property $ do
user1 <- forAll userGen
user2 <- forAll userGen
traceShowId user1 === traceShowId user2 |
Then you should be calling With this library, you do that be adding the If you are only debugging, then why do you care that the two tests in the same run are given the same input? |
Sorry for not being clear in my message. So let's not concentrate on the number of tests that are being run per property. |
I think this is the intended behavior. As I said before:
|
That's sad. I hoped that it is more accidental than intentional... |
I do not think that it is about the first element only. It then keeps generating the same values. In the example below, there are two tests receiving two So we are essentially running tests with the same generated values. open System
open Hedgehog
open Hedgehog.Xunit
open Xunit.Abstractions
type User = { id: Guid; name: String; age: int }
[<Properties(Tests = 5<tests>, Shrinks=0<shrinks>)>]
type Tests(output: ITestOutputHelper) =
[<Property>]
let ``Test A`` (user1: User, user2: User) =
output.WriteLine ($"{user1.id}, {user2.id}")
user1.id = user1.id
[<Property>]
let ``Test B`` (user1: User, user2: User) =
output.WriteLine ($"{user1.id}, {user2.id}")
user1.id = user1.id
Output:
|
Now this looks like a bug to me. Can you achieve the same behavior without |
Apparently yes. Back to basics: open System
open Xunit
open Hedgehog
open Xunit.Abstractions
type User = { id: Guid; name: String; age: int }
let propertyConfig = PropertyConfig.defaultConfig |> PropertyConfig.withTests 5<tests> |> PropertyConfig.withoutShrinks
let userGen =
gen {
let! id = Gen.guid
let! name = Gen.string (Range.linear 0 100) Gen.alpha
let! age = Gen.int32 (Range.linear 0 100)
return { id = id; name = name; age = age }
}
type PureTests(output: ITestOutputHelper) =
[<Fact>]
let ``Test A`` () =
property {
let! user1 = userGen
let! user2 = userGen
output.WriteLine ($"{user1}, {user2}")
user1.id = user1.id
} |> Property.checkBoolWith propertyConfig
[<Fact>]
let ``Test B`` () =
property {
let! user1 = userGen
let! user2 = userGen
output.WriteLine ($"{user1}, {user2}")
user1.id = user1.id
} |> Property.checkBoolWith propertyConfig It prints exactly the same users from both tests. This is why I suspect that we somewhere split the generator into two, use one part for a test, and pass it to the next test instead of the unused one... |
Any word on this one? |
No progress. Sorry. I don't have much time to maintain this project any more. |
I have two tests that are defined as:
The generator is defined using
LINQ
like:and the config is:
I mark my tests with
But then when I run these tests in the same test run, I see that
GetUserById
and GetUsersByIdget the same
User`!GetUsersById
receives two different users, thenGetUserById
receives one user, which is one of these thatGetUsersById
previously received.I played with it a bit, asking for more users, and it seems like the test that gets called second, would get the parameters that were previously passed to the test that was called first.
Is it by design?
It looks like the splitting some random generator issue to me? Like if it was split, but then the wrong part was passed down...
The text was updated successfully, but these errors were encountered: