Scala 工具包

如何管理测试资源?

语言

你可以在一行中要求整个工具包

//> using toolkit latest

MUnit 作为一个测试框架,仅在测试文件中可用:test 目录中的文件或具有 .test.scala 扩展名的文件。请参阅 Scala CLI 文档 以了解有关测试范围的更多信息。

或者,你只需要求 MUnit 的特定版本

//> using dep org.scalameta::munit:1.0.0-M7

在你的 build.sbt 文件中,你可以添加对 toolkit-test 的依赖

lazy val example = project.in(file("example"))
  .settings(
    scalaVersion := "3.2.2",
    libraryDependencies += "org.scala-lang" %% "toolkit-test" % "0.1.7" % Test
  )

这里的 Test 配置表示该依赖项仅由 example/src/test 中的源文件使用。

或者,你只需要求 MUnit 的特定版本

libraryDependencies += "org.scalameta" %% "munit" % "1.0.0-M7" % Test

在你的 build.sc 文件中,你可以添加一个扩展 TestsTestModule.Munittest 对象

object example extends ScalaModule {
  def scalaVersion = "3.2.2"
  object test extends Tests with TestModule.Munit {
    def ivyDeps =
      Agg(
        ivy"org.scala-lang::toolkit-test:0.1.7"
      )
  }
}

或者,你只需要求 MUnit 的特定版本

ivy"org.scalameta::munit:1.0.0-M7"

FunFixture

在 MUnit 中,我们使用函数式 fixture 以简洁且安全的方式管理资源。FunFixture 为每个测试创建一个资源,确保每个测试独立于其他测试运行。

在测试套件中,你可以定义和使用 FunFixture 如下所示

class FileTests extends munit.FunSuite {
  val usingTempFile: FunFixture[os.Path] = FunFixture(
    setup = _ => os.temp(prefix = "file-tests"),
    teardown = tempFile => os.remove(tempFile)
  )
  usingTempFile.test("overwrite on file") { tempFile =>
    os.write.over(tempFile, "Hello, World!")
    val obtained = os.read(tempFile)
    assertEquals(obtained, "Hello, World!")
  }
}
class FileTests extends munit.FunSuite:
  val usingTempFile: FunFixture[os.Path] = FunFixture(
    setup = _ => os.temp(prefix = "file-tests"),
    teardown = tempFile => os.remove(tempFile)
  )
  usingTempFile.test("overwrite on file") { tempFile =>
    os.write.over(tempFile, "Hello, World!")
    val obtained = os.read(tempFile)
    assertEquals(obtained, "Hello, World!")
  }

usingTempFile 是类型为 FunFixture[os.Path] 的固定装置。它包含两个函数

  • 类型为 TestOptions => os.Pathsetup 函数创建一个新的临时文件。
  • 类型为 os.Path => Unitteardown 函数删除此临时文件。

我们使用 usingTempFile 固定装置来定义需要临时文件的一个测试。请注意,测试的主体采用一个类型为 os.PathtempFile 作为参数。固定装置自动创建此临时文件,调用其 setup 函数,并在测试后通过调用 teardown 清理它。

在示例中,我们使用固定装置来管理一个临时文件。一般来说,固定装置可以管理其他种类的资源,例如临时文件夹、数据库中的临时表、与本地服务器的连接,等等。

组合 FunFixture

在某些测试中,你可能需要不止一个资源。你可以使用 FunFixture.map2 将两个函数固定装置组合成一个。

val using2TempFiles: FunFixture[(os.Path, os.Path)] =
  FunFixture.map2(usingTempFile, usingTempFile)

using2TempFiles.test("merge two files") {
  (file1, file2) =>
    // body of the test
}
val using2TempFiles: FunFixture[(os.Path, os.Path)] =
  FunFixture.map2(usingTempFile, usingTempFile)

using2TempFiles.test("merge two files") {
  (file1, file2) =>
    // body of the test
}

FunFixture[A]FunFixture[B] 使用 FunFixture.map2 将返回一个 FunFixture[(A, B)]

其他固定装置

FunFixture 是推荐的固定装置类型,因为

  • 它是显式的:每个测试都声明它们需要的资源,
  • 它是安全使用的:每个测试都独立使用自己的资源。

为了更灵活,MUnit 包含其他类型的固定装置:可重用固定装置、临时固定装置和异步固定装置。在 MUnit 文档 中了解有关它们的更多信息。

此页面的贡献者