ScalaCheck scopes?

193 views
Skip to first unread message

Derek Chen-Becker

unread,
Mar 11, 2012, 2:01:56 PM3/11/12
to specs2...@googlegroups.com
Having the ability to use Scope/Before/After for examples is a really nice feature. Is there any way to incorporate that into the ScalaCheck functionality? Something like

trait CheckScope extends Scope { ... }

check in new CheckScope { (foo: Foo) => ... }

I've taken a quick look through the API and I think there might be a way to get there via implicits, but what I'm thinking feels a bit hacky.

Thanks,

Derek

etorreborre

unread,
Mar 11, 2012, 6:38:53 PM3/11/12
to specs2...@googlegroups.com
Hi Derek,

I propose the following:

package examples

import org.scalacheck._
import org.specs2._
import specification._
import execute.Result

class ScalaCheckScopeSpec extends Specification with ScalaCheck { def is =

  "check something with before code" ! SC { (s: String) =>
    s.reverse === s
  }

  object SC extends ScalaCheckContext with Before {
    def before { println("before") }
    override def checkProp(p: Prop) = p.set(minTestsOk -> 200)
  }
}

// this trait would be provided by specs2
trait ScalaCheckContext extends ScalaCheck { this: Context =>
  def apply[T, P](f: T => P)(implicit toProp: (=>P) => Prop, arbitrary: Arbitrary[T], shrink: Shrink[T]): Result = {
    apply(checkProp(check(f)))
  }
  
  // this method can be overriden to provide specific ScalaCheck parameters
  def checkProp(p: Prop) = super.check(p)

}


Please try it out a bit and tell me how it works for you.

Thanks,

Eric

Derek Chen-Becker

unread,
Mar 13, 2012, 12:26:26 AM3/13/12
to specs2...@googlegroups.com
This looks like it's on the right track. One thing missing in this particular incarnation (and something that I use a lot in non-scalacheck examples) is allowing the scope to define local variables accessible within the check. I was able to hack together a minor change to:

  trait ScalaCheckContext[T,P] extends ScalaCheck { this: Context =>
    def apply()(implicit toProp: (=>P) => Prop, arbitrary: Arbitrary[T], shrink: Shrink[T]): Result = {
      apply(checkProp(check(checkFunc)))
    }

    def checkFunc: T => P
  
    // this method can be overriden to provide specific ScalaCheck parameters
    def checkProp(p: Prop) = super.check(p)                                          
  }


Which then lets me do:

"some check" ! (new FooContext() {
  val checkFunc = {...}
}.apply())

Of course, having the types on the ScalaCheckContext trait makes things a bit funky, and the syntax sucks, but it works. I was trying to figure out if there would be a way to simply override the "check" method within the context trait, but unfortunately I'm tied up in other work at the moment and didn't make it very far. Any ideas would be appreciated.

Derek

etorreborre

unread,
Mar 13, 2012, 2:59:24 AM3/13/12
to specs2...@googlegroups.com
I changed a little something in the ScalaCheck trait implementation and now you can write (with the latest 1.9-SNAPSHOT):

package examples

import org.specs2._

class ScalaCheckContextSpec extends mutable.Specification with ScalaCheck  {

  "check something with before code" ! new SC {
    check { (s: String) =>
      s.reverse === aString
    }.set(minTestsOk -> 200)
  }

  trait SC extends mutable.Before {
    val aString = "xxx"
    def before { println("before") }
  }

}

In terms of syntax, I don't think that we can really do better than this if we want Context traits, use of member variables of those traits and checked properties. Also note that this only works with a "mutable" Specification.

Eric.

Daniel Shmuglin

unread,
May 11, 2015, 4:29:51 AM5/11/15
to specs2...@googlegroups.com
Eric, hi.

This syntax doesn't seem to compile anymore after upgrading to specs2 3.6 (see the error bellow).

Error:(55, 13) not enough arguments for method check: (prop: org.scalacheck.Prop, parameters: org.specs2.scalacheck.Parameters, prettyFreqMap: org.scalacheck.util.FreqMap[Set[Any]] => org.scalacheck.util.Pretty)org.specs2.execute.Result.
Unspecified value parameters parameters, prettyFreqMap.
      check { (source: ThirdPartyAppsAttributes) =>
            ^

What's the proper way to use the scalacheck with custom scope in 3.6?

Thanks.

Daniel

etorreborre

unread,
May 11, 2015, 7:08:05 AM5/11/15
to specs2...@googlegroups.com, dan...@wix.com
Hi Daniel,

Try with `prop`.

Eric.

Daniel Shmuglin

unread,
May 11, 2015, 7:59:42 AM5/11/15
to specs2...@googlegroups.com, dan...@wix.com
Seems to blend.

Thanks a lot!

Daniel Shmuglin

unread,
Jun 30, 2015, 10:49:51 AM6/30/15
to specs2...@googlegroups.com
Eric, hi.

Just noticed that though it compiles, nothing inside the prop blog is ever executed :(

class ServicesPostProcessingTest extends SpecificationWithJUnit with Mockito with ScalaCheck {

trait ctx extends Scope {
val process = new DefaultServicesPostProcessing
}

"apply" should {

"do not filter out Initialized non-TPA" in new ctx {
implicit val arb = Arbitrary {
embeddedServiceDTOGen retryUntil { s => s.getEmbeddedServiceType != EmbeddedServiceType.ThirdPartyApps && s.getState == State.Initialized } map toEmbeddedService
}

prop { (s: EmbeddedService) =>
System.exit(-1)
process(Seq(s)) must contain(s)
}
}

}
}

etorreborre

unread,
Jun 30, 2015, 6:58:30 PM6/30/15
to specs2...@googlegroups.com, dan...@wix.com
Hi Daniel,

I'm sorry but control-flow management with exceptions is really tricky. Since ctx is an anonymous class an exception needs to be thrown from the body of that class when there is a failure.
But the `prop` method just declares a property, it doesn't execute it. If you want the property to be executed you need to transform it into a Result with `AsResult`:

 AsResult { prop { s: EmbeddedService =>
   1 must_== 2
}}


A possible better option here is to pass a property directly to the `in` method and use an Arbitrary `ctx` that will be passed as well:

"do not filter out Initialized non-TPA" in { prop { (s: EmbeddedService, ctx: ProcessContext) =>
  ctx.process(Seq(s)) must contain(s)
}}

Eric.

Daniel Shmuglin

unread,
Jul 6, 2015, 4:00:05 AM7/6/15
to specs2...@googlegroups.com, dan...@wix.com
Eric,

Thanks for your reply.
I'll check those two options.

Cheers.
Reply all
Reply to author
Forward
0 new messages