英文:
Scalatestplus scalacheck for testing effectful api requires unsafeRunSync()
问题
我正在探索实现对具有效果的 API 进行测试的选项。为了简洁起见,我有以下 API。
```scala
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)
}
我使用 AsyncWordSpec with ScalaCheckPropertyChecks
。我不得不使用 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()
}
}
}
}
是否有一种方法可以避免调用 unsafeRunSync()
并将其留给框架。在 scalatestplus
中与 scalacheck
一起使用时,并没有提到测试具有效果的 API。
PS:
这是我目标的一个简化示例。我正在探讨编写针对 tagless final algebra 的规则的选项。
<details>
<summary>英文:</summary>
I am exploring options to implement tests for effectful api. For brevity, I have the following api.
```scala
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.
答案1
得分: 1
ScalaTest 本身并不是设计用于测试效果。
如果你查看 cats-effects testing 的官方文档,那里列出了你可以使用的不同库。你可以使用 cats-effect-testing,它可以与 ScalaTest 和 scalacheck 集成。你还可以使用 scalacheck-effect,它也支持以 A => F[Assertion]
的形式编写具有效果的属性。
此外,如果你查看 cats-effect - testing # best practices,它说:
> 避免在测试中使用 unsafe*
方法,就像你在“主”代码中避免使用它们一样。编写与“正常”代码结构相同的测试会使测试不太可能出现故障,作为可执行文档,并保持易于阅读。
> 使用兼容的框架支持编写 IO[Assertion]
样式的测试。
所以,你在你写的示例测试中所做的并不完全是一个好的做法。
英文:
ScalaTest by itself, is not design for testing effects.
If you check the official docs of cats-effects testing, there is a list with the different libs that you can use. You have cats-effect-testing which can be integrated with ScalaTest and scalacheck. You have scalacheck-effect too that adds support for writing effectful properties with the shape A => F[Assertion]
.
Also if you check cats-effect - testing # best practices it says
> Avoid using unsafe*
methods in tests, the same as you'd avoid them in
> "main" code. Writing tests to be structured the same way as "normal"
> code results in tests that are less likely to be flaky, act as
> executable documentation, and remain easy to read.
>
> Use a compatible framework's support for writing IO[Assertion]
style
> tests.
So, what you are doing in the test you wrote as an example, it's not exactly good
答案2
得分: 1
如其他人已经回答,当使用scalatest与scalacheck时,无法避免这个问题。
但是,如果完全迁移不可行,没有什么可以阻止你在代码库中使用多个测试框架。
我建议使用scalacheck-effect与munit集成。我以前已成功将scalacheck和munit混合在同一个代码库中,原因类似 - sbt test
将运行它们全部。你也可以尝试编写一个与scalacheck-effect类似于munit的scalatest集成,但老实说我不会费心去做这件事。
通常,我还建议出于其他原因使用munit,如果迁移测试是一个选项,你应该考虑一下。根据你使用的scalatest DSL,这并不像你想象的那么困难。
英文:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论