elm-testとelm-check

最近テストについて勉強したいなぁと思っていたので調べてみた。
この記事は、主にelm-testとelm-checkの周辺？の話になる。
わからなかったところも多いので、また考えたい。

いろいろ試してみた的な[githubレポジトリ。](https://github.com/giisyu/elm-test-sample)

#Elmのテストライブラリ
Elmでテストするときは以下のライブラリを使う。

* [elm-test](https://github.com/deadfoxygrandpa/elm-test/tree/3.0.1)
   * assertテスト用のライブラリ。
   * コンソールで結果を確認も出来る。ドキュメントにはTravisCIで動かす例なんかも載っている。
* [elm-check](https://github.com/NoRedInk/elm-check/tree/2.0.0)
  * プロパティベーステストを行うライブラリ。
  * プロパティ（性質）ベーステストとは、主張、反証といった方向から行うテスト、よくわかってない。純粋なコードに使っていくようだ（http://d.hatena.ne.jp/kazu-yamamoto/20121205/1354692144）。
  * またランダムな値でelm-testを自動生成することも出来る。
  * 結果をelm-testのTest型にすることもできる。


#テストの確認方法
テストの出力形式について。
html（またはjs）ファイルと、コンソール確認する方法がある。

##.html または .js

```elm

main : Element
main =
    elementRunner tests  --elementRunnerやstringRunnerで、ElementやHtmlに出来る。

```

コンパイルしてできたhtmlをブラウザで開くと、テスト結果を確認できる。Elmらしい
出来たhtmlを、jsテストランナーから確認する技もある。後述

##コンソールで確認する
elm-testはelm-console(旧elm-io)をサポートしている。（consoleRunnerという、IO () 型にできる関数がある。）

elm-consoleは、nodeで実行出来るようにするライブラリ。
流れとしては、まずportに対して、IO () をConsole.runする。

```
port runner : Signal (Task.Task x ())
port runner =
    Console.run (consoleRunner tests)
```

次にそのelmファイルを、一旦jsファイルとして出力する。

```
elm-make ./Main.elm --output ./raw-test.js
```

次に、ダウンロードしたelm-stuff内にある、elm-consoleフォルダ内にあるelm-io.shファイルをbashで起動して使う。引数に先ほどのjsファイルと、最終的な名前を入れる。bashスクリプトがやっていることは、workerモードでElm.Mainを起動するコードを付け足している。

```
bash プロジェクトパス/elm-stuff/packages/laszlopandy/elm-console/1.0.3/elm-io.sh ./raw-test.js ./test.js
```

そしてそのファイルをnodeで起動すると、テスト結果をコンソールで確認できる。

```
node ./test.js
```

###elm-checkの確認方法

elm-checkの方についての話題。elm-checkの基本的な型をHtmlで確認する関数は、今のバージョンでは何故かないようだ。だがこちらのブログ（[Running Elm Check with phantomjs]
(http://zkessin.github.io/elm-examples-blog//testing/phantomjs/elm-check/2015/12/21/phantomjs-and-elmcheck.html)
）に書かれたコードで、elm-testのTest型に変換できる。

つまりelm-checkはすべてelm-testのTest型にして確認すればいいと思われる。


##どっちを使うか
出力がｈｔｍｌと、コンソールがあるのを確認したが、どっちをどうつかうのか。

個人的にはElmを書くときは、elmファイルとelmテストファイルをwatchして、テスト結果はコンソール確認しながら書く。

Elmから離れて大きな集合（htmlファイル＋jsファイル全体で行いたいことや、クリックしたら結果どう表示が変わる等）でテストをしたいときは、ｊｓでテストファイルを書いて、elmのテストは(できればhtml)で吐いて、それをjsテストから確認して、最終的にjsテストの結果一本を見る。とかできたら良いな。（まだよくわからない）


# Elmのテストライブラリを使ってこういう方法があるんだなという話
[elm-web-api](https://github.com/rgrempel/elm-web-api)
というプロジェクトが、複数ブラウザでテストしたり、すべてTask型でテストコード書いたりと、いろいろやってて参考になる。

##elm-testのテスト結果を他のテストランナーから確認する。

elm-web-apiだと[ここ](https://github.com/rgrempel/elm-web-api/blob/master/test/src/elm/CI.elm#L24)と[この](https://github.com/rgrempel/elm-web-api/blob/master/test/src/mocha/elmTest.js#L36)部分。
elmのテスト結果の文字列をdomからとりだして、failを数えている。
以下のブログではファントムjsでとっている。
[Running Elm Check with phantomjs]
(http://zkessin.github.io/elm-examples-blog//testing/phantomjs/elm-check/2015/12/21/phantomjs-and-elmcheck.html)

##テストをすべてTask型でかく書き方。
* Nativeを呼び出すElmのコード
* Signal型

なんかにはTask型でシーケンスに書けて有効っぽい。
参考
[elm-signal-extra](https://github.com/Apanatshka/elm-signal-extra/tree/master/test)のテスト
[sample](https://github.com/Apanatshka/elm-signal-extra/blob/master/test/Native/ApanatshkaSignalExtra.js)というSignalをTask型にする関数を定義してテストしたりしている。

こんな書き方もあるんだなぁと。

##jsdomでdomのテスト。
domのテストをjsdomを使うと、ブラウザの類を立ち上げる必要なくできると聞いたので、冒頭あげたレポジトリ内でちょっと試してみてる。
でもjsdomの使い方と、テストでの使い方でつまずいてdom内の文字の確認するしかできなかった。。

```js
var fs = require('fs');

var elmApp = fs.readFileSync("dist/client/app/elm.js", "utf-8")
var mainJs = fs.readFileSync("dist/client/main/main.js", "utf-8")


describe('domのテスト', () => {

  var result, button, $;

  jsdom({
    file: "dist/client/index.html",
    src: [elmApp, mainJs],
    skipWindowCheck: true
  });

  before(function() {
    result = document.querySelector("#result");
    button = document.querySelector("#testButton");
    $ = rerequire('jquery');
  });

  describe('dom表示のテスト', function() {
    it('結果を表示と出る', function() {
      assert(result.textContent === "結果を表示")
    });
    it('押したあと、error！と表示', function(done) {
      $("#testButton")
        .click();
      setTimeout(function() {
        result = document.querySelector("#result");
        assert(result.textContent == "error!");
        done()
      }, 500);
    });
  });
});

```

reactではクリックのシュミレート用の関数とかあって、いい感じっぽいんですが、elmじゃ聞かないしまだ早いかもしれない。まずヘッドレスブラウザ等で考えるべきだったかも。

#まとめ

Elmのテストライブラリと出力方法を確認してみた。そして新たな書き方や、Html出力したものを他のテストツールから確認したりする方法を知った。

elm-web-apiを見てたら、mocha（等テストランナー）からみたらelmもただのいちjsファイルって感じに出来そうなのが個人的に良い。

httpを使ったコードとか、taskとか、ｊｓのテストツール群とか、テストはいくらでも深くできそうなので、またその都度調べていきたい。

今年はElmを追っててとても楽しく、勉強になった、来年もやるぞい。