web-dev-qa-db-ja.com

assert()メソッドをRubyのKernelクラスに追加するのは慣用的なRuby?

Kent BeckのxUnitに相当するものをRubyでコーディングすることで、Rubyの理解を広げています。 Python(Kentが書いている)には、広く使用されている言語のassert()メソッドがあります。 Rubyはサポートしていません。これを追加するのは簡単だと思いますが、カーネルはそれを置くのに適した場所ですか?

ところで、RubyのさまざまなUnitフレームワークの存在を知っています-これは、「何かを成し遂げる」のではなく、Rubyのイディオムを学ぶための演習です。

72

いいえ、ベストプラクティスではありません。 Rubyのassert()に最もよく似ているのは、

 raise "This is wrong" unless expr

より具体的な例外処理を提供したい場合は、独自の例外を実装できます

95
Julik

Rubyでアサートを使用することは完全に有効だと思います。しかし、あなたは2つの異なることに言及しています:

  • xUnitフレームワークは、テストの期待値を確認するためにassertメソッドを使用します。アプリケーションコードではなく、テストコードで使用することを目的としています。
  • C、Java、Pythonなどの一部の言語には、プログラムのコード内で使用することを目的としたassert構造が含まれており、整合性についての仮定を確認します。これらのチェックは、コード自体の内部に構築されます。これらはテスト時のユーティリティではなく、開発時のユーティリティです。

私は最近 solid_assert:Rubyアサーションユーティリティを実装する小さなRubyライブラリ動機を説明する私のブログの投稿 を書きました。次の形式で式を記述します。

assert some_string != "some value"
assert clients.empty?, "Isn't the clients list empty?"

invariant "Lists with different sizes?" do
    one_variable = calculate_some_value
    other_variable = calculate_some_other_value
    one_variable > other_variable
end    

そして、それらを無効化して、assertinvariantが空のステートメントとして評価されるようにすることができます。これにより、本番環境でのパフォーマンスの問題を回避できます。ただし、 The Pragmatic Programmers を無効化しないことをお勧めします。それらがパフォーマンスに実際に影響する場合にのみ、それらを非アクティブ化する必要があります。

慣用的なRubyの方法は通常のraiseステートメントを使用しているという回答については、表現力に欠けると思います。アサーティブプログラミングの黄金律の1つは、通常の例外処理にアサーションを使用しないことです。それらは2つのまったく異なるものです。それらの2つに同じ構文を使用する場合、コードはより不明瞭になると思います。そしてもちろん、それらを無効にする機能は失われます。

アサーションを使用するのは良いことだと確信できます。なぜなら、 The JourneymanからMasterへのプラグマティックプログラマー および Code Complete のような必読の古典本を2つ読んでお勧めするからです。それらの使用。 Programming with assertions というタイトルのNice記事もあります。これは、アサーティブプログラミングの内容とその使用方法を非常によく説明しています(Javaに基づいていますが、概念はどの言語にも適用されます)。

28
jmanrubia

カーネルモジュールにassertメソッドを追加する理由は何ですか?なぜAssertionsなどと呼ばれる別のモジュールを使用しないのですか?

このような:

module Assertions
  def assert(param)
    # do something with param
  end

  # define more assertions here
end

アサーションを本当に利用可能にする必要がある場合everywhere次のようにします:

class Object
  include Assertions
end

免責事項:コードはテストしませんでしたが、原則としてこのようにします。

14

特に慣用的ではありませんが、良いアイデアだと思います。特に次のようにした場合:

def assert(msg=nil)
    if DEBUG
        raise msg || "Assertion failed!" unless yield
    end
end

そうすれば、DEBUG(または他の便利なスイッチ、私は過去にKernel.do_assertを使用した)セットで実行しないことにした場合、影響はありません。

6
regularfry

私の理解では、Rubyに慣れる方法として、独自のテストスイートを作成しているということです。 Test :: Unitはガイドとして役立つかもしれませんが、おそらくあなたが探しているものではありません(すでに仕事を終えているからです)。

そうは言っても、Pythonのアサートは(少なくとも私には)Cの assert(3) に似ています。ユニットテスト用に特別に設計されたものではなく、「これは絶対に起こらない」ケースをキャッチするためのものです。

Rubyの組み込みユニットテストが問題を表示する傾向は、個々のテストケースクラスが TestCase のサブクラスであり、それが何であったかを検証する「アサート」ステートメントを含むことです。それに渡され、レポートのために記録されます。

4
Atiaxi