/var/log/jsoizo

メモ帳 技術とか趣味とか

ScalaTestのAsync Specで複数のassertをしたい

こういうAsyncなテストがあり複数assertしたかったりする。
given-when-then-andのand相当。

class FooSpec extends AsyncFunSpec with Matchers {

  it("awesome test") {
    val f1: Future[String] = Future {
      Thread.sleep(1000)
      "foo"
    }
    val f2: Future[String] = Future {
      Thread.sleep(1000)
      "bar"
    }


    f1.map(v => assert(v == "baz"))
    f2.map(v => assert(v == "bar"))
  }

}

AsyncではないSpecに慣れていると future.map(_ shouldBe "bar") でこのテストが失敗してほしいところだがそうはならない。
1つ目のassertが失敗しても2つめは成功し, この結果をFuture[Assertion]として返却するため。
丁寧に書くとこうなっており、assertはTestFailedExceptionを投げるので1つめが失敗したとしてもa1だけがFuture.failedとなりテストが通ってしまう。

val a1: Future[Assertion] = f1.map(v => assert(v == "baz"))
val a2 : Future[Assertion] = f2.map(v => assert(v == "bar"))
a2

要はそれぞれのFuture[Assertion]を合成してあげればいいというだけである。

for {
  _ <- f1.map(v => assert(v == "baz"))
  _ <- f2.map(v => assert(v == "bar"))
} yield Succeeded

なんかFutureの扱いに慣れていない人みたいだが、何も考えてないと割と間違える気がする。
しかもテストが通ってしまうので始末が悪いだよなぁ。。。

参考

www.scalatest.org