Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rspec model tests for average rating method

I'm trying to write tests for the following method:

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

Here's what I have so far:

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

end

How can I test that the review_sum variable is calculating the sum correctly, or is the method already fully tested? I'm new at rspec so any help is appreciated!

like image 378
Sara Avatar asked Mar 01 '26 00:03

Sara


1 Answers

To answer directly I suggest you not to:

  • Generate random value of the review rating
  • Copy the method code directly to verify it. You can't score your own paper, don't you?

Instead:

  • Use manually created ratings and calculate the average manually
  • Verify if the method could output what you've calculated.

Further improvement

  • Use FactoryGirl to create test objects.
  • DRY the code

My version(assume FactoryGirl installed)

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
like image 186
Billy Chan Avatar answered Mar 03 '26 14:03

Billy Chan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!