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

202n 年を迎えて尚、 test-unit > rspec なのでは?という再考と、Power Assert は良いぞという話 #33

Closed
kachick opened this issue May 2, 2021 · 6 comments
Labels

Comments

@kachick
Copy link
Owner

kachick commented May 2, 2021

TL;DR

  • 実は今でも test-unit が最強ではないのか?
  • Power Assert はシーンによってマジで強力で、 binding.irb とか binding.pry みたいな事を頻繁にテストコード中でやりたくなるぐらいだったら、 power-assert を使っておくのに良い場面だと思う。(が、少なくとも Ruby の 今の https://github.com/ruby/power_assert には色々制限もあるので、元々の twada さん が提唱した「なんでも PowerAssert」という事にはならないかなと思っている。むしろ部分的に使うべきと言うか。 )

何についてか / About

ref: link, link

経緯 / History

  1. test-unit はとにかく「気軽に書ける」
  2. 反面、気軽に書けすぎて、「これ何をtestしてるんだっけ」みたいなことに数年後なったりする。自分ですらそうなっちゃうわけだから、他の人でも自分の書いたtestを読めるようにするのは確かに結構大変なのかも知れない。 rspec でも description の無い it は書けるわけなので、これは test-unit が悪いわけじゃなくて、ついつい楽な方に行っちゃうよねという程度の話だと思う。そんな test でも無いよりはマシだと思うので、サクサク書けるというのは非常に大きいと思う。 rspec 界隈が ベストプラクティスとして 1 example 内はなるべく 1 matcher にしようみたいな事を言っているのも、 rspec の書きづらさに拍車をかけていると思う
  3. 最近知ったが、今のtest-unitが標準でintegrateしている power-assert が、使い方に注意が必要だったりかなり重い感じはあるものの、ここぞというところに絞って使うととても強力。 rspec でこれを使うようなのは、過去にちょっと試されたみたいだが今メンテされててアクティブな物が無さそう。 => https://github.com/kachick/rspec-matchers-power_assert_matchers 作ってみた
  4. rsepc はとにかく多機能なのが強いけど、そこまでの多機能さが必要なシーンはどれほどあるのかというのと、ブロックの中で全てやろうとしているので Ruby 的にハマる事がある。後、単純にネストした深いブロックが生じやすくて、個人的にそれは Ruby としてバッドプラクティスだと思っている。rspec の思想とかとは別に、実現方法が実は Ruby との相性が良くなかったのではないか?Rubyだからこそ生まれたとも言えそうなので皮肉なものだが。
  5. test-unit は 普通の module やら class やら method 定義やらの感覚がそのまま使えるので、namespace 周りの 悩みが少ない
  6. test-unit も、調べれば最低限欲しいような機能はちゃんとあることが多そう。ただ、その情報を調べるのが大変。 https://abicky.net/2018/04/28/221511/ 例えば rspec 的 に description 渡す機能もあるみたいなので、別に test-unit で BDD 的な書き方をやれないとかそういう時代では無さそう。
  7. minitest は使ったこと無くて、興味もない
  8. contain_exactly とか、rspec の matcher には確かに便利〜というか、それそれみたいなのあるが、じゃあちゃんとその中身を把握してるのか?というとそうでもないわけで、 matcher を追加するのも出来るはするがそっちは若干面倒という認識。 その点 test-unit の assertion を自分で追加するのには何の苦労も無い。既存の assertion の使い方とか古臭さ、少なさみたいなのには正直ちょっと不満を覚えるが、それは後方互換性維持の為に仕方ないんだろうなというのと、そいつらを組み合わせて自分専用のassertionを作る事も簡単なわけで、これは考え方次第なのではと思う。
  9. と色々書いたが、正直所謂PORO?(Plain Old Ruby Object だっけ、なんか酷いネーミングだ)のtestでしか使ったこと無いので、普通の rails アプリケーション test だとどうなるのかとか全然調べてない。 DB と接続してホゲホゲぐらいは多分出来るだろうし、 factory-bot 的なものは再実装するの大して難しく無さそうというかファクトリー定義はどうせ細かくわかれるだろうから、自作するぐらいの心構えは仕方がないと思う。しかし Capybara 使っての feature spec 的なのどうなるんだ?とか全くわからん。でも、仮に難しかったとしてもそれこそ「そういうシーンでだけ」rspecを使うみたいな共存体制を取れば良いだけではないか。

結論 / Conclusion

  • foo
  • bar
  • baz
@kachick kachick added help wanted Extra attention is needed question Further information is requested ruby labels May 2, 2021
@kachick kachick changed the title test-unit は気がるにバシバシ書けるが、 rspec は多くのパターンを書きづらい。しかし rspec の方が多機能だし、数年後とかに読み返しやすい。両方併用するとか出来ないか 2021 年を迎えて再び、 test-unit > rspec なのでは?という再考と、power-assert は良いぞという話 May 16, 2021
@kachick kachick added tips and removed help wanted Extra attention is needed question Further information is requested labels May 16, 2021
@kachick kachick changed the title 2021 年を迎えて再び、 test-unit > rspec なのでは?という再考と、power-assert は良いぞという話 202n 年を迎えて尚、 test-unit > rspec なのでは?という再考と、power-assert は良いぞという話 May 16, 2021
kachick added a commit to kachick/ruby-ulid that referenced this issue May 16, 2021
@kachick kachick changed the title 202n 年を迎えて尚、 test-unit > rspec なのでは?という再考と、power-assert は良いぞという話 202n 年を迎えて尚、 test-unit > rspec なのでは?という再考と、Power Assert は良いぞという話 May 21, 2021
@kachick
Copy link
Owner Author

kachick commented Jun 4, 2021

さて、大昔と比べて test-unit に増えてる機能は Power Assert だけではないわけで、 https://qiita.com/repeatedly/items/727b08599d87af7fa671 で紹介されてる rspec っぽい記法は知っては居るが、そもそもブロックを避けられるなら越したこと無いなと思ってるのであんま使う気になれないな・・・

https://www.clear-code.com/blog/2013/1/23.html
https://test-unit.github.io/test-unit/en/Test/Unit/Data/ClassMethods.html

データ駆動テスト自体は自分も好きなのだけれど、正直 test 数が増える事自体には別に意味を感じられず、each で回して assertion 一杯で良いのでは?と思ってしまう。
そのままだと落ちたときに何がなんだかわからないので、 assetion の最後にメッセージを渡してやる、みたいな工夫は居るが、普通の Ruby コードで表現できるので悪いと思っていない。
というよりも description data や、 rake の desc みたいに、 「直後のメソッド定義に動きかける」系のメタプログラミング全開な機能をあまり好きになれなくて使う気になれないんだよな・・・普通に keyword arguments とかで渡せる方が嬉しい気持ちはある。

@kachick
Copy link
Owner Author

kachick commented Jun 5, 2021

データ駆動テスト用の機能 data 使ってみた。

https://github.com/kachick/string-safe_inspector/blob/3f9958e994d1637fa1f6cbe4e4f867746be05dc2/test/test_string-safe_inspector.rb#L48-L84

「直後のメソッド定義に動きかける」 のは、やっぱりうーんとなるが、それを除けば非常に良い感じだった。
なにより受け渡せるデータの形に縛りが無いのが良い。
Hash の key になれるオブジェクトには制限があるけど、このAPIだと key には文字列だけ、 value には なんでも。なので好き勝手出来る。
今後活用しよう。(手のひらくるりん)

@kachick
Copy link
Owner Author

kachick commented Jun 6, 2021

test-unit の assertion を自分で追加するのには何の苦労も無い

とか言っといてなんだけど、「ちゃんと作る」時には、なんかそれなりの手順が必要そうな雰囲気だ。

https://github.com/test-unit/test-unit/blob/a2106658fe85e79478322e03a33f75977b82c911/lib/test/unit/assertions.rb#L19-L40
https://github.com/test-unit/test-unit/blob/a2106658fe85e79478322e03a33f75977b82c911/lib/test/unit/assertions.rb#L1757-L1766

    ##
    # Test::Unit::Assertions contains the standard Test::Unit assertions.
    # Assertions is included in Test::Unit::TestCase.
    #
    # To include it in your own code and use its functionality, you simply
    # need to rescue Test::Unit::AssertionFailedError. Additionally you may
    # override add_assertion to get notified whenever an assertion is made.
    #
    # Notes:
    #
    # * The message to each assertion, if given, will be propagated with the
    #   failure.
    # * It is easy to add your own assertions based on assert_block().
    #
    # @example Example Custom Assertion
    #
    #   def deny(boolean, message=nil)
    #     message = build_message(message, '<?> is not false or nil.', boolean)
    #     assert_block(message) do
    #       not boolean
    #     end
    #   end
      public
      # Called whenever an assertion is made. Define this in classes
      # that include Test::Unit::Assertions to record assertion
      # counts.
      #
      # This is a public API for developers who extend test-unit.
      #
      # @return [void]
      def add_assertion
      end

ふむふむ、なるほどね(わかってない)

@kachick
Copy link
Owner Author

kachick commented Jun 6, 2021

ruby/csv#216
ruby/rbs#556

とかもそうだけど、 ruby 本家系?が大体 test-unit を好んでいるという印象も昔から合って(なぜ 標準添付の minitest を選ばないのかは、色々あるんだろう)、個人的には rails project 的なので無ければやっぱ test-unit 使っとくのが一番無難なんじゃないのかなとは思っているんだよなぁ

しかし https://github.com/ruby/csv/pull/216/files では EnvUtil を削っていて、え、まさか EnvUtil が test-unit に同梱されてるってこと?なら一択では。と思ったが、そういうわけではないようだ。単に ruby/ruby から fork した時の残りなのかな。まぁ、たしかに普通に考えれば csv の機能テストするときに EnvUtil は要らなさそうだ。

求められる EnvUtil の gem 化 (多分そんな事は起こらないし、その namespace 使ったら怒られが発生しそうだ)

@kachick
Copy link
Owner Author

kachick commented Jun 25, 2022

最近はあんま Ruby 触らないけど、触るときは大体 test-unit か minitest なので rspec 書かなくなってきた。薄い rspec が置いてあると仕様とか確かに読みやすいと思うけど、網羅性広いのとか共通化しだすと test 系のほうが楽な気がする。両方使ってもいいのでは。

@kachick kachick closed this as completed Jun 25, 2022
@kachick kachick removed the tips label Jun 25, 2022
@kachick
Copy link
Owner Author

kachick commented May 2, 2024

求められる EnvUtil の gem 化 (多分そんな事は起こらないし、その namespace 使ったら怒られが発生しそうだ

https://github.com/ruby/test-unit-ruby-core/blob/7b20ceb51631e69471684ffe242a3e3f5e56c760/lib/envutil.rb 経由で使えるようになってた!

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