sizeRange
parameter (I'm using scalatest's ScalaCheckPropertyChecks
) but that doesn't seem to have an effect.
.sample
the option can provide it. Let me know if this kind of usage need an issue ?val pw = new PrintWriter(f)
for {
sample <- Gen.choose(5000, 100000).sample
_ <- 0 until sample
t <- Gen.choose(-500f, 500f).sample
} {
pw.write(s"$t\n")
}
pw.close()
I have a question about the default Shrink[Int]
instance.
From what I can see, it "simply" halves its input it reaches 0. This obviously works, but isn't very precise. Let's say, for example, that you have the following property:
val propTest = forAll { i: Int =>
i < 156
}
If you get an input of, say, 482, it'll get halved to 241, then get stuck there - it has no way of getting back "up" from (241 / 2) to 156.
An alternative implementation would be to halve the input, but then explore the larger part of the halved space:
implicit val intShrink: Shrink[Int] = {
def halves(inf: Int, sup: Int): Stream[Int] = {
if(math.abs(sup - inf) <= 1) Stream.empty
else {
val mid = inf + (sup - inf) / 2
mid #:: halves(mid, sup)
}
}
Shrink(i => halves(0, i))
}
I've ran some tests and this seems to consistently find the most precise value possible.
Was there any reason it wasn't implemented that way? For example, "hoping" for a value closer to 0 and avoiding getting stuck in a local optimum?
@ashawley yeah I've actually pushed the experience further and it's not actually a good idea. Binary search works because you keep a running context - [a, b]
. With shrinking, you do have that context while looking for the next failing test case, but you lose it as soon as you find that test case.
That is, you can be looking for your local minimum in [100, 150]
, and you'll end up searching in [0, 125]
.
You end up spending far more time looking at values you've already explored, and I'm not at all convinced it's safe - there *must be some infinite loop scenario
def noShrink[T]: Shrink[T] = Shrink(_ => Stream.empty)
Stream
, whats the recommendation here?
withLazyList
in #627.
Hi, I want to include some properties into ordinary AnyFunSuite, for example
MyAwesomeTest extends AnyFunSuite {
test("ordinary test") {
assert(true)
}
test("scalacheck test" {
val prop = forAll { b: Boolean =>
b
}
prop.check()
}
}
How can I launch property check in that scenario? I want to have a red failed test instead of
! Falsified after 0 passed tests.
> ARG_0: 0
> ARG_0_ORIGINAL: 71
I haven't found the answer in https://github.com/typelevel/scalacheck/blob/master/doc/UserGuide.md
test("scalacheck test") {
forAll { b: Boolean =>
b
}
}
Auto-application to `()` is deprecated. Supply the empty argument list `()` explicitly to invoke method dispatch,
or remove the empty argument list from its definition (Java-defined methods are exempt).
In Scala 3, an unapplied method like this will be eta-expanded into a function.
forAll {}
forAll {}
syntax, is there any obvious alternative that I am missing in the library?
Here's a different attempt at shrinking ints (basically a Scala version of the QuickCheck implementation) which seems to have better results than the default one: https://scastie.scala-lang.org/XbfRtWfFRG6rAKy6mUVbjg
Note that, contrary to the default ScalaCheck instance, it does not explore negative values, simply because QuickCheck doesn't.
Is there any reason the QuickCheck implementation wasn't ported over as is?
If not, I'm happy to make a more generic version and submit a PR...
Hi everyone. I'm trying to generate an ADT that is previously validated. So, instead of returning the actual ADT it is returning a Validate[ADT]. This is the generator:
val coordinatesGen: Gen[ValidationResult[Coordinates]] = for {
latitude <- arbitrary[Double].suchThat(BigDecimal(_).scale <= 8).suchThat(_.abs < 90)
longitude <- arbitrary[Double].suchThat(BigDecimal(_).scale <= 8).suchThat(_.abs < 180)
} yield {
Coordinates(
latitude = latitude,
longitude = longitude
)
}
implicit val arbCoordinatesGen: Arbitrary[ValidationResult[Coordinates]] = Arbitrary(coordinatesGen)
And this is the test:
property("coordinates") = forAll { coordinates: ValidationResult[Coordinates] =>
coordinates.isValid
}
This is not working tho, it seems like no test is passing: Generating coordinates.coordinates: Gave up after only 0 passed tests. 501 tests were discarded.
. Is this related to the fact that I'm returning a ValidationResult
instead of the actual ADT?
Gen.between
I think is the one I'm thinking of