高木のブログ

【Elixir】テストを書いてみる

2022/12/03

Elixir でのテストを触りだけやる

バージョン

$ elixir -v
Erlang/OTP 25 [erts-13.1.1] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [jit:ns] [dtrace]

Elixir 1.14.2 (compiled with Erlang/OTP 25)

$ mix -v
Erlang/OTP 25 [erts-13.1.1] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [jit:ns] [dtrace]

Mix 1.14.2 (compiled with Erlang/OTP 25)

プロジェクト作成

mix new でプロジェクトを作成する

$ mix new hello

以下のファイル群が生成された

$ cd hello
$ tree .
.
├── README.md
├── lib
│   └── hello.ex
├── mix.exs
└── test
    ├── hello_test.exs
    └── test_helper.exs

2 directories, 5 files

hello.ex には、:world を返す hello 関数が定義されている

$ iex -S mix
Erlang/OTP 25 [erts-13.1.1] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [jit:ns] [dtrace]

Interactive Elixir (1.14.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Hello.hello
:world

mix test でテストを実行する

$ mix test
Compiling 1 file (.ex)
Generated hello app
..
Finished in 0.01 seconds (0.00s async, 0.01s sync)
1 doctest, 1 test, 0 failures

Randomized with seed 96636

もちろん通る

テストを変更する

hello(文字列)Hello, 文字列! を返す関数を想定してテストを書き換えてみる

テストは doctest と ExUnit が使われているらしい

それぞれ、以下のような変更をした

doctest

lib/hello.ex
 defmodule Hello do
   @moduledoc """
   Documentation for `Hello`.
   """

   @doc """
   Hello world.

   ## Examples

-      iex> Hello.hello()
-      :world
+      iex> Hello.hello("world")
+      "Hello, world!"

   """
   def hello do
     :world
   end
 end

ExUnit

test/hello_test.exs
 defmodule HelloTest do
   use ExUnit.Case
   doctest Hello

   test "greets the world" do
-    assert Hello.hello() == :world
+    assert Hello.hello("world") == "Hello, world!"
   end
 end

テストを実行

$ mix test
warning: Hello.hello/1 is undefined or private. Did you mean:

      * hello/0

Invalid call found at 2 locations:
  (for doctest at) lib/hello.ex:11: HelloTest."doctest Hello.hello/0 (1)"/1
  test/hello_test.exs:6: HelloTest."test greets the world"/1



  1) test greets the world (HelloTest)
     test/hello_test.exs:5
     ** (UndefinedFunctionError) function Hello.hello/1 is undefined or private. Did you mean:

           * hello/0

     code: assert Hello.hello("World") == "Hello, World!"
     stacktrace:
       (hello 0.1.0) Hello.hello("World")
       test/hello_test.exs:6: (test)



  2) doctest Hello.hello/0 (1) (HelloTest)
     test/hello_test.exs:3
     ** (UndefinedFunctionError) function Hello.hello/1 is undefined or private. Did you mean:

           * hello/0

     stacktrace:
       (hello 0.1.0) Hello.hello("world")
       (for doctest at) lib/hello.ex:11: (test)


Finished in 0.03 seconds (0.00s async, 0.03s sync)
1 doctest, 1 test, 2 failures

Randomized with seed 202919

当然テストはコケる

関数を修正する

テストが通るように関数を修正する

lib/hello.ex
 defmodule Hello do
   @moduledoc """
   Documentation for `Hello`.
   """

   @doc """
   Hello world.

   ## Examples

       iex> Hello.hello("world")
       "Hello, world!"

   """
   def hello(text) do
-    :world
+    "Hello, #{text}!"
   end
 end

テストを実行する

$ mix test
..
Finished in 0.01 seconds (0.00s async, 0.01s sync)
1 doctest, 1 test, 0 failures

無事、通った

参考


SNS でシェアする


ytkg

Written by ytkg, Twitter, GitHub