Okay, let me clarify that title first. I, as most of you, have two sets of tests for my Rails application: rspec and cucumber. rspec heavily focusses on testing models and business logic while cucumber focusses on testing the entire application stack and user interaction.
The problem is that as your app grows, your test set grows - and so does the time it takes to run those tests.
In my previous article I told you about how I like to tests my scope. There was a fair amount of criticism on that post and after considering it all (and hearing Corey Haines’ talk on Arrrrcamp last friday), I’m convinced it’s the wrong path.
In essence Rails allows you to create a scope to generate a custom database query for you. Now, if you only test your configuration of Rails (as I did in my previous post), you don’t know if that scope works or not.
The content of this post is no longer correct. Please read this article for details.
Testing scopes has always felt a bit weird to me. Normally I’d do something like this:
class Post < ActiveRecord::Base scope :published, where(:published => true) scope :latest, order("created_at DESC") end describe Post do context 'scopes' do before(:all) do @first = FactoryGirl.create(:post, :created_at => 1.day.ago, :published => true) @last = FactoryGirl.create(:post, :created_at => 4.day.ago, :published => false) end it "should only return published posts" do Post.
Today I learned that Ruby garbage collection can be of huge importance to performance. More precisely, if Ruby does a lot of garbage collection it may slow down your code. Running garbage collection only every 10 or 20 seconds when running specs may increase performance dramatically.
At this time specs for Ariejan.net take an average of 25.29s to run. This is not bad, but in my opinion faster specs are better.
I’m currently writing some RSpec tests that use Time.now.
I want my model to calculate a duration and store the future time in the database. I’ve already specced the calculation of the duration, but I also want to spec that everything gets saved correctly. Here’s my first spec:
it "should do stuff" do m = Model.create() m.expires_at.should eql(Time.now + some_value) end This fails.
It fails because Time.now is quite accurate and some milliseconds have passed between the two calls.