LoginSignup
1
0

More than 5 years have passed since last update.

見易い定数同値テストのためのRSpec matcher

Last updated at Posted at 2016-12-19

概要

RSpecでモジュールで定義した定数との同値テストの結果を見易くする。
(これ、需要は少なくないと思うので、標準の方法でもあるのではないかと疑っています。知ってる方いたら教えて頂けると幸いです)

前振り

RSpecのテストを書いていて、ある対象がモジュールで定義した定数と一致すること、というテストケースを書くことがある。
例えば、こんなテストケース。

# プロダクトコード抜粋
module Status
  SUCCESS = 0
  ERROR = -1
end

# テストコード抜粋
status = Status::SUCCESS
expect(status).to eq Status::Error
# => expected: -1
# =>      got: 0

この失敗するテストの結果は、人間にとって見易いものではない。
我々が知りたいのは0とか-1とかいう数値ではなく、SUCCESSとかERRORとかいう意味のある名前である。

解決方法

以下のようなmatcherを実装する。

RSpec::Matchers.define :const_eq do |mozule, exp_symbol|
  match do |act_val|
    mozule.const_get(exp_symbol) == act_val
  end
  failure_message do |act_val|
    act_symbol = mozule.constants(true).find { |c| mozule.const_get(c) == act_val }
    act_msg = if act_symbol.nil? then "ACTUAL: unknown value(#{act_val})"
              else "ACTUAL: #{mozule.name}::#{act_symbol}(#{act_val})"
              end
    exp_val = mozule.const_get(exp_symbol)
    "EXPECT: #{mozule.name}::#{exp_symbol}(#{exp_val})\n" << act_msg
  end
end

使用例

# プロダクトコード抜粋
module Status
  SUCCESS = 0
  ERROR = -1
end

# テストコード抜粋
status = Status::ERROR
expect(status).to const_eq Status, :SUCCESS
# => EXPECT: Status::SUCCESS
# => ACTUAL: Status::ERROR
expect(999).to const_eq Status, :SUCCESS
# => EXPECT: Status::ERROR
# => ACTUAL: unknown value(999)

改善予定

  • --format documentationしたときにも見易くするためにdescriptionを定義する。
  • より細かな制御ができるmatcherを生成する方法はその2で紹介する。
1
0
0

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
1
0