Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test-unit/minitest と rspec の最大の違いは「比較時のレシーバ にどちらを取るか」 なのかなと今更思った話 #123

Closed
kachick opened this issue Jun 8, 2021 · 2 comments
Labels

Comments

@kachick
Copy link
Owner

kachick commented Jun 8, 2021

rspec は BDD ツールなのだとか、そういう話は全部置いておいて、「ユニットテストの為の道具」として見た時の話だが、これは意識してこなかったけど大差だなぁと思ったのが #103 をやる中であった。

まぁ全部が全部そうかは知らない、 test-unit でも、 test-unit/test-unit#181 こういうことはあった。
でも普通に考えて一番基本的な物が何かと言えば多分

  • test-unit/minitest - assert_equal assertion
  • rspec - eq matcher

だと思っている。
思っているのだが、定義を見ると大違いだ。

https://github.com/test-unit/test-unit/blob/90a03fbeb11cddc1015b134469f0006d934aeb83/lib/test/unit/assertions.rb#L244

          assert_block(full_message) { expected == actual }

https://github.com/seattlerb/minitest/blob/f4f57afaeb3a11bd0b86ab0757704cb78db96cf4/lib/minitest/assertions.rb#L218

      result = assert exp == act, msg

https://github.com/rspec/rspec-expectations/blob/040d1b0bba83031c9ae432fd3a4462fdd1cc74e7/lib/rspec/matchers/built_in/eq.rb#L35

          actual == expected

なんと、rsepc に関してはレシーバが逆なのである。

お前一応 rubinius & ruby/spec のコミッタじゃないのか!とか言われると 🙇 なのだが、今更気になって mspec(ruby/spec が使ってる、古代の少機能な rspec みたいなやつ。) の定義も見てみた。

https://github.com/ruby/mspec/tree/0091e8a62e954717cd54641f935eaf1403692041/lib/mspec/matchers eq がない・・・

とりあえず equal matcher はやっぱこの順だよな・・・

https://github.com/ruby/mspec/blob/0091e8a62e954717cd54641f935eaf1403692041/lib/mspec/matchers/equal.rb#L6-L9

  def matches?(actual)
    @actual = actual
    @actual.equal?(@expected)
  end

というところで、 使用例側見て思い出した。そうだ、 eq とかじゃなくて == 使ってるんだった・・・ should だからね・・・
ということはこれか

https://github.com/ruby/mspec/blob/0091e8a62e954717cd54641f935eaf1403692041/lib/mspec/matchers/base.rb#L13-L36

  def ==(expected)
    method_missing(:==, expected)
  end

  def method_missing(name, *args, &block)
    result = @actual.__send__(name, *args, &block)
    unless result
      ::SpecExpectation.fail_predicate(@actual, name, args, block, result, "to be truthy")
    end
  end

やっぱり rspec と同じ、 actual 側が レシーバになっている。

これは、メソッドを自在に定義可能な Ruby では大差だと思っていて、意味合いが全く違う。
どちらが良いのか悪いのかと聞かれて自分ごときが答えられる気はしないし、それぞれが深い考慮の上でこうしているのだろうが、個人的には expected 側がレシーバになるほうが 堅い と思っている。

勿論どんな spec を書くかにも依るとは思っていて、 expect(array.size).to eq(42) みたいな、Rubyの built-in なオブジェクト同士で比較するなら、まぁ問題にはならないと思う。
でも expect(described_class.new).to eq(something) みたいな spec を書いたとしたら、それって実際には actual の == 挙動自体 をテストしているようなもので、それって本当にやりたいこと・・・?と思ってしまうのだ。

いやー、ちょっとrspecがこういう設計にした理由を知りたいなと思ったのと、個人的に仕事でのアプリケーション開発みたいなところ以外のplain rubyなgemのtest書く時にはやっぱ rspec 避けようかなぁと思った次第である。(別に dis って無いよ!)

@kachick kachick added the ruby label Jun 8, 2021
@kachick kachick closed this as completed Jun 8, 2021
@kachick
Copy link
Owner Author

kachick commented Jun 8, 2021

他の言語とも比べてみようと思って jest とか go とか見に行こうとして https://github.com/facebook/jest/blob/bc50e7f360ab1845abbaa0b3ad788caead0d3174/packages/expect/src/matchers.ts#L82 を眺めて、ほー === を直に使わずに Object.is なんだ? と、脇道にそれたところで気づいたが、 Ruby とは言語自由度みたいなのが違いすぎるから比較対象にならんなと思った・・・

ということはなんだ、全く詳しくないけど、Smalltalk とかと比べると良いのかな?
CUI ベースの GNU Smalltalk の repository は本来 GitHub じゃないらしいのだが、ゆとりなので そういうのよくわからない。
2018年で更新止まってて怪しいが、mirror を見てみる。 https://github.com/gnu-smalltalk/smalltalk

https://github.com/gnu-smalltalk/smalltalk/blob/dfe4b5660037c4d178853ee00458a75e51a88563/tests/arrays.ok 全くわからない・・・ 🙌
そもそも syntax highlight が効かない時点で、ゆとりの自分には・・・

https://ja.wikipedia.org/wiki/SUnit Kent Beck が書いたということで、この SUnit というものが原点っぽいな。GNU Smalltalk でも紹介されてる https://www.gnu.org/software/smalltalk/manual/html_node/SUnit.html (ここまで来ると考古学だ・・・)

https://github.com/gnu-smalltalk/smalltalk/blob/dfe4b5660037c4d178853ee00458a75e51a88563/packages/sunit/SUnit.st 多分これだと思うのだが、ぶっちゃけ「読めない」

どちらかというと、Ruby の書籍よりサクサクSmalltalkオブジェクト指向っぽいものの雰囲気を掴んだような事言っといてなんだが、実際の Smalltalk 全く読み書きできないんだよね。完全にイキってしまっていた。 🙇

そのうち学ぶ・・・

@kachick
Copy link
Owner Author

kachick commented Jul 1, 2022

https://eslint.org/docs/latest/rules/yoda
rubocop/rubocop#4145

Yoda condition と言って嫌う向きがあるのは知ってるけど、ことメソッドコールの意味合いが大きく変わる言語ではスタイル云々では無い気もするんだけど・・・

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant