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

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

D3 ワーストプラクティス

41b86e49df294f939a86f6cb409048be?s=128

ababup1192

June 01, 2018
Tweet

Transcript

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

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

    半学生、半社会人 - Elmとドラクエを布教しに 2
  3. 目次 - 言語ネットワーク(研究の話) - 環境要件 - 開発環境遷移 - Elmと自動テスト -

    まとめ 3
  4. 言語ネットワーク 4 同じ意味を持つ、違う表現の言語を 中間表現を中心として繋げることで ネットワークを構築する。 ユーザインタフェースを提供し、各言語 を編集でき、言語の変更は中間表現を 介して他の言語に反映される。 また、時間などのイベントにより中間表 現が変更される場合もある。

  5. 例 - デジタル・アナログ時計 5 デジタル時計 <-> アナログ時計 2つの言語からなるネットワーク デジタル時計の数字を変えると、変 更がアナログ時計に伝わる

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

    が伝わる グラフの傾きや切片を変更すると数 式へ変更が伝わる 教育での利用を想定
  7. 環境要件 7 中間データのロジックが正しく動いて いるかテストしたい 正しく言語が生 成されているか テストしたい

  8. 開発環境遷移 8 - ScalaFx - Scala.js - TypeScript + React(Redux)

    - Elm
  9. ScalaFX 9 利点 - Scalaが使用可能 懸念点 - Javaが入った環境が必要 - JavaFXがベースなのでミュータブル

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

    - 環境構築が複雑 - フレームワークのデファクトスタンダー ドが決まっていない - 結果テストに対する知見が薄くなる ScalaからコンパイルするAltJS
  11. Scala.js 11 - implicit val r とは ・・・ - Px.cbMとは・・・

    - ^^ <^.^
  12. TypeScript + React(Redux) 12 利点 - サポートが厚い(Microsoft) - 開発者(知見)が多い 懸念点

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

    O △ サポート X Scala.JS X O O X TypeScript + React △(フレームワーク・ ライブラリに依存) △(フレームワーク・ライブラ リ選定) O △
  14. 各環境所感 14 僕「世の中って厳しいな・・・何かを妥協し ないと求めるものは得られないのかな ・・・」

  15. 颯爽と現れるElm 15 < そんなこと無いよ!!! 

  16. 各環境所感 16 言語 UIに対するテスト ロジックに対するテスト マルチプラット フォーム 開発コスト ScalaFX X

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

    - テスタビリティが高い (純粋関数型言語) - 学習コストが低い(初期コストは高いが途中から平坦 ) 懸念点 - 情報が少ない(がHaskellの知識をほぼそのまま転用可能 ) - JSのライブラリをフルに使うような場合には向かない (Elmを捨てよ) Haskellライクな AltJS
  18. Elm 18

  19. Elm 19 Model - アプリケーションの全体の状態 View - UIを表現した関数呼び出し Update -

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

    Modelを戻り値とする関数 Msg - 網羅性を保証した自己定義型 すべての項目に対して言語レベルでテスト可能 (言語レベルでテスト項目を制限 )
  21. 自動テスト - 値の比較(言語レベル) 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
  22. 自動テスト - 更新した値の比較 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 値の更新は、新しい値を作るため 他の関数(処理)に値を渡しても不変であることが保証される
  23. 自動テスト - 分岐した値の比較 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)
  24. 自動テスト - 分岐した値の比較 24 TypeScript Elm var x = 10

    if(x > 10) { x *= 2 } x === 12 // false // テストがなければ気 づかない x = 10 (if x > 10 then x * 10) == 12 // コンパイルエラー // テストが無くても防げる! elseを書き忘れてし まった!
  25. 自動テスト - オプション値 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”
  26. 自動テスト - エラー値 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
  27. 自動テスト - 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 節は何・・・?
  28. 自動テスト - 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 が値を返す パターン漏れはコンパイラが検知、不思議なケー スはカバーする必要がない
  29. 自動テスト - 実際の想定されるテスト 29 TypeScript 状態1 状態2 状態3 状態4 状態5

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

    ケース6 Model, Update, Msg, View 自己定義したケースの漏れ (網羅性)、 不正な型の値を返していないかは、コンパイラがチェック 各ケースが正しい値を返しているかはテストで保証 UI(見た目)もテストで保証
  31. 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"
  32. Property Based Testing - 例 32 now > [2018] [5]

    [30] [19] [00] [30] == Expired 0, 1000000000000000, -1, -1000000000000, 10, ...
  33. これからの自動テストのあり方(お気持ち) 33 テスト屋さん エンジニア 品質の高いアウトプット 網羅性、ランダム、 複雑性等の 項目の洗い出し テスト仕様 質の高いコード

    テストコードで 品質を保証 UXの担保 真にお客様に 向き合う
  34. まとめ 34 Elmは言語レベルで、網羅性・型の安全性・テスタ ビリティを保証する 人間の労力を大きく減らし、本質的にやりたい品 質の確認に時間を割けます

  35. まとめ 35 Elmをプロダクト採用して品質を向上させて、お客 様を満足させましょう! 導入の際にはハンズオン協力します!是非お呼 びください!

  36. 例 - XML・JSON・YAML・ツリー 36 データ構造の変換と編集できるビューア 実務での利用を想定

  37. 例 - PlantUML・UML 37 エンジニアは、手慣れ たテキストエディタで 非エンジニアは、グラ フィカルなエディタで 変更を加える テキストをバージョン管

    理し、ヒストリを流すこ とでアニメーションする 議事録を自動生成
  38. Elm 38 依存関係, Elmのバージョンを見て自動でライブラリを選ぶ

  39. Elm 39 “[(1, 2), (3, 4), (5, 6)]” |. は捨てる

    |= は値として使う elm-tools/parser 座標の列のパーサコンビネータ
  40. 環境要件 40 - リッチなGUI機構を持っていること - マルチプラットフォームかつエンドユーザのスタートコストが少ないこと - テスタビリティが高いこと(自動テストがしたい) - 関数型言語

    - 自動テストは最高のドキュメント - 開発速度が早いこと - 多くの言語ネットワークサンプルを生産したいため
  41. Elm 41 直感的な自動テスト