2

少し前に Ruby を学ぶことを決めたとき、単体テストと TDD 方法論を使い始めることも決めました。私は Test::Unit の使用を開始し、いくつかの非常に小さなクラスを作成して、一般的な単体テスト、特に Ruby と Test::Unit の感触をつかみました。

これまでのところ、すべてが非常に簡単でしたが、入力と出力だけが変更された 20 個のテストがあったため、nUnit の TestCase に似たものを実行したいと考えました。

コードは次のようになります。

def test_2_inserted_return_true
    actual = @prime_generator.is_prime?(2)
    assert_equal(true, actual)
  end

  def test_3_inserted_return_true
      actual = @prime_generator.is_prime?(3)
      assert_equal(true, actual)
    end

  def test_5_inserted_return_true
    actual = @prime_generator.is_prime?(5)
    assert_equal(true, actual)
  end

これは、DRY の観点からは非常に恐ろしいことです。私が望むのは、nUnit の TestCase に似たものです。

このようなもの:

[TestCase(2.5d, 2d, Result=1.25d)]
[TestCase(-2.5d, 1d, Result = -2.5d)]
public double ValidateDivision(double numerator, double denominator)
{
    var myClass = new MyClass();
    return myClass.Divide(numerator,denominator);
}

グーグルを試してみましたが、Test::Unit について何も見つかりませんでした。RSpec と Selenium でいくつか見つけましたが、それはあまり役に立ちません。ここでも検索してみましたが、何も見つかりませんでした。

テストメソッドにパラメーターを持たせることを考えましたが、そのようにメソッドを再度定義します...それについては満足していません。その上、私の記憶が正しければ、それは不可能でした (私は今テストすることができませんし、することもできません)。

だから、私の質問は: Ruby (1.9.2) で Test::Unit を使用してデータ駆動型のテストを行うことは可能ですか? そうでない場合、どのフレームワークがそれを行うことができますか?

4

3 に答える 3

4

古き良きループを忘れないようにしましょう。

def test_that_the_first_few_primes_are_detected_as_prime
  [2, 3, 5, 7, 11, 13, 17].each do |p|
    assert @primality_tester.prime?(p)
  end
end

メタプログラミングを使用して個別のテスト メソッドを定義する人もいますが、この場合はやり過ぎだと思います。

[2, 3, 5, 7, 11, 13, 17].each do |p|
  define_method :"test_that_#{p}_is_detected_as_prime" do
    assert @primality_tester.prime?(p)
  end
end

一般的に、テストは DRY であるべきではないと思います。それらは DAMP (説明的で意味のあるフレーズ) である必要があります。結局のところ、テストはあなたの仕様書であり、あなたのドキュメントであり、Ruby やプログラミング全般に精通していない人にも読まれます。したがって、特に上記のように少しクリーンアップした場合、元の例が悪いかどうかさえわかりません。

def test_that_2_is_detected_as_prime
  assert @primality_tester.prime?(2)
end

def test_that_3_is_detected_as_prime
  assert @primality_tester.prime?(3)
end

def test_that_5_is_detected_as_prime
  assert @primality_tester.prime?(5)
end

これが私がしたことです:

  • テストの名前を変更する: テスト名は完全な文を形成し、テストが何をするかを単純に言い直すものではありません。
  • assertの代わりに使用assert_equal: が等しいかどうかをチェックすることはtrue、とにかく良い考えであることがほとんどなく、結果が真実であることをassert 既にチェックしています。
  • @prime_generator名前をに変更します。これは素数を生成@primality_testerしないため、数値が素数かどうかのみをチェックします。
  • 質問はすでに疑問符によって暗示されているため、名前を just に変更is_prime?しますprime?
  • 最後になりましたが、重要なこととして、書式設定を修正します。書式設定が標準の Ruby コーディング規則と矛盾しているだけでなく、それ自体でも一貫していなかったからです。

ただし、IMO の最適なソリューションは次のようなものです。

def test_that_the_first_few_primes_are_detected_as_prime
  assert @primality_tester.prime?(2)
  assert @primality_tester.prime?(3)
  assert @primality_tester.prime?(5)
end

そこには重複がありますが、テストを読みやすく、発音可能にするために必要なのは重複です。DRY は、進化して拡張される製品コードにとっては優れた原則ですが、テストの場合、DRY は常に DAMP とバランスを取る必要があります。(カスタム アサーションを書くのは理にかなっているかもしれませんが、私はそれを疑っています。少なくとも、常にヒントとなる適切な名前を思い付くことができません。)

まったく異なるアプローチは、Haskell の QuickCheck や .NET の Pex に似たプロパティ ベースのチェックです。RushCheckと呼ばれる QuickCheck の Ruby ポートがありますが、2006 年からメンテナンスされておらず、数週間前にメンテナンスが開始されたばかりで、Ruby の最近のバージョンに対応するためにはまだ多くの作業が残っています。

于 2011-04-06T13:29:00.397 に答える
2

単体テスト用に rspec を確認する必要があります。

require 'prime'

describe "Numbers List" do
  [2, 3, 5, 7, 11, 13, 17].each do |i|
    it "#{i} is prime" do
      i.prime?
    end
  end
end

歩留まり:

scratch-1.9.2> rspec -cfn primes.rb 

Numbers List
  2 is prime
  3 is prime
  5 is prime
  7 is prime
  11 is prime
  13 is prime
  17 is prime

Finished in 0.00146 seconds
7 examples, 0 failures
于 2011-04-06T22:27:31.743 に答える