我正在尝试为以下方法编写测试:
def average_rating
reviews = self.reviews
review_sum = reviews.inject(0) { |sum, review| sum += review.rating }
avg_rating = (review_sum / reviews.count).to_i unless review_sum == 0
end
这是我到目前为止所拥有的:
describe "#average_rating" do
it "should be nil when there are no reviews" do
api_without_reviews = Api.new name: 'Fake API', description: 'It does something', category: 'Fake category', url: 'http://www.example.com'
api_without_reviews.average_rating.should be_nil
end
it "should calculate average rating properly" do
api_with_reviews = Api.new name: 'Fake API', description: 'It does something', category: 'Fake category', url: 'http://www.example.com'
api_with_reviews.save
api_with_reviews.reviews.create rating: Random.rand(1..5), thoughts: 'blah'
api_with_reviews.reviews.create rating: Random.rand(1..5), thoughts: 'blah'
average = api_with_reviews.reviews.inject(0) { |sum, review| sum += review.rating } / api_with_reviews.reviews.count
api_with_reviews.average_rating.should eq average
end
端
如何测试review_sum变量是否正确计算总和,或者方法是否已经过全面测试?我是rspec的新人,所以感谢任何帮助!
答案 0 :(得分:2)
直接回答我建议你不要:
相反:
我的版本(假设已安装FactoryGirl)
describe "API" do
describe "average_rating" do
# Use "before" but not "let" because this var must be clean in every example
before { @api = FactoryGirl.create(:api) }
it "should be nil when there are no reviews" do
@api.average_rating.should be_nil
end
it "should calculate average rating properly" do
[1, 5].each do |r|
FactoryGirl.create(:review, rating: r, api: @api)
end
@api.average_rating.should eq(3)
end
end
end
# spec/factories.rb
FactoryGirl.define do
factory :api do
name 'Fake API'
description 'It does something'
category 'Fake category'
url 'http://www.example.com'
end
factory :review do
rating rand(1..5)
thoughts "blah"
api #Association: belongs_to API
end
end
答案 1 :(得分:0)
如果你不想安装和设置factorygirl(我建议你将来使用它,它在测试和开发控制台中都非常有用,它可以大大简化创建很多对象必需的属性),这里有一些代码。这也使用了新的rspec语法,其中'expect'比'should'更受青睐。
describe "API" do
describe "Method: average_rating" do
before(:each) do
@api = Api.create(:attributes => "some value")
end
it "is nil when there are no reviews" do
expect( @api.average_rating ).to be_nil
end
it "calculates average rating properly" do
ratings_sum = 0
5.times do |rating_value|
@api.ratings << Rating.new(:rating => rating_value, :thoughts => "lorem ipsum")
ratings_sum += rating_value
end
ratings_average = ratings_sum / @api.ratings.count
expect( @api.average_rating ).to eq( ratings_average )
end
end
end
答案 2 :(得分:0)
我认为没有必要使用FactoryGirl进行此测试。您并没有真正测试数据库的任何内容。您只想为对象设置状态,然后测试方法的结果。
根据您设置测试的方式,我认为您走在正确的轨道上。使用RSpec 2.13和Ruby 1.9.3,这就是我编写测试的方法。
describe Api do
subject(:api) { Api.new name: 'API Under Test', description: 'Testing' }
describe "requesting the average rating" do
context "with no reviews" do
it { expect(api.average_rating).to be_nil }
end
context "with one or more reviews" do
it "is the standard average of the review ratings rounded down" do
api.reviews = [
Review.new(rating: 1, thoughts: 'test review 1'),
Review.new(rating: 2, thoughts: 'test review 2'),
Review.new(rating: 5, thoughts: 'test review 3'),
]
expect(api.average_rating).to eq 2
end
end
end
end
一些跟进点:
context
,但是,我这样做是为了在设置上提供更多语义(而不是您希望测试证明的内容); context
==设置,it
==测试结果let
。这里的优点是您提供了被测对象let
并且命名为subject
为您提供了一种定义在测试中使用的备忘变量的方法@api
版本的实例变量,因为它可以在以后更改时提供更大的灵活性,而无需更新所有测试(请参阅barewords)