RSpec の described_class を試してみた
RSpec の described_class
は普段使わないんですがいろいろと試してみました。
described_class
とは
described_class
とはその名の通り describe
に渡したクラスを返すメソッドになります。
require "rspec"
describe Array do
it do
pp described_class
# => Array
end
end
単に describe
に渡した値が返ってくるだけなのかな?と思ったらそうでもなかった。
モジュールを渡した場合
described_class
という名前なんですがモジュールを渡した場合には module
が返ってきます。
require "rspec"
describe Enumerable do
it do
pp described_class
# => Enumerable
end
end
文字列を渡した場合
文字列を渡した場合は nil
が返ってくるみたいですね。
require "rspec"
describe "String" do
it do
pp described_class
# => nil
end
end
class / module
以外だと nil
を返すんですかね…?
数値や配列を渡した場合
と思ったんですが数値や配列の場合はその値を返してきてたので文字列だけが特別なのかも?
require "rspec"
describe 42 do
it do
pp described_class
# => 42
end
end
describe [1, 2, 3] do
it do
pp described_class
# => [1, 2, 3]
end
end
describe :Symbol do
it do
pp described_class
# => :Symbol
end
end
described_class
は何を返している?
described_class
は内部で self.class.metadata[:described_class]
の値を返しているみたい。
require "rspec"
describe Array do
it do
pp self.class.metadata
# => {block: #<Proc:0x000073d2cc9efad0 /tmp/vE0nmCZ/63:3>,
# description_args: [Array],
# description: "Array",
# full_description: "Array",
# described_class: Array,
# file_path: "/tmp/vE0nmCZ/63",
# line_number: 3,
# location: "/tmp/vE0nmCZ/63:3",
# absolute_file_path: "/tmp/vE0nmCZ/63",
# rerun_file_path: "/tmp/vE0nmCZ/63",
# scoped_id: "1"}
end
end
じゃあ described_class
の値はどう取得してリウのかというと https://github.com/rspec/rspec-core/blob/aec5f49485d97908183dbe790a7fefb8baaa8091/lib/rspec/core/metadata.rb#L304-L309 のあたりで取得しているみたいですかね?
def described_class
candidate = metadata[:description_args].first
return candidate unless NilClass === candidate || String === candidate
parent_group = metadata[:parent_example_group]
parent_group && parent_group[:described_class]
end
NilClass
と String
のときのみだけ特殊な動きになってそう。
describe
がネストしている場合はどうなるのか
describe
ネストしている場合は内側の値を返します。
require "rspec"
describe Array do
describe String do
it do
pp described_class
# => String
end
end
end
ただし、文字列の場合は nil
ではなくてその外側の describe
を返すので注意してください。
require "rspec"
describe Array do
describe "String" do
it do
pp described_class
# => Array
end
end
end
多分 describe
がネストするときは describe "#hoge"
みたいにメソッド名などを提議することが多いのでその対応として String
が特別になっているんですかねー。
require "rspec"
describe Array do
describe "#size" do
it do
# この場合は外のクラスを参照するようにしている
pp described_class
# => Array
end
end
end
Discussion