error_msg.ex 使用了點宏git
(廢了點時間,一致在嘗試抹初那段for,想直接定義個工具宏, 因爲生疏了沒能很快成功,服務器
好在for的代碼也很簡短,而實際上從csv生成的話,也是要作循環工做,算是安慰)ide
defmodule ErrorMsg do @msgs %{ player_not_enough: "player_not_enough", can_not_start_when_playing: "can_not_start_when_playing", can_not_dismiss_when_playing: "can_not_dismiss_when_playing", just_creator_can_start: "just_creator_can_start", just_creator_can_dismiss: "just_creator_can_dismiss", can_not_join_when_playing: "can_not_join_when_playing", repeated_join: "repeated_join", can_not_quit_when_playing: "can_not_quit_when_playing", can_not_quit_when_creator: "can_not_quit_when_creator", can_not_make_up_when_not_playing: "can_not_makeup_when_not_playing", can_not_make_up_when_open: "can_not_make_up_when_open", can_not_make_up_when_full: "can_not_make_up_when_full", just_tian_gong_can_open: "just_tian_gong_can_open", repeated_open: "repeated_open" } for {tag, text} <- @msgs do def unquote(tag)() do unquote text end end end
錯誤消息也能夠從外部文件生成,只是系列自己主要演示基礎服務器開發,所以就不進一步了。工具
我曾經在博客裏有寫過方案從excel直接生成測試
(不過如今不建議了,該方案依賴的excel處理庫不夠好, 建議轉成csv,再從csv生成更好)ui
simple_table.ex 新增的使測試經過的代碼spa
defmodule SimpleTable do @state_ready :ready @state_playing :playing @state_dismiss :dismiss def init() do %{ id: 0, cards: nil, creator: nil, seat_map: %{}, seat_order: [], state: @state_ready } end def is_playing?(table), do: table.state == @state_playing def is_dismiss?(table), do: table.state == @state_dismiss def is_ready?(table), do: table.state == @state_ready def set_playing(table), do: put_in(table.state, @state_playing) def set_ready(table), do: put_in(table.state, @state_ready) def set_dismiss(table), do: put_in(table.state, @state_dismiss) def set_cards(table, cards), do: put_in(table.cards, cards) def get_cards(table), do: table.cards def init_deal(table) do table.seat_order |> Enum.map(&(find_seat(table, &1))) |> Enum.reduce(table, fn seat, new_table -> new_table |> init_deal_one(seat) end) end def init_deal_one(table, seat) do {:ok, cards, left} = SimplePoker.init_deal(table.cards) seat = seat |> Seat.add_cards(cards) table |> update_seat(seat) |> set_cards(left) end def set_id(table, id), do: put_in(table.id, id) def get_id(table), do: table.id def set_creator(table, player), do: put_in(table.creator, player) def get_creator(table), do: table.creator def seat_count(table), do: table.seat_order |> Enum.count def seat_order(table), do: table.seat_order def find_seat(table, %{} = player), do: find_seat(table, player |> Player.get_id) def find_seat(table, player_id), do: table.seat_map[player_id] def add_seat(table, player) do seat = Seat.init(player) seat_id = seat |> Seat.get_id table = table |> update_seat(seat) add_to_order(table, seat_id) end def update_seat(table, seat), do: put_in(table.seat_map[seat |> Seat.get_id], seat) def add_to_order(table, seat_id), do: update_in(table.seat_order, &(&1 ++ [seat_id])) def remove_seat(table, %{} = player), do: remove_seat(table, player |> Player.get_id) def remove_seat(table, player_id) do table = update_in(table.seat_map, fn m -> Map.delete(m, player_id) end) update_in(table.seat_order, fn o -> List.delete(o, player_id) end) end def start(table, player) do cond do is_playing?(table) -> {:error, ErrorMsg.can_not_start_when_playing} seat_count(table) < 2 -> {:error, ErrorMsg.player_not_enough} not is_creator?(table, player) -> {:error, ErrorMsg.just_creator_can_start} true -> table = table |> set_playing {:ok, table} end end def quit(table, player) do cond do is_playing?(table) -> {:error, ErrorMsg.can_not_quit_when_playing} is_creator?(table, player) -> {:error, ErrorMsg.can_not_quit_when_creator} end end def dismiss(table, player) do cond do is_playing?(table) -> {:error, ErrorMsg.can_not_dismiss_when_playing} not is_creator?(table, player) -> {:error, ErrorMsg.just_creator_can_dismiss} true -> table = table |> set_dismiss {:ok, table} end end def make_up(table, player) do cond do is_ready?(table) -> {:error, ErrorMsg.can_not_make_up_when_not_playing} find_seat(table, player) |> Seat.is_open? -> {:error, ErrorMsg.can_not_make_up_when_open} find_seat(table, player) |> Seat.is_full? -> {:error, ErrorMsg.can_not_make_up_when_full} end end def join(table, player) do cond do is_playing?(table) -> {:error, ErrorMsg.can_not_join_when_playing} find_seat(table, player) -> {:error, ErrorMsg.repeated_join} true -> table = table |> add_seat(player) {:ok, table} end end def open(table, player) do cond do find_seat(table, player) |> Seat.is_open? -> {:error, ErrorMsg.repeated_open} not (find_seat(table, player) |> Seat.get_cards |> SimplePoker.can_be_tian_gong?) -> {:error, ErrorMsg.just_tian_gong_can_open} end end def is_creator?(table, player), do: table.creator |> Player.get_id == player |> Player.get_id end
測試果真發現須要調整,分解測試仍是須要當心。3d
好在有測試的話,很容易就發現問題。這大概是測試的好處了吧。excel
還有其餘的小改動, seat.ex simple_poker.excode
具體看git吧
果真,寫代碼比寫測試快得多, 看着測試一個一個經過,仍是挺享受的。
另外,看代碼 join 和 quit 的cond 語句少了true, 顯然說明咱們的測試還沒覆蓋到!!!!
測試使代碼更容易編寫,代碼又輔助發現測試不足。相輔相成。