私は仕事中に最初のmodel spec
タスクを開始しました。多くのフィーチャー・スペックを書いた後で、(スペックを考慮しないで)モデル・スペックを書くという異なる視点に入るのは難しいです。私は私が経験していた難しさを説明するために、一例として、Order
モデルの方法を取るよ:Rails:このメソッドのモデル仕様を書くには?
def update_order_prices
self.shipping_price_cents = SHIPPING_PRICE_CENTS unless shipping_price_cents
return if order_lines.empty?
self.total_price_cents = calculate_order_price
self.total_line_items_price_cents = calculate_total_order_line_price
self.total_tax_cents = calculate_tax_amount
end
EDITのTLを、DR
を私は単に私を書き込み、その答えと完全に満足していますこのメソッドの仕様残りの投稿はこれまでに試したことを示していますが、この質問に答える必要はありません。
最初のアプローチ:まず
私がテストするために何を知りませんでした。私はメソッドが呼び出された時と場所を見つけようとしました。そして、このメソッドで触れられている属性がどのようなものであるべきかを知るシナリオを見つけることを試みました。要するに、私は文脈を理解しようと多くの時間を費やした。その後、同僚は、モデル仕様のメソッドをコンテキストに関係なく独立してテストする必要があると述べました。私はすべてのケースを特定していることを確認するだけです。だから、だろう、この方法は:(まだ行っていない場合)
- それはorder_linesが
- 空の場合、ORDER_LINEが
現在のアプローチ:
私はこれらの点のテストを書いてみましたが、まだ疑問が生じ:
テスト1
it 'sets shipping price cents to default (if not done already)' do
order.shipping_price_cents = nil
order.update_order_prices
expect(order.shipping_price_cents).to eq(Order::SHIPPING_PRICE_CENTS)
end
私は右のこの1つを得たと確信していますが、私が間違っていることを証明して自由に感じます。私はshipping_price_centsをnilに設定してそれを設定するコードをトリガし、セントでテストされたメソッドをモデルで定義されているデフォルト値と同じように呼び出します。
テスト2
it 'returns early if order_lines is empty' do
expect(order.update_order_prices).to eq(nil)
end
だからここで私はorder_lines
協会にはオブジェクトが存在しない場合にメソッドが早く返すことをテストします。私はそれを行うための手がかりを持っていなかったので、私はコンソールに入って、注文を受け取り、それに関連したorder_linesを削除し、返されるものを見てメソッドを呼び出しました。
2.3.1 :011 > o.order_lines
=> #<ActiveRecord::Associations::CollectionProxy []>
2.3.1 :012 > o.update_order_prices
=> nil
は、その後、関連するORDER_LINEでのご注文のために同じことをやった:
2.3.1 :017 > o.update_order_prices
=> 1661
だから私は、返される 'nil' のためにテストしました。しかし、私は正しいことをテストしているようには感じません。
試験3
it 'sets (the correct?) values if order_line is set' do
order_line = create(:order_line, product: product)
order = create(:order, order_lines: [order_line])
order.update_order_prices
expect(order.total_price_cents).to eq(order.calculate_order_price)
expect(order.total_line_items_price_cents).to eq(order.calculate_order_line_price)
expect(order.total_tax_cents).to eq(order.calculate_tax_amount)
end
Iは、単に属性が、私は外見てはいけないように、それらは、実際の値を使用せずに設定されるものと等しいことをテスト。もし私が絶対値をテストしたいのであれば、この関数の外で調べて、メソッドをテストしないでOrderオブジェクトのステータスなどを調べなければなりません。テストので
Failures:
1) Order Methods: #update_order_prices sets (the correct?) values if order_line is set
Failure/Error: expect(order.total_price_cents).to eq(order.calculate_order_price)
NoMethodError:
private method `calculate_order_price' called for #<Order:0x007ff9ee643df0>
Did you mean? update_order_prices
、渡された最初の2つのテストを実行する
、3つ目はしませんでした。この時点で私は少し失われて、経験豊かな開発者がこの一見単純なテストをどのように書いているか聞いてもらいたいです。私はあなたがupdate_order_prices
後に期待している正確な値に対して仕様にあると思い
おかげ
私はアプリの状態をテストしていませんか? – Flip
いいえ、前に定義した前提条件で呼び出されたメソッドの正しい結果を指定するだけです。これは、あなたのアプリでは、注文ラインに関連する可能性のある製品は100ユーロですが、(モデル/ユニット)仕様では1ユーロに設定し、結果が期待どおりであることを確認することを意味します。状態は統合仕様でテストされます。 – basiszwo