I'm writing Specs2
tests that use a temporary file and properties from ScalaCheck
. Without properties it works fine :
import better.files.File
import org.specs2.execute.{AsResult, Result}
import org.specs2.mutable.Specification
import org.specs2.specification.ForEach
trait TmpDirContext extends ForEach[File] {
def foreach[R: AsResult](testWithFile: File => R): Result = {
val tmpDirCtx = File.temporaryDirectory()
AsResult(tmpDirCtx.apply(testWithFile))
}
}
class OkTest extends Specification with TmpDirContext {
import better.files._
"Example" should {
"work" in { tmpDir: File =>
tmpDir.exists must beTrue
}
}
}
val test = new OkTest
specs2.run(test)
If I add properties, it doesn't compile :
import org.scalacheck.Prop
import org.specs2.ScalaCheck
class KoTest extends Specification with ScalaCheck with TmpDirContext {
"KoTest" should {
"work" in { tmpDir: File =>
"for" ! Prop.forAll { value: Int =>
tmpDir.exists must beTrue
}
}
}
Error:(26, 16) could not find implicit value for evidence parameter of type org.specs2.execute.AsResult[better.files.File => org.specs2.specification.core.Fragment]
"work" in { tmpDir: File =>
I've managed to make it compile, but then the test fails seemingly because the ForEach
from TmpDirContext
has already disposed of a temporary folder:
class KoTest2 extends Specification with ScalaCheck with TmpDirContext {
"KoTest2" should {
"work" >> { tmpDir: File =>
Prop.forAll { value: Int =>
tmpDir.exists must beTrue
}
}
}
}
I guess I'm missing something... How to make it work and have the tmpDir available in the property testing?
You can try the following approach
import org.specs2.mutable.Specification
import java.io.File
import org.specs2.ScalaCheck
import org.scalacheck._
class KoTest extends Specification with ScalaCheck with TempDir { sequential
"KoTest" should {
"work" >> {
"for" >> prop { (tmpDir: File, value: Int) =>
tmpDir.exists must beTrue
}.after(deleteTmpDir)
}
}
}
trait TempDir {
implicit def arbitraryTempDir: Arbitrary[File] =
Arbitrary(tmpDir)
val tmpDir = new File("temp")
def deleteTmpDir = tmpDir.delete
}
It is presented here