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

nonEmptyListOf.sample started to return None #708

Closed
SebastianRabiej opened this issue Nov 6, 2020 · 4 comments · Fixed by #709
Closed

nonEmptyListOf.sample started to return None #708

SebastianRabiej opened this issue Nov 6, 2020 · 4 comments · Fixed by #709

Comments

@SebastianRabiej
Copy link

Dear fellow developers,

After migration from 1.14.3 to 1.15 Gen.nonEmptyListOf.sample started to behave differentlly.

This code works on version 1.14.3 but sometimes brakes on version 1.15.0 and 1.15.1:

import org.scalacheck.Gen
import org.scalatest.flatspec.AnyFlatSpecLike
import org.scalatest.OptionValues._
import org.scalatest.matchers.should.Matchers

class ScalaCheckTestSpec extends AnyFlatSpecLike with Matchers {
  it should "work" in {
    for (nr <- 1 to 10000) {
      println("iteration nr: " + nr)
      val values = Gen.nonEmptyListOf(Gen.chooseNum(2, 100)).sample.value
      values shouldNot be(empty)
    }
  }
}

The reason for failure always will be None after the method sample.

@imRentable
Copy link

I experience a similar behavior in generators that don't use Gen.nonEmptyListOf as well.

@ashawley
Copy link
Contributor

ashawley commented Nov 6, 2020

Is there a reason you're using .sample in your tests? Is that from an example you saw somewhere? Or are you using it here because you believe that's the root cause of the issue? The method sample is good for checking your generators, but it shouldn't be used in property tests. You should be using forAll.

The canonical property test of your generator would be something like:

  property("nonEmptyListOf(chooseNum)") = {
    Prop.forAll(Gen.nonEmptyListOf(Gen.chooseNum(0,100))) { l =>
      l.length > 0
    }
  }

The above works fine for me.

non added a commit to non/scalacheck that referenced this issue Nov 6, 2020
Previously we used the standard buildableOf and just filtered out empty
collections. However, given that the underlying methods support a size
parameter it's just as easy to inline buildableOf's implementation and
start the minimum size at 1, not 0.

Fixes typelevel#708
@non
Copy link
Contributor

non commented Nov 6, 2020

I agree with @ashawley that it's better to avoid sample and that generators may return None and callers have to deal with it -- you can't necessarily call a generator 10,000 times and expect that all of the results will be Some(...).

However, I've independently been trying to reduce how often this happens, and noticed that it was fairly easy to avoid needing suchThat in the definition of nonEmptyBuildableOf (used by this method). So I've created a PR to address that, which would also make it less likely to receive None values here.

@non non closed this as completed in #709 Nov 6, 2020
@ashawley
Copy link
Contributor

ashawley commented Nov 9, 2020

Also, you need to use Prop.forAllNoShrink, not Prop.forAll. I should have used that above. Otherwise, test failures will shrink your generators to empty lists and produce unexpected and confusing errors.

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

Successfully merging a pull request may close this issue.

4 participants