I am exploring options to implement tests for effectful api. For brevity, I have the following api.
object util {
import cats.effect.Sync
def stringReverser(string: String): String = string.reverse
def stringReverserF[F[_]: Sync](s: String): F[String] = Sync[F].delay(s.reverse)
}
I use AsyncWordSpec with ScalaCheckPropertyChecks
. I had to use unsafeRunSync
.
class SampleAsyncWordSpec extends wordspec.AnyWordSpec
with org.scalatestplus.scalacheck.ScalaCheckPropertyChecks {
import util._
import cats.effect.unsafe.implicits.global
"String reverser[F] with property based tests" must {
"satisfy consistency with length in original and reversed string" in {
forAll {(s: String) =>
val ioAssertion = stringReverserF[IO](s).map(r => assert(s.length() == r.length() + 1))
ioAssertion.unsafeRunSync()
}
}
}
}
Is there a way to avoid calling unsafeRunSync() and leave it to the framework. In scalatestplus
with scalacheck
, there is no mention of testing effectful api.
PS: This is a trimmed down example of my goal. I am exploring on options to write rules for tagless final algebra.
As others have answered, when using scalatest with scalacheck, it's not possible to avoid this.
However, there's nothing stopping you from having multiple test frameworks in your codebase if a full migration isn't possible.
I recommend using scalacheck-effect with the munit integration. I've successfully mixed scalacheck+munit in the same codebase before for similar reasons - sbt test
will run them all. It's possible that you could write a scalatest integration for scalacheck-effect similar to the munit one, but I wouldn't bother honestly.
I typically also recommend using munit over scalatest for other reasons; if it's an option to migrate your tests, you should consider it. It's not as hard as you might think, depending what scalatest DSL you're using