Testing Impressionist with RSpec

On Bloopist, my blogging platform, I use the Ruby Gem Impressionist to track how many views each post gets. I've been experimenting with adding tests to Bloopist's code base. I want to make it less likely that adding a feature will break the site.

One particular feature that broke was the Popular Posts box. The Popular Posts box is supposed to show a blog's posts that got the most views. This feature broke once when I refactored some code. I thought that was the perfect time to add another test to the Bloopist code base. I wrote a test to make sure that the posts in the popular posts box were in fact the posts with the most views. Obviously this test failed when I wrote it. Then I fixed the feature, and my test started passing. I pushed the updates to the site, and voila, the feature was working again.

Here's my setup for getting tests with Impressionist to work with RSpec. Please comment if you see any ways this can be improved.

(Note: I use the Faker gem to create random dummy data for my database objects during testing.)

# spec/models/blog_spec.rb

require 'spec_helper'
require 'rails_helper'

describe "Blog" do

  # ...

  context "with posts" do
    before :each do
      @user = FactoryGirl.create(:user_with_blog)
      @blog = @user.blogs.first
      @posts = 10.times.map{FactoryGirl.create(:post_with_impressions, author: @user, blog: @blog)}
    end
    it "returns popular posts" do
      popular_posts = @blog.popular_posts
      last_impression_count = popular_posts.first.impressions_count
      popular_posts.each do |post|
        expect(post.impressions_count).to be <= last_impression_count
        last_impression_count = post.impressions_count
      end
    end
  end
end
# spec/factories.rb

FactoryGirl.define do

  factory :user do
    email {Faker::Internet.email}
    username {Faker::Internet.user_name}
    password {Faker::Internet.password}
    factory :user_with_blog do
      after(:create) do |user|
        blog = create(:blog)
        create(:blog_permission, user: user, blog: blog)
      end
    end
  end

  factory :blog do
    name {"#{Faker::Book.author}'s Blog"}
    subdomain {Faker::Lorem.word}
  end

  # ...

  factory :post do
    title {Faker::Book.title}
    body {Faker::Lorem.paragraphs.join("\n\n")}
    association :author, :factory => :user
    association :blog
    published_at {Faker::Time.between(DateTime.now - 1, DateTime.now + 1)}
    factory :post_with_impressions do
      after(:create) do |post|
        rand(10).times do
          create(:impression, impressionable: post)
        end
      end
    end
  end

  factory :impression do
    impressionable factory: :post
    request_hash {Faker::Lorem.characters(10)}
    session_hash {Faker::Lorem.characters(10)}
    ip_address {Faker::Internet.ip_v4_address}
    created_at {Faker::Time.between(DateTime.now - 1, DateTime.now)}
  end

end

Photo by Mike Steele