ScalaのPlay Frameworkでの開発をしていると、HTMLテンプレートの中でちょっとした条件分岐を書くことがある。そういう時に毎回手動で確認するのも大変なので、簡単なテストくらいは書いておきたいと思った。
そこで今回はjsoupを使ってテストを書くのを試したのでメモ。
jsoupとは
Java用のHTMLのParserライブラリ。jQueryのselectorのような形でデータを取り出したりできるので、HTMLの確認をするのに便利に使える。Java用なのでScalaにも使える。
jsoupをテスト用に導入する
build.sbtに以下のように書いておく。バージョン番号はその時の最新を選んでおくと良い。
libraryDependencies += "org.jsoup" % "jsoup" % "1.10.3" % Test
今回テストしたいcontrollerとview
とりあえずテスト用に、簡単なcontrollerとviewを用意する。
- controller: https://github.com/shibayu36/scala-play-blog/blob/fd8354c9529c9081888fafaa42de09716cd361e9/app/controllers/HomeController.scala
- view: https://github.com/shibayu36/scala-play-blog/blob/fd8354c9529c9081888fafaa42de09716cd361e9/app/views/index.scala.html
app/controllers/HomeController.scala
package controllers import javax.inject._ import play.api._ import play.api.mvc._ @Singleton class HomeController @Inject()(cc: ControllerComponents) extends AbstractController(cc) { def index() = Action { implicit request: Request[AnyContent] => Ok(views.html.index()) } }
app/views/index.scala.html
@() @main("Welcome to Play") { <h1>Welcome to Play!</h1> <div class="div1"> <p class="class1">hoge1</p> <p class="class2">fuga1</p> </div> <div class="div2"> <p class="class1">hoge2</p> <p class="class2">fuga2</p> </div> }
jsoupで出力されたHTMLをテストする
jsoupさえ導入されていれば、contentAsStringで取り出した文字列をparseしたら、あとはいろいろな方法でデータを取り出してテストできる。 https://github.com/shibayu36/scala-play-blog/blob/fd8354c9529c9081888fafaa42de09716cd361e9/test/controllers/HomeControllerSpec.scala
test/controllers/HomeControllerSpec.scala
package controllers import play.api.test._ import play.api.test.Helpers._ import org.jsoup.Jsoup class HomeControllerSpec extends test.ControllerSpec { describe("HomeController GET") { it("render the index page from a new instance of controller") { val controller = new HomeController(stubControllerComponents()) val home = controller.index().apply(FakeRequest(GET, "/")) status(home) shouldBe OK contentType(home) shouldBe Some("text/html") contentAsString(home) should include ("Welcome to Play") val doc = Jsoup.parse(contentAsString(home)) val h1 = doc.select("h1") h1.text shouldBe "Welcome to Play!" val pElems = doc.select("p") pElems.get(0).text shouldBe "hoge1" pElems.get(1).text shouldBe "fuga1" pElems.get(2).text shouldBe "hoge2" pElems.get(3).text shouldBe "fuga2" val pWithClass1Elems = doc.select("p.class1") pWithClass1Elems.get(0).text shouldBe "hoge1" pWithClass1Elems.get(1).text shouldBe "hoge2" // nested example val div1Elem = doc.select(".div1").first val pElemsInDiv1 = div1Elem.select("p") pElemsInDiv1.get(0).text shouldBe "hoge1" pElemsInDiv1.get(1).text shouldBe "fuga1" } } }
あとjsoupをいい感じに使えば、テンプレートのテストをいろいろ行うことができる。 https://jsoup.org/cookbook/ あたりをみると、jQueryのセレクタの方法で要素の取り出しは柔軟にできるし、要素からHTMLや属性を取り出したりもできるので、大体これでテストできそう。
まとめ
今回はjsoupを使ったテストについて書いてみた。これでHTMLのテンプレートのテストもできるようになったので安心できるようになった。