ElixirでDynamoのsample実行とExUnitを使ってみた

Shinjuku.ex第1回目ということで、新宿 Brooklyn Parlorにて、命の水ビールをぐびぐびしながら、6人ぐらいElixirについてもくもくしてきました。

  • Dynamo という Sinatraっぽいフレームワークについて動かしてみる
  • 途中まで読んでいたチュートリアルの続きを最後までもくもく
  • テスト大好き ExUnit を使ってみる

ちなみに、チュートリアルが2つめなのは、チュートリアルをもくもくするのも良いけれど、動く物を試した用が良いよね!ってことでDynamoを動かそうと、なかなかうまく動くところまでいかなくて、途中で心が折れそうになり、横道反れた結果です。

あと、結論だけ書いてもおもしろくないので、失敗/躓いたところ多めで。

Dynamo を動かしてみる

必要なのは以下の3つ

erlang / rebar は、macならhomebrewから簡単にインストール出来る
(自分は、rebarがhomebrewにあるとは思ってなかったので、試行錯誤しました)

Elixir のインストールは Getting Started の 1.1.2 Manual install あたりを参照すれば良いかと
http://elixir-lang.org/getting_started/1.html

rebar というのは、erlangにおけるビルドツールらしい。makeやRubyのrakeみたいなもので、rebar.config というファイルにそのタスクが書かれているっぽい

$ git clone https://github.com/josevalim/dynamo.git
$ cd ./dynamo
$ make setup

make setup で dynamo が依存しているsubmoduleのセットアップとcompileを行う・・・が、普通に失敗する

$ make setup
git submodule update --init
# 中略
Compiled src/ibrowse_http_client.erl
cd deps/cowboy && make
make[1]: rebar: No such file or directory # ← ここら辺
make[1]: *** [deps] Error 1
make: *** [setup] Error 2

どうやら、deps/cowboy の make で rebarが無い模様
(homebrew等でインストールしてパスが通っていればこのエラーには遭遇しないはず。たぶん)

rebar がないので、もう一つのsubmoduleで依存しているdeps/ibrowse のrebarを拝借することに

$ cd ./deps/cowboy
$ ../ibrowse/rebar get-deps
$ ../ibrowse/rebar compile
<||

これで cowboy の準備はokで、dynamo の make setup タスクは完了
なお、get-deps / compile はcowboyのMakefileを見ると書いてある

次に dynamo のディレクトリに戻って make compile
>||
$ cd ../../
$ make compile

ダメな場合、直接下記を実行してみる

$ elixirc -pa deps/cowboy/ebin lib/*/*/*.ex lib/*/*.ex lib/*.ex -o ebin

これで、 ebin ディレクトリの中にコンパイル済み(?)のファイルが出来ているはず

examples/simple.exs の実行

実行の方法は simple.exs 自体に書かれている

$ cat ./examples/simple.exs                                                                                                                                                 [master]
# Run this app from root with:
#
#   elixir -pa ebin --no-stop examples/simple.exs

defmodule MyApp do
# 以下略
$ elixir -pa ebin --no-stop examples/simple.exs
Running ::MyApp on port 3000 with Cowboy # この行が表示されれば起動完了

"Running ::MyApp on port 3000 with Cowboy" が表示されない(listenに失敗してる?)場合もあり、どうやら原因不明に失敗している人もいた。

無事に表示された場合、http://localhost:3000/foo/bar にアクセスしてみる (http://localhost:3000/ じゃないよ) と Hello World! が表示されるはず

ExUnit を使ってみる

ExUnitの使い方をいろいろ見てみたいなら、やっぱりリポジトリの /test/ ディレクトリ下を見るのが良いかも
https://github.com/josevalim/dynamo/tree/master/test

基本的には、Rubyなどでもおなじみの /test ディレクトリ下にテストファイルがあり /test/test_helper.exs みたいなのがある感じ

以下、チュートリアルにあったサンプルにテストを追加してみたファイル
例では math.ex として保存して実行してみた

ExUnit.start []

defmodule Math do
  def sum(a, b) do
    a + b
  end
end

defmodule AssertionTest do
  use ExUnit::Case

  def test_pass do
    assert_equal 30, Math.sum(10, 20)
  end

  def test_failed do
    assert_equal 10, Math.sum(10, 20)
  end
end
$ elixir ./math.ex
.F

1) test_failed (::AssertionTest)
  ** (::ExUnit::AssertionError) Expected 30 to be equal to 10
  stacktrace:
    lib/elixir/builtin.ex:1023: ::Elixir::Builtin.raise/2
    lib/ex_unit/assertions.ex:374: ::ExUnit::Assertions.assert/2
    lib/ex_unit/runner.ex:78: ::ExUnit::Runner.run_test/3
    lib/enum.ex:556: ::Enum.do_each/3
    lib/enum.ex:136: ::Enum.each/3
    lib/enum.ex:131: ::Enum.each/2
    lib/ex_unit/runner.ex:69: ::ExUnit::Runner.run_tests/2

2 tests, 1 failures.

テストケースが2個しかないので表示が寂しいけれど、こんな感じでテストを書くことが出来る

ExUnit でキモになるところは、ExUnit.start [] と書かないと下記のようなエラーになります。

** (exit) "ExUnit::Server is not running. Are you sure you used exunit from command line?"
    lib/ex_unit/server.ex:59: ::ExUnit::Server.check/1
    lib/ex_unit/case.ex:6: ::ExUnit::Case.__using__/2
    /Users/toshiwo/var/misc/elixir/math.ex:8: ::ExUnit::Case.__using__/2
    src/elixir_dispatch.erl:104: :elixir_dispatch.dispatch_macro/6
    lists.erl:1278: :lists.mapfoldl/3
    lists.erl:1279: :lists.mapfoldl/3
    src/elixir_translator.erl:44: :elixir_translator.translate_each/2
    lists.erl:1278: :lists.mapfoldl/3

個人的には ::ExUnit::Server って単語だけで、erlangの message passingなんかを使って、テストケースを並列や分散させて走らせたり出来るのかな〜と妄想全開なところが気になってます
(実際のところの事実はまだ(知らない|調べてない)けれど・・・

まとめ

  • 結構Elixirそのものよりも、erlang に対する理解が乏しいので erlang に対して調べてたりしたことが多かった
  • 他にも Dynamo を動かすにあたり make ファイル読んだり、Elixir と関係ないところが・・・
  • でも、ExUnit 触ってみておもしろかった!TDDじゃなくてもテスト重要!!

以上、こんな感じで3時間ほどもくもくしてました。