scalaspecs2scalacheck

In the specs2 framework, why does using a Scope prevent execution of a forAll quantifier?


In the code below, how can I make Specs2 execute the first test? The "print ones" test passes when it should fail. The code inside the forAll() section is not executing because of the new Scope.

The println statements are only for tracing output. Please let me know if you see any lines starting with "one".

The empty Scope is just for demonstrating the problem. This is stripped-down from code where I actually use variables in a Scope.

import org.scalacheck.Gen
import org.scalacheck.Prop._
import org.specs2.ScalaCheck
import org.specs2.mutable.Specification
import org.specs2.specification.Scope

class TestingSpec extends Specification with ScalaCheck {
  "sample test" should {
    "print ones" in new Scope { 
      println("The first test passes, but should fail")
      forAll(Gen.posNum[Int]) { (x: Int) =>
          println("one: " + x)
          (0 < x) mustNotEqual true
      } 
    } 

    "print twos" in { 
      println("The second test passes and prints twos")
      forAll(Gen.posNum[Int]) { (x: Int) =>
        println("two: " + x)
        (0 < x) mustEqual true
      } 
    } 
  }
}

Here is my output:

sbt> testOnly TestingSpec
The second test passes and prints twos
The first test passes, but should fail
two: 1
two: 2
two: 1
    ...
two: 50
two: 34
two: 41
[info] TestingSpec
[info] 
[info] sample test should
[info]   + print ones
[info]   + print twos
[info] 
[info] Total for specification TestingSpec
[info] Finished in 96 ms
[info] 2 examples, 101 expectations, 0 failure, 0 error
[info] 
[info] Passed: Total 2, Failed 0, Errors 0, Passed 2
[success] Total time: 3 s, completed Apr 28, 2015 3:14:15 PM

P.S. I updated my project dependency from version 2.4.15 to specs2 3.5. Still has this issue...


Solution

  • This is because anything you put in a Scope must throw exceptions when there is a failure. A ScalaCheck Prop will not do anything unless you execute it so your example will always be passing.

    The workaround is to transform the Prop into a specs2 Result by using the following implicit for example:

    import org.specs2.execute._
    
    implicit class RunProp(p: Prop) {
      def run: Result = 
        AsResult(p)
    }
    

    Then

    "print ones" in new Scope { 
      println("The first test passes, but should fail")
       forAll(Gen.posNum[Int]) { (x: Int) =>
         println("one: " + x)
          (0 < x) mustNotEqual true
       }.run 
    }