12
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ElmAdvent Calendar 2016

Day 20

elm-testのテストコード改良に挑戦してみます

Last updated at Posted at 2016-12-18

あらまし

モジュール作ったらアプリケーションで実行するのは億劫なので資産残しついでにテストコードを実行しているんですが、
elm-testのテストコードの可読性をもう少し上げられないだろうかと、ちょっと工夫してみました。
改良というと絶対的に良くなったような表現になっちゃいますが、あくまで個人的な好みではあります:disappointed:

下記がelm-test initすると自動的に入ってくるサンプルコードの抜粋で、これを初期状態とします。
この中には2つのテストケースが入っていて、
両方共期待値と関数結果の2つの値の同一性を見ています。

Tests.elm(もとのコード)
all : Test
all =
    describe "Unit test examples"
        [ test "Addition" <|
            \() ->
                Expect.equal (3 + 7) 10
        , test "String.left" <|
            \() ->
                Expect.equal "a" (String.left 1 "abcdefg")
        ]

自分にとっては下記の要素あたりがやや作法的で、可読性を下げていたり毎回記述しなければいけない面倒さを感じさせるのかなーと思います。

  • カッコ省略の<|
  • \() ->の関数記述

変更その1: 大きい枠組みの変更

段階的に変更していこうと思います。
まず、test関数の型注釈が以下のようになってます。

test : String -> (() -> Expectation) -> Test

文字列と関数の2つの値を受け取ってTest型を返すようになっているので、
test関数のエイリアスになるような中置関数を定義してあげると<|を省略できそうです。
"テスト内容" => コードという感じになるようにしてみます。

TestExp.elm
module TestExp exposing (..)

import Test exposing (Test)
import Expect exposing (Expectation)

(=>) : String -> (() -> Expectation) -> Test
(=>) = Test.test

この=>関数をテストコードに適用してみます。

Tests.elm(v1)
import TestExp exposing (..)

all : Test
all =
    describe "Unit test examples"
        [ "Addition" =>
            \() ->
                Expect.equal (3 + 7) 10
        , "String.left" =>
            \() ->
                Expect.equal "a" (String.left 1 "abcdefg")
        ]

test関数<|がいなくなって、ちょっとだけスッキリしたように感じます。

変更その2:空引数をとる関数の変更

次に\() ->を何とか出来ないかなーと。1行専有しているし。。
改めて、test関数の型注釈を見ると、2つめの引数は()を取ってExpectationを返すようになっているので、その構造さえ踏襲すれば変更が加えられそうです。

test : String -> (() -> Expectation) -> Test

()を引数に取って、呼び出す際には省略するような関数の定義パターンは下記のようなものが考えられます。

f : () -> Int
f _ = 100
f : () -> Int
f = \() -> 10

では、Expect.equal関数に\() ->記述を吸収してもらおうかなと思います。
ということでeq関数を作ってみました。

TestExp.elm(追記)
eq : a -> a -> () -> Expectation
eq a b _ = Expect.equal a b

このeq関数をテストコードに適用してみます。

Tests.elm(v2)
all : Test
all =
    describe "Unit test examples"
        [ "Addition"
            => eq (3 + 7) 10
        , "String.left"
            => eq "a" (String.left 1 "abcdefg")
        ]

当初の課題が全部クリアになりました。
これで個人的に感じていた作法感が無くなりました!

変更その3:可読性もっと上がるか挑戦

v2のコードで不足感は無いんですが、
同一性を調べるという事をもうちょっとわかりやすく出来ないかということで
最後にeq関数を中置関数に変更してみたいと思います。
=>の右辺にカッコを付けなくても良いように演算優先度も調整します。

TestExp.elm(変更)
(===) : a -> a -> () -> Expectation
(===) a b _ = Expect.equal a b

infixl 8 =>

コレをテストコードに適用してみます。

Tests.elm(v3)
all : Test
all =
    describe "Unit test examples"
        [ "Addition"
            => (3 + 7) === 10
        , "String.left"
            => "a" === (String.left 1 "abcdefg")
        ]

同一性を確認しているという事をもう少し語っているコードになったんではないかと思います。
v2とv3はどっちが良いかは好みの問題かなと。

中置関数つくる手法はJSでは出来なかったやり方なのでElmカワイイよという思いが一段と増すポイントかなと思います。
乱用するとオレオレ記号だらけのコードになると思うので、要所のみの使用がいいんではないかと。
自分は取り敢えず会社のメンバーに今回のテストコードの手法を共有し、メンバーにホクホクしてもらったv3を採用しました。

12
1
7

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?