A Good Spec Should Be Easy to Read

Submitted by swarut on Thu, 06/21/2012 - 14:46

I am working on a test-intensive project. Yesterday, I just implement one spec for the code I just wrote. However, I made a very big mistake. Here is a part of the spec code.

  1. it 'should set iCal alarms based on user preferences' do
  2.   user.prefs = User.default_preferences
  3.   user.save!
  4.  
  5.   EventRsvp.make!(user: user, event: event, joining: 'Y')
  6.  
  7.   alarms = subject.alarms
  8.   alarms.should_not be_empty
  9.   alarms.first.description.should eq event.title
  10.   alarms.first.action.should eq 'DISPLAY'
  11.   alarms.first.trigger.should eq '-PT15M'
  12.  
  13.   feed.events.inject(0){ |count, item| count += item.alarms.present? ? 1 : 0}.should == 1
  14. end

The thing I miss is that the code is hard to read. It took one a while to understand what the last statement feed.events.inject(0){ |count, item| count += item.alarms.present? ? 1 : 0}.should == 1 does. As spec is a description of the software behavior, other people who are not the code owner should be able to read and understand it easily. This is an important objective, and I broke it T_T. Finally, I got my code improved by my senior. Here is the better one he made.

  1. conntext 'given user has iCal reminder preference enabled' do
  2.   subject { decorated.to_ics(user) }
  3.   before(:each) do
  4.     user.prefs = User.default_preferences.merge(
  5.       ical_notifications: { user_notification: true }
  6.     )
  7.     user.save!
  8.   end
  9.  
  10.   context 'and RSVPed to the event' do
  11.     before { EventRsvp.make!(user: user, event: event, joining: 'Y') }
  12.     it 'should set feed alarms' do
  13.       alarms = subject.alarms
  14.       alarms.should_not be_empty
  15.       alarms.first.description.should eq event.title
  16.       alarms.first.action.should eq 'DISPLAY'
  17.       alarms.first.trigger.should eq '-PT15M'
  18.     end
  19.   end
  20.   context 'and did not RSVP to the event' do
  21.     it 'should not set feed alarms' do
  22.       alarms = subject.alarms
  23.       alarms.should be_empty
  24.     end
  25.   end
  26. end