Time.now를 가짜로 만드는 방법?
Time.now단위 테스트에서 시간에 민감한 방법을 테스트 할 목적 으로 설정하는 가장 좋은 방법은 무엇입니까 ?
저는 Timecop 라이브러리를 정말 좋아합니다 . 시간 왜곡과 마찬가지로 블록 형식으로 시간 왜곡을 수행 할 수 있습니다.
Timecop.travel(6.days.ago) do
@model = TimeSensitiveMode.new
end
assert @model.times_up!
(예, 블록 형태의 시간 여행을 중첩 할 수 있습니다.)
선언적 시간 여행을 할 수도 있습니다.
class MyTest < Test::Unit::TestCase
def setup
Timecop.travel(...)
end
def teardown
Timecop.return
end
end
좀이 오이 타임 캅에 대한 도우미 여기를 . 다음과 같은 작업을 수행 할 수 있습니다.
Given it is currently January 24, 2008
And I go to the new post page
And I fill in "title" with "An old post"
And I fill in "body" with "..."
And I press "Submit"
And we jump in our Delorean and return to the present
When I go to the home page
I should not see "An old post"
개인적으로 나는 시계를 다음과 같이 주입 가능하게 만드는 것을 선호합니다.
def hello(clock=Time)
puts "the time is now: #{clock.now}"
end
또는:
class MyClass
attr_writer :clock
def initialize
@clock = Time
end
def hello
puts "the time is now: #{@clock.now}"
end
end
그러나 많은 사람들이 조롱 / 스터 빙 라이브러리를 선호합니다. RSpec / flexmock에서는 다음을 사용할 수 있습니다.
Time.stub!(:now).and_return(Time.mktime(1970,1,1))
또는 Mocha에서 :
Time.stubs(:now).returns(Time.mktime(1970,1,1))
저는 RSpec을 사용하고 있는데 Time.now를 호출하기 전에 Time.stub! (: now) .and_return (2.days.ago) 을했습니다. 그런 식으로 특정 테스트 케이스에 사용한 시간을 제어 할 수 있습니다.
Rspec 3.2를 사용하여 Time.now 반환 값을 가짜로 찾은 유일한 방법은 다음과 같습니다.
now = Time.parse("1969-07-20 20:17:40")
allow(Time).to receive(:now) { now }
이제 Time.now는 항상 Apollo 11이 달에 착륙 한 날짜를 반환합니다.
출처 : https://www.relishapp.com/rspec/rspec-mocks/docs
할 일 타임 워프
시간 왜곡은 원하는 것을 수행하는 라이브러리입니다. 그것은 당신에게 시간과 블록이 걸리는 방법을 제공하며 블록에서 일어나는 모든 일은 가짜 시간을 사용합니다.
pretend_now_is(2000,"jan",1,0) do
Time.now
end
Time클래스 객체를 참조하는 상수 일뿐 임을 잊지 마십시오 . 기꺼이 경고를하고 싶다면 언제든지 할 수 있습니다.
real_time_class = Time
Time = FakeTimeClass
# run test
Time = real_time_class
또한 이 의견을 넣은 이 질문을 참조하십시오 .
당신이 무엇을 비교하는지에 따라 Time.now, 때로는 동일한 목표를 달성하거나 동일한 기능을 테스트하기 위해 조명기를 변경할 수 있습니다. 예를 들어, 어떤 날짜가 미래에있을 경우 한 가지 일이 발생하고 과거 일 경우 다른 일이 발생해야하는 상황이있었습니다. 내가 할 수 있었던 것은 내 비품에 루비 (erb)를 포함하는 것입니다.
future:
comparing_date: <%= Time.now + 10.years %>
...
past:
comparing_date: <%= Time.now - 10.years %>
...
그런 다음 테스트에서와 관련된 시간을 기준으로 다양한 기능 또는 작업을 테스트하는 데 사용할 항목을 선택합니다 Time.now.
같은 문제가 발생하면 특정 날짜와 시간에 대한 사양에 대한 시간을 가짜로 만들어야했습니다.
Time.stub!(:now).and_return(Time.mktime(2014,10,22,5,35,28))
이것은 당신에게 줄 것입니다 :
2014-10-22 05:35:28 -0700
ActiveSupport가 포함 된 경우 다음을 사용할 수 있습니다.
travel_to Time.zone.parse('2010-07-05 08:00')
http://api.rubyonrails.org/classes/ActiveSupport/Testing/TimeHelpers.html
이런 종류의 작동하고 중첩을 허용합니다.
class Time
class << self
attr_accessor :stack, :depth
end
def self.warp(time)
Time.stack ||= []
Time.depth ||= -1
Time.depth += 1
Time.stack.push time
if Time.depth == 0
class << self
alias_method :real_now, :now
alias_method :real_new, :new
define_method :now do
stack[depth]
end
define_method :new do
now
end
end
end
yield
Time.depth -= 1
Time.stack.pop
class << self
if Time.depth < 0
alias_method :new, :real_new
alias_method :now, :real_now
remove_method :real_new
remove_method :real_now
end
end
end
end
It could be slightly improved by undefing the stack and depth accessors at the end
Usage:
time1 = 2.days.ago
time2 = 5.months.ago
Time.warp(time1) do
Time.real_now.should_not == Time.now
Time.now.should == time1
Time.warp(time2) do
Time.now.should == time2
end
Time.now.should == time1
end
Time.now.should_not == time1
Time.now.should_not be_nil
Depending upon what you are comparing Time.now to, sometimes you can change your fixtures to accomplish the same goal or test the same feature. For example, I had a situation where I needed one thing to happen if some date was in the future and another to happen if it was in the past. What I was able to do was include in my fixtures some embedded ruby (erb):
future:
comparing_date: <%= Time.now + 10.years %>
...
past:
comparing_date: <%= Time.now - 10.years %>
...
Then in your tests then you choose which one to use to test the different features or actions based upon the time relative to Time.now.
i just have this in my test file:
def time_right_now
current_time = Time.parse("07/09/10 14:20")
current_time = convert_time_to_utc(current_date)
return current_time
end
and in my Time_helper.rb file i have a
def time_right_now
current_time= Time.new
return current_time
end
so when testing the time_right_now is overwritten to use what ever time you want it to be.
I allways extract Time.now into a separate method that I turn into attr_accessor in the mock.
The recently-released Test::Redef makes this and other fakery easy, even without restructuring the code in a dependency-injection style (especially helpful if you're using other peoples' code.)
fake_time = Time.at(12345) # ~3:30pm UTC Jan 1 1970
Test::Redef.rd 'Time.now' => proc { fake_time } do
assert_equal 12345, Time.now.to_i
end
However, be careful of other ways to obtain time that this will not fake out (Date.new, a compiled extension that makes its own system call, interfaces to things like external database servers which know current timestamps, etc.) It sounds like the Timecop library above might overcome these limitations.
Other great uses include testing things like "what happens when I'm trying to use this friendly http client but it decides to raise this an exception instead of returning me a string?" without actually setting up the network conditions which lead to that exception (which may be tricky). It also lets you check the arguments to redef'd functions.
참고URL : https://stackoverflow.com/questions/1215245/how-to-fake-time-now
'Program Club' 카테고리의 다른 글
| DataFrame pandas에서 날짜 사이의 일 수가있는 열 추가 (0) | 2020.10.31 |
|---|---|
| Swift의 사전에서 키 값을 어떻게 얻을 수 있습니까? (0) | 2020.10.31 |
| iOS 프로그래밍에서 xib 파일 대신 스토리 보드를 사용하면 어떤 이점이 있습니까? (0) | 2020.10.31 |
| '클릭'및 '입력'시 이벤트 트리거 (0) | 2020.10.31 |
| Dictionary.Add 대 Dictionary [key] = value의 차이 (0) | 2020.10.31 |