Upgrade to Pro — share decks privately, control downloads, hide ads and more …

フロントエンド開発で自動テストをしてElmという言語に流れ着いた話

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

 フロントエンド開発で自動テストをしてElmという言語に流れ着いた話

D3 ワーストプラクティス

Avatar for ababup1192

ababup1192

June 01, 2018
Tweet

More Decks by ababup1192

Other Decks in Programming

Transcript

  1. 自己紹介 - Twitter: ababupdownba - GitHub: ababup1192 - 2018年3月にBizReachに入社 -

    半学生、半社会人 - Elmとドラクエを布教しに 2
  2. 例 - デジタル・アナログ時計 5 デジタル時計 <-> アナログ時計 2つの言語からなるネットワーク デジタル時計の数字を変えると、変 更がアナログ時計に伝わる

    アナログ時計の針を動かすと、 変更がデジタル時計に伝わる 時間経過でも時計は動く 初等教育での利用を想定
  3. 例 - 数式・グラフ, 座標 6 数式 <- グラフ 2つの言語からなるネットワーク 数式の値を変更するとグラフへ変更

    が伝わる グラフの傾きや切片を変更すると数 式へ変更が伝わる 教育での利用を想定
  4. ScalaFX 9 利点 - Scalaが使用可能 懸念点 - Javaが入った環境が必要 - JavaFXがベースなのでミュータブル

    要素が強い - テストが難しい - JavaFXが Oracle JDKから削除 JavaFXをScalaでラッパーしたGUIフレームワーク
  5. Scala.js 10 利点 - Scalaの多くの資産が利用可能 - サポートが厚い 懸念点 - 複雑

    - 環境構築が複雑 - フレームワークのデファクトスタンダー ドが決まっていない - 結果テストに対する知見が薄くなる ScalaからコンパイルするAltJS
  6. TypeScript + React(Redux) 12 利点 - サポートが厚い(Microsoft) - 開発者(知見)が多い 懸念点

    - JavaScriptがベースなので、言語そのもののテスタビリ ティが低い - テスタビリティを補うには、フレームワーク依存のテスト フレームワークを利用する AltJS JavaScriptに型を付与した言語
  7. 各環境所感 13 言語 UIに対するテスト ロジックに対するテスト マルチプラット フォーム 開発コスト ScalaFX X

    O △ サポート X Scala.JS X O O X TypeScript + React △(フレームワーク・ ライブラリに依存) △(フレームワーク・ライブラ リ選定) O △
  8. 各環境所感 16 言語 UIに対するテスト ロジックに対するテスト マルチプラット フォーム 開発コスト ScalaFX X

    O △ サポート X Scala.JS X O O X TypeScript + React △(フレームワーク・ ライブラリに依存) △(フレームワーク・ライブラ リ選定) O △ Elm O O O △(O?)
  9. Elm 17 利点 - 言語自体がフレームワークを内包している (選択コストが無い) - ビルド環境がシンプル - 型安全

    - テスタビリティが高い (純粋関数型言語) - 学習コストが低い(初期コストは高いが途中から平坦 ) 懸念点 - 情報が少ない(がHaskellの知識をほぼそのまま転用可能 ) - JSのライブラリをフルに使うような場合には向かない (Elmを捨てよ) Haskellライクな AltJS
  10. Elm 19 Model - アプリケーションの全体の状態 View - UIを表現した関数呼び出し Update -

    Modelの更新 Msg - 変更の種類を通知 すべての項目に対して言語レベルでテスト可能 (言語レベルでテスト項目を制限 )
  11. Elm 20 Model - 数値、文字列、リスト、レコード View - Html型の値と言う単なるデータ Update -

    Modelを戻り値とする関数 Msg - 網羅性を保証した自己定義型 すべての項目に対して言語レベルでテスト可能 (言語レベルでテスト項目を制限 )
  12. 自動テスト - 値の比較(言語レベル) 21 TypeScript Elm [1, 2, 3] ===

    [1, 2, 3] // false [1, 2, 3] === [1, 2, 3] // True { a: 1, b: “abc” } === { a: 1, b: “abc” } // false { a = 1, b = “abc” } === { a = 1, b = “abc” } // True
  13. 自動テスト - 更新した値の比較 22 TypeScript Elm record = { a

    = 1, b = “abc” } { record | b = “def” } == { a = 1, b = “def” } // True record == { a = 1, b = “abc” } // True var obj = { a: 1, b: “abc” } obj.b = “def” obj === { a: 1, b: “def” } // false 値の更新は、新しい値を作るため 他の関数(処理)に値を渡しても不変であることが保証される
  14. 自動テスト - 分岐した値の比較 23 TypeScript Elm var x = 10

    if(x > 10) { x *= 2 } else { x += 2 } x === 12 x = 10 (if x > 10 then x * 10 else x + 2) == 12 aが前後で 書き換わる ifは式なので そのまま比較可能 xは不変(== 10)
  15. 自動テスト - 分岐した値の比較 24 TypeScript Elm var x = 10

    if(x > 10) { x *= 2 } x === 12 // false // テストがなければ気 づかない x = 10 (if x > 10 then x * 10) == 12 // コンパイルエラー // テストが無くても防げる! elseを書き忘れてし まった!
  16. 自動テスト - オプション値 25 TypeScript Elm function evenDouble(num) { if(num

    % 2 == 0) return num * 2; else return undefind; } var doubled = evenDouble(10) if(doubled === undefined) { return “odd number”; } return “num: ${num}”; evenDouble num = if num % 2 == 0 then Just num * 2 else Nothing case (evenDouble 10) of Just num -> “num: ” ++ toString num Nothing -> “odd number”
  17. 自動テスト - エラー値 26 TypeScript Elm function evenDouble(num) { if(num

    % 2 == 0) return { status: “OK”, value: num * 2 }; else return { status: “NG”, value: “odd number” }; } var { staus, value } = evenDouble(10) if(status === “OK”) { return “num: ${value}”; } else if(status === “NG”) { “error: ${value}”; } evenDouble num = if num % 2 == 0 then Ok num * 2 else Err “odd number” case (evenDouble 10) of Ok num -> “num: ” ++ toString num Err msg -> “error: ” ++ msg
  18. 自動テスト - UIテストと分岐 27 39 37 38 40 39 打たれたキー

    TypeScript function toKeyCode(key) { if(key === UP) { return 38; } else if(key === DOWN) { return 40; } … else { console.log(“なんかのキー”) } } 分岐漏れが怖い else 節は何・・・?
  19. 自動テスト - UIテストと分岐 28 39 37 38 40 39 打たれたキー

    Elm type Key = Up | Down | Left | Right toKeyCode key = case key of UP -> 38 DOWN -> 40 Left -> 37 Right -> 39 case が値を返す パターン漏れはコンパイラが検知、不思議なケー スはカバーする必要がない
  20. 自動テスト - 実際の想定されるテスト 29 TypeScript 状態1 状態2 状態3 状態4 状態5

    状態6 各状態をデバッガ等で確認、人間が網羅的に確認していく。
  21. 自動テスト - 実際の想定されるテスト 30 Elm ケース1 ケース2 ケース3 ケース4 ケース5

    ケース6 Model, Update, Msg, View 自己定義したケースの漏れ (網羅性)、 不正な型の値を返していないかは、コンパイラがチェック 各ケースが正しい値を返しているかはテストで保証 UI(見た目)もテストで保証
  22. Property Based Testing (Fuzz) 31 randomlyGeneratedStringの生成データ例 str: "" str: "k1C#dcn-2=v`xI,q.NmwRDk5wY9QE{IR|z~h

    G6V1dO[Jl]*/f=)C^Z=<i=V+<{ ]le@Cpy{KD*47[gX7(-g?}f2" str: " \t\n\n\n\n" str: "\n" str: "e"
  23. Property Based Testing - 例 32 now > [2018] [5]

    [30] [19] [00] [30] == Expired 0, 1000000000000000, -1, -1000000000000, 10, ...
  24. Elm 39 “[(1, 2), (3, 4), (5, 6)]” |. は捨てる

    |= は値として使う elm-tools/parser 座標の列のパーサコンビネータ