Elixirをやろうとしていつも挫折をします。Hello, Worldを何度もやった記憶があるのですが、
今回は真面目にExDocを使ってHello, Worldのドキュメントを作ってみます。
準備
docker-composeを使ってElixirを使える環境を整えます。
version: "3.7"
services:
web:
build: .
working_dir: /opt/app
volumes:
- .:/opt/app
FROM elixir:1.7.4-alpine
RUN mix local.hex --force
最新版のElixirのイメージを指定して、docker-compose buildをして最低限の環境を作ります。
mixコマンドでのプロジェクト作成
以下のコマンドを実行してプロジェクトを生成します。
$ docker-compose run --rm web mix new hello_world
* creating README.md
* creating .formatter.exs
* creating .gitignore
* creating mix.exs
* creating config
* creating config/config.exs
* creating lib
* creating lib/hello_world.ex
* creating test
* creating test/test_helper.exs
* creating test/hello_world_test.exs
Your Mix project was created successfully.
You can use "mix" to compile it, test it, and more:
cd hello_world
mix test
Run "mix help" for more commands.
rubyのコマンドでいうところのbundle initのようなものですが、現在いるディレクトリにプロジェクトを
作成するオプションはなく、必ず1回層下のディレクトリが作成されるようです。
docker-compose.ymlのvolumeの部分を新しく作成されたディレクトリに合わせます。
volumes:
- ./hello_world:/opt/app
先程mix newしたときにmix testでテストは実行できると示されたので、mix testを実行して
念の為結果を確認します。
$ docker-compose run --rm web mix test
Compiling 1 file (.ex)
Generated hello_world app
..
Finished in 0.1 seconds
1 doctest, 1 test, 0 failures
Randomized with seed 211440
ドキュメントの修正
mix newで生成されたHelloWorldモジュールに既にドキュメントのサンプルが記載されていますので、
これを修正しながら動作確認をしていきます。とりあえず、Elixir 1.7からドキュメントに対していくつか
のメタデータを付与出来るようになったので、メタデータを付加してみます。
defmodule HelloWorld do
@moduledoc """
Documentation for HelloWorld.
"""
@moduledoc authors: ["d511805"], since: "1.7.0"
@doc """
Hello world.
## Examples
iex> HelloWorld.hello()
:world
"""
def hello do
:world
end
end
この状態でIExで確認してみるとメタデータが表示されることが確認できます。
authorsを確認することは出来ないようです。sinceは@doc単位でも記述することが出来ます。
iex(4)> h HelloWorld
HelloWorld
since: 1.7.4
Documentation for HelloWorld.
ドキュメントの生成
IEx上ではhでモジュールやそのメソッドのドキュメントを見ることが出来ますが、ex_docを使うことでhtmlやepubにドキュメントを出力することが出来ます。
mix.esxのdepsに以下の記述を追加して、mix deps getsを行います。
def deps do
[
{:ex_doc, "~> 0.19", only: :dev, runtime: false},
]
end
$ docker-compose run --rm web mix deps.get
Resolving Hex dependencies...
Dependency resolution completed:
New:
earmark 1.3.1
ex_doc 0.19.2
makeup 0.8.0
makeup_elixir 0.13.0
nimble_parsec 0.5.0
* Getting ex_doc (Hex package)
* Getting earmark (Hex package)
* Getting makeup_elixir (Hex package)
* Getting makeup (Hex package)
* Getting nimble_parsec (Hex package)
あとはmix docsを実行すると、docディレクトリにドキュメントが出力されます。
$ docker-compose run --rm web mix docs
==> nimble_parsec
Compiling 4 files (.ex)
Generated nimble_parsec app
==> makeup
Compiling 45 files (.ex)
Generated makeup app
==> earmark
Compiling 1 file (.yrl)
Compiling 2 files (.xrl)
Compiling 3 files (.erl)
Compiling 25 files (.ex)
Generated earmark app
==> makeup_elixir
Compiling 4 files (.ex)
Generated makeup_elixir app
==> ex_doc
Compiling 18 files (.ex)
Generated ex_doc app
==> hello_world
Compiling 1 file (.ex)
Generated hello_world app
Docs successfully generated.
View them at "doc/index.html".
メソッドの追加とドキュメントの追加
ドキュメントの出力が完了したので、もう一つ簡単なメソッドを追加して、そのドキュメントを
記述します。
defmodule HelloWorld do
...
@doc """
名前をメソッドに入力するとその名前に挨拶をしてくれるメソッドです。
## パラメータ
- name: 人名を表現する文字です。
## Examples
iex> HelloWorld.hello()
:world
"""
@spec hello(String.t()) :: String.t()
def hello(name) do
"Hello, " <> name
end
end
このようなメソッドとそれに対するドキュメントを追加して、IExで確認すると、新しい関数に対するドキュメント
を確認することが出来ます。IExではr HelloWorldというように編集したモジュールをリロードする機能
がありますが、ドキュメント部分に関しては、rでリロードしても読み込まれずに、IExを再起動する必要が
あるようです。
iex(4)> h HelloWorld.hello/1
def hello(name)
@spec hello(String.t()) :: String.t()
名前をメソッドに入力するとその名前に挨拶をしてくれるメソッドです。
## パラメータ
• name: 人名を表現する文字です。
## Examples
iex> HelloWorld.hello()
:world
テストの追加とdoctestの追加
最後に追加したメソッドのtestを追加するのと、doctestの修正も行います。
defmodule HelloWorldTest do
use ExUnit.Case
doctest HelloWorld
...
test "greets Hello, name" do
assert HelloWorld.hello("dd511805") == "Hello, dd511805"
end
end
defmodule HelloWorld do
...
## Examples
iex> HelloWorld.hello("dd511805")
"Hello, dd511805"
iex> HelloWorld.hello("john")
"Hello, john"
"""
@spec hello(String.t()) :: String.t()
def hello(name) do
"Hello, " <> name
end
end
テストを流して、動作確認を行います。
$ docker-compose run --rm web mix test
Compiling 1 file (.ex)
....
Finished in 0.2 seconds
2 doctests, 2 tests, 0 failures
Randomized with seed 152034
無事にテストとdoctestが通っていることが確認出来ました。doctestはドキュメント内に書いてある
テストコードと結果をテストしてくれるものですが、そのコメントに対応するメソッドのテストコードか
まではチェックしていないので、他のメソッドからドキュメントをコピーしている場合などは、正しいサンプル
になっていない場合でもdoctestが通ってしまいます。
それでもメソッドの処理を変更した際にテストだけでなく、ドキュメント側の修正もしないとエラーに
なるのは、テスト、ドキュメント整備の習慣としてはいいことだと思います。