テスト容易性設計のやつOCamlでやってみた

自分の場合は現在時刻を引数で渡すようにしました。
モジュールやコンテキスを表すデータ型みたいなものを渡してもいいんですが仰々しいので。

t-wada.hatenablog.jp

コードはここに置いてあります。
Design-for-testability - OCaml version · GitHub

実装として、ファンクタに表示するメッセージのリストを渡して、挨拶用のモジュールを定義できるようにしてあります。
モジュールは下記の4つのモジュールです。

  • Time - 時刻を扱うデータ型モジュール
  • Time_range - 時刻の範囲を扱うデータ型モジュール
  • Greeter_message - 挨拶のデータ型モジュール
  • Greeter - 時刻によって挨拶を返すモジュール
open Greeter

module Greeter = Greeter.Make(struct
  (* 05:00:00以上 12:00:00未満 *)
  let morning = Time_range.create
    ~stime:(Time.create ~hour:5 ~min:0 ~sec:0)
    ~etime:(Time.create ~hour:12 ~min:0 ~sec:0)

  (* 12:00:00以上 18:00:00未満 *)
  let noon = Time_range.create
    ~stime:(Time.create ~hour:12 ~min:0 ~sec:0)
    ~etime:(Time.create ~hour:18 ~min:0 ~sec:0)

  (* 18:00:00以上 05:00:00未満 *)
  let night1 = Time_range.create
    ~stime:(Time.create ~hour:18 ~min:0 ~sec:0)
    ~etime:(Time.create ~hour:23 ~min:59 ~sec:60)
  let night2 = Time_range.create
    ~stime:(Time.create ~hour:0 ~min:0 ~sec:0)
    ~etime:(Time.create ~hour:5 ~min:0 ~sec:0)

  let messages = [
    (Greeter_message.create ~range:morning ~msg: "おはようございます");
    (Greeter_message.create ~range:noon ~msg: "こんにちは");
    (Greeter_message.create ~range:night1 ~msg: "こんばんは");
    (Greeter_message.create ~range:night2 ~msg: "こんばんは")
  ]
end)

またテスト用のパッケージをインストールするのが面倒だったので、テストの実行部分のコードを書きました。
通常はounitやppx_inline_testとかを使用した方がいいと思います。

ビルドもduneではなくocamlfind、ocamloptを使用しています。
適当なコード書くときに*.opam、duneファイル書くの結構面倒なんですよね。

感想

OCamlで時刻を扱うコードを書くの今ままでなかったので、標準モジュールを調べたりして、またOCamlに詳しくなりました。

今回はUnixモジュールのlocaltime、time関数やtm型を使用しました。
Windowsでは動かないと思います。