scalascalatestscalacheckcats-effecttagless-final

Scalatestplus scalacheck for testing effectful api requires unsafeRunSync()


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.


Solution

  • 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