Search code examples
ruby-on-railsrspecrspec-railsrspec3

and sometimes I get failed spices because of Time.now, can't understand why


so i have a method in model

class << self
  def last_week
    start = Time.zone.now.beginning_of_week - 7.days
    finish = start + 7.days
    where('appointment_at >= ? AND appointment_at < ?', start, finish).order(appointment_at: :desc)
  end
end

And I write spec for this method.

RSpec.describe Appointment, type: :model, vcr: { record: :none } do
  let!(:time) { Time.now }
  let(:appointment_at) { time }

  context '.last_week' do
    let!(:scoped_appointment) { create(:appointment, appointment_at: time - 2.days) }
    let!(:another_appointment) { create(:appointment, appointment_at: time - 16.days) }

    it do
      travel_to(time) do
        expect(Appointment.last_week).to include(scoped_appointment)
        expect(Appointment.last_week).not_to include(another_appointment)
      end
    end
  end
 end

And sometime i get failed this spec with error.

expected #<ActiveRecord::Relation []> to include #<Appointment id: 18, lead_id: 27, body: nil, appointment_at: "2019-02-25 00:59:47", google_id: nil, ... "pending", user_id: 22, notify: nil, cc_emails: nil, appointment_minutes: nil, status_message: nil>
   Diff:
   @@ -1,2 +1,2 @@
   -[#<Appointment id: 18, lead_id: 27, body: nil, appointment_at: "2019-02-25 00:59:47", google_id: nil, created_at: "2019-02-27 00:59:47", updated_at: "2019-02-27 00:59:47", timezone: nil, subject: "Meeting with Lead", address: nil, notification: nil, status: "pending", user_id: 22, notify: nil, cc_emails: nil, appointment_minutes: nil, status_message: nil>]
   +[]

I can't understand why?

And I have a suggestion that I should tightly set time

in spec_helper.rb

$now = DateTime.parse('2020-01-01 00:00:01 -0500')

will it be right? and why ?


Solution

  • Your test setup is brittle. It will break depending on the day of the week you run your spec.

    The scope in your model returns appointments from the previous week, Monday through Sunday (you are calling beginning_of_week and adding 7 days to it)

    So if your tests run on a Wednesday, like in the example you provided, the appointment’s appointment_at field will be set to Monday (since you are calculating it as Time.now - 2.days). That means your scope will not cover that appointment.

    I suggest you use a specific time in your setup. Given your current setup, using let(:time) { DateTime.parse('2019-02-25 00:00:00') } should work