読者です 読者をやめる 読者になる 読者になる

akairosame’s blog

備忘録やメモ

sbt+Specs2でコンソール出力を設定する方法

Scala

テストケースが増えていくとSpecs2でテストをした際にログが肥大して見辛かったり、失敗したテスト箇所の情報が今ひとつ足りなかったのでコンソールへ出力する内容を設定する方法を調べました。

環境

Specs2 3.6.6
sbt 0.13.12

設定方法

Specs2側でコンソール出力する内容の設定を持っているので、それをテスト時に指定すれば良いようです。
Arguments reference

org.specs2.reporter.Notifier などのクラスを実装すれば好きなように出力を弄れるようですね。今回はそこまで必要なかったので簡単な設定で変更できる部分のみ試しました。

例えば、失敗したテストだけ詳細を出力するようにして(xonly)、失敗した際にはスタックトレースを出力するようにする(failtrace)と、
build.sbtを以下のようにすると設定できました。

lazy val root = (project in file(".")).
  settings(
    name := "root",
    scalaVersion := "2.11.8",
    libraryDependencies += "org.specs2" %% "specs2-core" % "3.6.6" % "test",
    scalacOptions in Test ++= Seq("-Yrangepos"),
    // Specs2設定
    testOptions in Test += Tests.Argument(sbt.TestFrameworks.Specs2, "xonly", "true", "failtrace", "true")
  )
テストしてみる

簡単なテストケースを用意してテストしてみました。

import org.specs2.mutable.Specification

class PassSpec extends Specification {
  "Pass" should {
    "test" in {
      true must beTrue
    }
  }
}

class TargetSpec extends Specification {
  object Target {
    def test(b: Boolean) = b must beTrue
  }

  "Target#test" should {
    "true" in {
      Target.test(true)
    }
    "false" in {
      Target.test(false)
    }
  }
}

PassSpecはテストに通過するクラス、TargetSpecはテストに失敗するクラスです。スタックトレースがどんな感じで出るか見るためオブジェクトにMatcherを置きました。

これで設定によって出力がどのように変わったか見てみました。

設定前

[info] Loading project definition from C:\xxx\project
[info] Set current project to root (in build file:/C:/xxx/)
[info] PassSpec
[info]
[info] Pass should
[info]   + test
[info]
[info]
[info] Total for specification PassSpec
[info] Finished in 30 ms
[info] 1 example, 0 failure, 0 error
[info]
[info] TargetSpec
[info]
[info] Target#test should
[info]   + true
[error]   x false
[error]    the value is false (TargetSpec.scala:13)
[info]
[info]
[info]
[info] Total for specification TargetSpec
[info] Finished in 30 ms
[info] 2 examples, 1 failure, 0 error
[info]
[error] Failed: Total 3, Failed 1, Errors 0, Passed 2
[error] Failed tests:
[error]         TargetSpec
[error] (test:test) sbt.TestsFailedException: Tests unsuccessful
[error] Total time: 2 s, completed 2017/01/09 22:27:47


設定後

[info] Loading project definition from C:\xxx\project
[info] Set current project to root (in build file:/C:/xxx/)
[info] PassSpec
[error]   x false
[error]    the value is false (TargetSpec.scala:13)
[error] TargetSpec$Target$.test(TargetSpec.scala:13)
[error] TargetSpec$$anonfun$2$$anonfun$apply$5.apply(TargetSpec.scala:21)
[error] TargetSpec$$anonfun$2$$anonfun$apply$5.apply(TargetSpec.scala:21)
[info] TargetSpec
[error] Failed: Total 3, Failed 1, Errors 0, Passed 2
[error] Failed tests:
[error]         TargetSpec
[error] (test:test) sbt.TestsFailedException: Tests unsuccessful
[error] Total time: 2 s, completed 2017/01/09 22:24:47

すっきりして良いですね。通過したテストでログを圧迫しなくなりそうです。スタックトレースも出ているので、とりあえずこれでテスト中に何らかのエラーが起こった時にも追跡しやすくなるんじゃないかなと思います。