Techioz Blog

テスト データをランダムに生成するのは悪い習慣ですか? [閉まっている]

概要

rspec を使い始めて以来、フィクスチャの概念に問題がありました。私の主な懸念は次のとおりです。

私がやり始めたことの 1 つは、すべてのモデルに #generate_random メソッドを追加することです。この方法は、仕様を実行している場合にのみ使用できます。例えば:

class Item
  def self.generate_random(params={})
    Item.create(
      :name => params[:name] || String.generate_random,
      :price => params[:price] || rand(100)
    )
  end
end

(これを行う具体的な詳細は、実際にはもう少し明確です。すべてのモデルの生成とクリーンアップを処理するクラスがありますが、このコードは私の例としては十分明確です。) したがって、上記の例では、次のようにテストします。が続きます。心のフェイントに対する警告: 私のコードは before(:all) の使用に大きく依存しています。

describe Item do
  describe '#most_expensive' do
    before(:all) do
      @items = []
      3.times { @items << Item.generate_random }
      @items << Item.generate_random({:price => 50})
    end

    it 'should return the most expensive item' do
      sorted = @items.sort { |a, b| b.price <=> a.price }
      expensive = Item.most_expensive
      expensive.should be(sorted[0])
      expensive.price.should >= 50      
    end
  end
end

こうすることで、テストで驚くべき動作がより明らかになります。この方法でデータを生成すると、コードが期待どおりに動作しないというエッジケースに遭遇することがありますが、フィクスチャのみを使用していれば気付かなかったでしょう。たとえば、#most_expensive の場合、複数の商品が最も高価な価格を共有するという特殊なケースの処理を忘れた場合、最初の時点でテストが失敗することがありました。 AutoSpec で非決定的なエラーが発生することを確認すると、何かが間違っていることがわかります。フィクスチャのみを使用していた場合、そのようなバグを発見するまでにさらに時間がかかる可能性があります。

私のテストでは、予想される動作が何であるかをコードで実証するという点でも、少しうまく機能します。私のテストでは、sorted とは、価格の降順に並べ替えられたアイテムの配列であることが明らかです。 #most_expensive がその配列の最初の要素と等しいと予想されるため、most_expensive の予想される動作が何であるかはさらに明らかです。

それともこれは機能しますか?では、これは悪い習慣なのでしょうか?試合に対する私の恐怖心は不合理なものなのでしょうか?モデルごとにgenerate_randomメソッドを記述するのは手間がかかりすぎますか?

解決策

このトピックやリンク先のジェイソン・ベイカーのトピックで誰も言及していないことに驚いた モンテカルロテスト。私がランダム化されたテスト入力を広範囲に使用したのはこの時だけです。ただし、テスト ケースごとに乱数ジェネレーターのシードを一定にすることで、テストを再現可能にすることが非常に重要でした。