测试
ScalaTest、MUnit、ZIO Test。
30 分钟
测试
Scala 测试主流框架:ScalaTest(BDD/FunSpec 风格)、MUnit(轻量、Scala 3 友好)、ZIO Test(效应测试)。对照 /roadmaps/scala「Testing」节点。
学习目标
- 用 ScalaTest 编写单元测试与表驱动测试
- 了解 MUnit 与 sbt 测试集成
- 知道 ZIO Test 测效应型代码的方式
核心概念
ScalaTest 单元测试
// src/main/scala/calc.scala
def add(a: Int, b: Int): Int = a + b
def parsePositive(s: String): Option[Int] =
s.toIntOption.filter(_ > 0)
// src/test/scala/calcSuite.scala
import org.scalatest.funsuite.AnyFunSuite
class CalcSuite extends AnyFunSuite:
test("add") {
assert(add(2, 3) == 5)
}
test("parsePositive rejects zero and invalid") {
assert(parsePositive("0").isEmpty)
assert(parsePositive("abc").isEmpty)
assert(parsePositive("42").contains(42))
}
sbt test
sbt "testOnly CalcSuite"
测试类放 src/test/scala,sbt 自动发现 *Suite / *Test。
表驱动与 Matchers
import org.scalatest.funsuite.AnyFunSuite
import org.scalatest.matchers.should.Matchers
class AddTableSuite extends AnyFunSuite with Matchers:
val cases = List(
(1, 2, 3),
(0, 0, 0),
(-1, 1, 0)
)
cases.foreach { (a, b, want) =>
test(s"add($a, $b) == $want") {
add(a, b) shouldBe want
}
}
表驱动与 Go table-driven test 同理;shouldBe 提供更好的失败 diff。
MUnit 与 ZIO Test 概览
// MUnit 示例
class BookmarkSuite extends munit.FunSuite:
test("title nonEmpty") {
assertEquals(Bookmark(1, "u", "t").title, "t")
}
// ZIO Test 概念
import zio.test._
import zio.test.Assertion._
val spec = suite("bookmark")(
test("valid id") {
assert(parseId("1"))(isRight(equalTo(1L)))
}
)
MUnit 启动快、与 Scala 3 集成好;ZIO Test 可测 ZIO 失败分支与 clock 等环境。
与 Java 对照
| Scala | Java |
|---|---|
| ScalaTest / MUnit | JUnit 5 |
sbt test | mvn test / Gradle test |
| ZIO Test | 无标准效应测试 |
| FunSuite / FlatSpec |