Rails testing: Thay đổi thời gian với TimeHelpers
Vấn đề Hãy tưởng tượng bạn đang test ứng dụng Rails của mình với RSpec, bạn cần di chuyển thời gian đến tương lai hoặc quá khứ để test các chức năng của mình. Bạn biết rằng Timecop có đầy đủ những thứ bạn cần về thời gian nhưng bạn cũng mới nghe về 1 module được xây dựng sẵn từ Rails 4.1 tên ...
Vấn đề
Hãy tưởng tượng bạn đang test ứng dụng Rails của mình với RSpec, bạn cần di chuyển thời gian đến tương lai hoặc quá khứ để test các chức năng của mình. Bạn biết rằng Timecop có đầy đủ những thứ bạn cần về thời gian nhưng bạn cũng mới nghe về 1 module được xây dựng sẵn từ Rails 4.1 tên ActiveSupport::Testing::TimeHelpers đáp ứng đầy đủ những thứ bạn cần. Bạn sẽ quyết định sẽ dùng gem Timecop hay sử dụng module kia?
Để có câu trả lời cho riêng mình, chúng ta hãy cũng tìm hiểu về module TimeHelpers nhé!
Các method của Timehelpers
travel(duration, &block)
Thay đổi thời gian hiện tại thành thời gian trong tương lai hoặc trong quá khứ bằng khoảng cách đến Time.now, Date.today và DateTime.now
Time.current # => Tue, 23 Jan 2018 22:13:47 JST +09:00 travel 1.day Time.current # => Wed, 24 Jan 2018 22:14:20 JST +09:00 Date.current # => Wed, 24 Jan 2018 DateTime.current # => Wed, 24 Jan 2018 22:14:20 +0900
Phương thức này cũng chấp nhận một block, nó sẽ trả về thời gian ban đầu ở cuối block:
Time.current # => Wed, 24 Jan 2018 22:14:20 JST +09:00 travel 1.day do User.create.created_at # => Wed, 24 Jan 2018 22:14:44 JST +09:00 end Time.current # => Tue, 23 Jan 2018 22:17:28 JST +09:00
travel_back() Trả về thời gian ban đầu bằng cách xóa các phần khai báo được thêm vào bởi travel và travel_to
Time.current # => Tue, 23 Jan 2018 22:18:10 JST +09:00 travel_to Time.zone.local(2015, 11, 24, 01, 04, 44) Time.current # => Tue, 24 Nov 2015 01:04:44 JST +09:00 travel_back Time.current # => Tue, 23 Jan 2018 22:19:23 JST +09:00
travel_to(date_or_time) Thay đổi thời gian hiện tại thành thời gian cho trước bằng cách bỏ Time.now, Date.today và DateTime.now để trả lại thời gian hoặc ngày được truyền vào phương thức này.
Time.current # => Tue, 23 Jan 2018 22:20:01 JST +09:00 travel_to Time.zone.local(2015, 11, 24, 01, 04, 44) Time.current # => Tue, 24 Nov 2015 01:04:44 JST +09:00 Date.current # => Tue, 24 Nov 2015 DateTime.current # => Tue, 24 Nov 2015 01:04:44 +0900
Ngày được lấy làm dấu thời gian là đầu ngày trong múi giờ của ứng dụng. Time.current trả về dấu thời gian, và Time.now tương đương của nó trong múi giờ hệ thống. Tương tự như vậy, Date.current trả về một ngày bằng đối số, và Date.today là ngày theo Time.now. (Lưu ý rằng bạn hiếm khi phải xử lí Time.now, hoặc Date.today, để tôn trọng múi giờ của ứng dụng, hãy luôn sử dụng Time.current và Date.current.)
Phương thức này cũng chấp nhận một block, nó sẽ trả về thời gian ban đầu ở cuối block:
Time.current # => Tue, 24 Nov 2015 01:04:44 JST +09:00 travel_to Time.zone.local(2015, 11, 24, 01, 04, 44) do Time.current # => Tue, 24 Nov 2015 01:04:44 JST +09:00 end Time.current # => Tue, 23 Jan 2018 22:27:42 JST +09:00
Ứng dụng trong Rspec
Tưởng tượng rằng bạn phải thống kê số like của người dùng trong ngày hôm qua, bạn viết RSpec như sau:
require "rails_helper" describe "#create" do before do travel_to("2017-01-18 10:00:00") user.like.create end context "when user liked" do it "should create stats of today like" do travel_to("2017-01-19 10:00:00") expect(StatsOfLike.on_yesterday.size).to eq 1 end end end
Khi bạn chạy test của bạn, bạn nhận đc thông báo lỗi method_missing: undefined method travel_back for RSpec::ExampleGroups. Làm thế nào để sửa lỗi này? Hãy include ActiveSupport::Testing::TimeHelpers vào phần test của bạn.
require "rails_helper" include ActiveSupport::Testing::TimeHelpers describe "#create" do before do travel_to("2017-01-18 10:00:00") user.like.create end context "when user liked" do it "should create stats of today like" do travel_to("2017-01-19 10:00:00") expect(StatsOfLike.on_yesterday.size).to eq 1 end end end
Một cách khác để thêm module này vào:
RSpec.configure do |config| .... config.include ActiveSupport::Testing::TimeHelpers .... end
Vậy là mình đã hoàn thành bài giới thiệu về module TimeHelpers, chúc các bạn viết test dễ dàng hơn với module này!