この記事はElmアドベントカレンダー 21日目の記事です。
ネタがなくて困っていたところ、ジンジャーさんのこんな投稿を見つけたのでelm-program-testを紹介します。
ジンジャーさんありがとうございます。
https://twitter.com/jinjor/status/1201911801119559685
elm-program-test とは
リポジトリより引用
elm-program-test provides a convenient API that works with elm-test (including Test.Html) for testing your Elm programs as complete units.
Elmプログラムのテスト実装に便利なAPIを提供しており、elm-testを内包しています。
elm-testがユニットテストやファズテストの実装に便利なAPIを提供しているのに対し、
elm-program-testはより上位レベルのテスト実装に便利なAPIを提供しています。
一連の操作を行った後に画面状態が期待通りになっているか確認したい場合などが利用例になると思います。
何が便利なのか
elm-program-testを使うと、テスト実装が実装コードの仕様変更やリファクタリングに対して堅牢になります。
具体的には、「機能は変わっていないのに、デザインが変わったせいでテスト書き直しになってしまった」のような問題が起こりづらくなります。
実際のテストコードを見てみましょう。
リポジトリからの引用です
import Test exposing (..)
import Test.Html.Selector exposing (class, text)
import ProgramTest exposing (clickButton, expectViewHas, start)
import MyProgram -- just an imaginary example
exampleProgramTest : Test
exampleProgramTest =
test "cannot publish without a title" <|
\() ->
ProgramTest.createElement
{ init = MyProgram.init
, update = MyProgram.update
, view = MyProgram.view
}
|> start ()
|> clickButton "New Post"
|> clickButton "Publish"
|> expectViewHas
[ class "invalid-article"
, text "You must provide a title before publishing"
]
いろいろ書いてありますが、テスト内容としてはstart以降です1。読んでみると、New Postボタン、Publishボタンの順で押した場合に、エラーメッセージが出るかどうかを確認するテストのようですね。
ここで注目したいのは、クリックするボタンの位置の指定にタグ構造を使っていない2ことです。これにより、デザインや内部の処理構造を変えてもテストを書き直さなくて済むようになっています。
elm-program-testには今回紹介したボタンクリックのシミュレート以外にも
- リンクをクリックする
- inputにテキスト入力する
- チェックボックスにチェックをつける
- セレクトボックスの中から選ぶ
といったユーザ操作をシミュレートするための便利な関数があります3。ガイドにEllieによる実装例もあるため、まず使ってみてはいかがでしょうか。
参考情報
リポジトリ https://github.com/avh4/elm-program-test/
ガイド https://elm-program-test.netlify.com/
Elm Package https://package.elm-lang.org/packages/avh4/elm-program-test/latest
Twitterで質問があったので追記
clickButtonに自動で探してもらえるボタンは以下のパターンのようです
- buttonのtext部分一致
- role属性がbuttonになっているタグのtext部分一致
- formタグ内 buttonのvalue部分一致
- formタグ内 input type submitのvalue部分一致
-
startの前部分では、Browser.element実装で使われるinit, update, view を渡しています。ProgramTestには、ElmのBrowser.XXに合わせて、createSandbox, createElement, createDocument, createApplicationや、Platform.workerのための createWorkerがあります。 ↩
-
実装を見ると、ボタンの実装としてあり得る可能性を列挙しており、その中のどれかであれば自動でボタンを見つけてくれるようです。 ↩
-
他に、Cmdを使ったテストなどもできるようですが、現状のElmの仕様ではCmd値を直接検証できないためにテスト用の型を定義する必要があり、コストに見合うかどうかを検討した方がよいと書かれていました。 ↩