I have a case class that I am trying to test via ScalaCheck. The case class contains other classes.
Here are the classes:
case class Shop(name: String = "", colors: Seq[Color] = Nil)
case class Color(colorName: String = "", shades: Seq[Shade] = Nil)
case class Shade(shadeName: String, value: Int)
I have generators for each one
implicit def shopGen: Gen[Shop] = 
  for {
    name <- Gen.alphaStr.suchThat(_.length > 0)
    colors <- Gen.listOf(colorsGen)
  } yield Shop(name, colors)
implicit def colorsGen: Gen[Color] =
  for {
   colorName <- Gen.alphaStr.suchThat(_.length > 0)
   shades <- Gen.listOf(shadesGen)
  } yield Color(colorName, shades)
implicit def shadesGen: Gen[Shade] = 
  for {
    shadeName <- Gen.alphaStr.suchThat(_.length > 0) //**Note this**
    value <- Gen.choose(1, Int.MaxValue)
  } yield Shade(shadeName, value)
When I write my test and simply do the below:
  property("Shops must encode/decode to/from JSON") {
     "test" mustBe "test   
  }
I get an error and the test hangs and stops after 51 tries. The error I get is Gave up after 1 successful property evaluation. 51 evaluations were discarded.
If I remove Gen.alphaStr.suchThat(_.length > 0) from shadesGen and just replace it with Gen.alphaStr then it works. 
Question
- Why does having Gen.alphaStrwork forshadesGen, however,Gen.alphaStr.suchThat(_.length > 0)does not?
- Also when I run test multiple times (with Gen.alphaStr) some pass while some don't. Why is this?
 
                        
You probably see this behavior because of the way
listOfis implemented. Inside it is based onbuildableOfwhich is in turn based onbuildableOfNwhich has following comment:Your data structure is essentially a list of lists so even one bad generation will curse the whole data-structure to be discarded. And obviously most of the failures happens at the bottom level. That's why removing the filter for
shadeNamehelps. So to make it work you should generate more valid strings. You may changeGen.alphaStrto some custom-made generator based onnonEmptyListOfsuch as:Another simple way to work this around is to use
retryUntilinstead ofsuchThatsuch as in: