rspec を使い始めて以来、フィクスチャの概念に問題がありました。私の主な懸念事項は次のとおりです。
テストを使用して、驚くべき動作を明らかにします。私は、テストしている例について考えられるすべてのエッジ ケースを列挙できるほど賢いわけではありません。ハードコードされたフィクスチャの使用は、私が想像した非常に特殊なケースでコードをテストするだけなので、制限があるようです。(確かに、どのケースをテストするかに関しては、私の想像力にも限界があります。)
コードのドキュメントの形式としてテストを使用します。ハードコーディングされたフィクスチャ値がある場合、特定のテストが何を実証しようとしているのかを明らかにするのは困難です。例えば:
describe Item do describe '#most_expensive' do it 'should return the most expensive item' do Item.most_expensive.price.should == 100 # OR #Item.most_expensive.price.should == Item.find(:expensive).price # OR #Item.most_expensive.id.should == Item.find(:expensive).id end end end
最初の方法を使用すると、最も高価なアイテムが何であるかが読者に示されず、その価格が 100 であることがわかります。3 つの方法はいずれも、そのフィクスチャ
:expensive
が にリストされている最も高価なものであると信じるよう読者に求めますfixtures/items.yml
。Item
不注意なプログラマーは、 inを作成before(:all)
したり、別のフィクスチャを に挿入したりして、テストを中断する可能性がありfixtures/items.yml
ます。それが大きなファイルである場合、問題の原因を突き止めるのに長い時間がかかる可能性があります。
私が始めたことの 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
場合、複数のアイテムが最も高価な価格を共有するという特別なケースを処理するのを忘れると、最初の でテストが失敗することがありましたshould
。AutoSpec で非決定論的な失敗を見ると、何かが間違っているという手がかりが得られます。フィクスチャだけを使用していた場合、そのようなバグを発見するのにさらに時間がかかる可能性があります。
また、私のテストでは、予想される動作がどのようなものかをコードで示すという、わずかに優れた仕事もしています。私のテストでは、sorted が価格の降順で並べ替えられたアイテムの配列であることが明らかになりました。その配列の最初の要素と等しいと予想#most_expensive
しているので、 の予想される動作がさらに明確になりmost_expensive
ます。
それで、これは悪い習慣ですか?固定具に対する私の恐怖は不合理なものですか? モデルごとにメソッドを書くのはgenerate_random
大変ですか? または、これは機能しますか?